aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/objects
diff options
context:
space:
mode:
authorattila <none@none>2014-08-20 10:26:01 +0200
committerattila <none@none>2014-08-20 10:26:01 +0200
commit1a6dc8268c841b348bd97c07e739ecd871ce15a4 (patch)
tree6e361a5ea5259a0bc7eeea0bbe727e74187d418a /src/jdk/nashorn/internal/objects
parent0b6e5c2050ccc3aac8dfcbd8f0daa9e707cf1093 (diff)
8027043: Turn global accesses into MethodHandle.constant, with one chance of reassignment, e.g. x = value occuring once in the global scope is ok, twice is not.
8027958: NASHORN TEST: Create tests to test markdown javascript engine work with Nashorn 8028345: Remove nashorn repo "bin" scripts to avoid confusion with JDK bin launcher programs 8029090: Developers should be able to pass nashorn properties and enable/disable JFR from command line 8030169: Need regression test for bug JDK-8010731 8033105: Make sure Nashorn test harness can run zlib benchmark 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation. 8035820: Optimistic recompilation 8035836: Array performance improvements 8036127: Prototype filter needs to be applied to getter guard as well, not just getter 8036986: Test should check that correctly type is returned running with optimistic. If optimistic assumption was wrong we should get the right one. 8037086: Check that deoptimizing recompilations are correct 8037177: -Dnashorn.optimistic should be enabled by default, meaning that it has to be explicitly set to false to run with the jdk 8 style conservative types 8037534: Use scope types to determine optimistic types 8037572: Add more test cases to check static types 8037967: Broke the build, by commiting without saving the last review comment 8038223: Symbol trace debug output takes time 8038396: fix for the compiler expression evaluator to be more inquisitive about types 8038398: OptimisticRecompilationTest fails on staging repo nashorn/jdk9/nashorn due to test framework 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output. 8038413: NPE in unboxInteger 8038416: Access to undefined scoped variables deoptimized too much 8038426: Move all loggers from process wide scope into Global scope 8038799: Guard and unbox boxed primitives types on setting them in Properties to avoid megamorphisism 8038945: Simplify strict undefined checks 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects. 8040024: BranchOptimizer produces bad code for NaN FP comparison 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back 8040093: Make sure that optimistic splitting works in optimistic types 8040102: Remove all references to Unsafe and definition of anonymous clases from the code 8040655: When processing a RewriteException debug object, the return value has already been reset to null. We need to catch this value before that. 8041434: Add synchronization to the common global constants structure 8041625: AccessorProperty currentType must only by Object.class when non-primitive, and scoping followup problem for lazily generated with bodies 8041905: Fix apply2call bug that prevented avatar.js unit tests from running correctly 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes 8042118: Separate types from symbols 8043002: Improve performance of Nashorn equality operators 8043003: Use strongly referenced generic invokers 8043004: Reduce variability at JavaAdapter call sites 8043132: Nashorn : all tests failed with java.security.AccessControlException 8043133: Fix corner cases of JDK-8041995 8043137: Collapse long sequences of NOP in Nashorn bytecode output 8043232: Index selection of overloaded java new constructors 8043235: Type-based optimizations interfere with continuation methods 8043431: Fix yet another corner case of JDK-8041995 8043504: Octane test harness was missing argument to print_always at one callsite, causing erroneous logging 8043605: Enable history for empty property maps 8043608: Make equality tests inline better 8043611: Move timing dependent benchmark for apply2call specialization to currently_failing. It is dependent that nothing takes machine time when doing the two runs, causing spurious assertions. Suggest running octane.raytrace manually instead to verify that this works, or incorporating it in the nightly test suite 8043632: Parallelize class installation and various script fixes. 8043633: In order to remove global state outside of contexts, make sure Timing class is an instance and not a static global collection of data. Move into Context. Move -Dnashorn.timing to an official logging option. 8043956: Make code caching work with optimistic typing and lazy compilation 8044012: Integrate the latest best known performance flags int ant octane jobs, and make sure that it's easy to compare 'ant octane-nashorn' and 'ant octane-v8' at the push of a button. (or rather; the entry of a command line) 8044102: Ensure bechmark exclude list for Octane benchmarks is in only one place, project.properties, and fix benchmark harness 8044154: Nashorn : all tests failed with java.security.AccessControlException 8044171: Make optimistic exception handlers smaller 8044502: Get rid of global optimistic flag 8044518: Ensure exceptions related to optimistic recompilation are not serializable 8044533: Deoptimizing negation produces wrong result for zero 8044534: Constant folding for unary + should produce int for boolean literals 8044760: Avoid PropertyMap duplicate for global instances 8044786: Some tests fail with non-optimistic compilation 8044803: Unnecessary restOf check 8044816: On-demand compiled top-level program doesn't need :createProgramFunction 8044851: nashorn properties leak memory 8046013: TypeError: Cannot apply "with" to non script object 8046014: MultiGlobalCompiledScript should cache :createProgramFunction handle 8046025: AccessorProperty.getGetter is not threadsafe 8046026: CompiledFunction.relinkComposableInvoker assert is being hit 8046201: Avoid repeated flattening of nested ConsStrings 8046215: Running uncompilable scripts throws NullPointerException 8046898: Make sure that lazy compilation is the default, remove redundant "enable lazy compilation" flags, added warning message if compile logging is enabled and lazy is switched off. Verified existing test suite code coverage equivalence between lazy and eager. 8046905: apply on apply is broken 8046921: Deoptimization type information peristence 8047035: (function() "hello")() crashes in Lexer with jdk9 8047057: Add a regression test for the passing test cases from JDK-8042304 8047067: all eval arguments need to be copied in Lower 8047078: Fuzzing bug discovered when ArrayLiteralNodes weren't immutable 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator 8047331: Assertion in CompiledFunction when running earley-boyer after Merge 8047357: More precise synthetic return + unreachable throw 8047359: large string size RangeError should be thrown rather than reporting negative length 8047369: Add regression tests for passing test cases of JDK-8024971 8047371: local variable declaration in TypeEvaluator should use ScriptObject.addOwnProperty instead of .set 8047728: (function(x){var o={x:0}; with(o){delete x} return o.x})() evaluates to 0 instead of undefined 8047959: bindings created for declarations in eval code are not mutable 8048009: Type info caching accidentally defeated 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval 8048079: Persistent code store is broken after optimistic types merge 8048505: ScriptingFunctions.readFully couldn't handle file names represented as ConsStrings 8048586: String concatenation with optimistic types is slow 8048718: JSON.parse('{"0":0, "64":0}') throws ArrayindexOutOfBoundsException 8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes 8049086: Minor API convenience functions on "Java" object 8049222: JSType class exposes public mutable arrays 8049223: RewriteException class exposes public mutable arrays 8049242: Explicit constructor overload selection should work with StaticClass as well 8049318: Test hideLocationProperties.js fails on Window due to backslash in path 8049524: Global object initialization via javax.script API should be minimal 8050432: javax.script.filename variable should not be enumerable with nashorn engine's ENGINE_SCOPE bindings 8050964: OptimisticTypesPersistence.java should use java.util.Date instead of java.sql.Date 8051019: Separate src and test execution sandbox directories 8051346: Test262 tests for ECMAScript 5 now in branch "es5-tests" 8051439: Wrong type calculated for ADD operator with undefined operand 8051839: GuardedInvocation needs to clone an argument 8053908: jdeps is not PATH on Mac, results in ant clean test failure on Mac 8053910: ScriptObjectMirror causing havoc with Invocation interface 8053913: Auto format caused warning in CompositeTypeBasedGuardingDynamicLinker 8054223: Nashorn: AssertionError when use __DIR__ and ScriptEngine.eval() 8054411: Add nashorn.args.prepend system property 8054503: test/script/external/test262/test/suite/ch12/12.6/12.6.4/12.6.4-2.js fails with tip 8054651: Global.initConstructor and ScriptFunction.getPrototype(Object) can have stricter types 8054898: Avoid creation of empty type info files 8054993: type info cache may be disabled for test262 and tests explicitly changing that property should use @fork 8055034: jjs exits interactive mode if exception was thrown when trying to print value of last evaluated expression 8055042: Compile-time expression evaluator was missing variables 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally 8055139: test/script/trusted/JDK-8055107.js fails with access control exception 8055186: Backport Nashorn optimistic typing to 8u repository 8055529: Clean up the bin directory Reviewed-by: jlaskey, lagergren, sundar Contributed-by: marcus.largergren@oracle.com, hannes.wallnoefer@oracle.com, sundararajan.athijegannathan@oracle.com --HG-- rename : test/script/basic/arraysIntKey.js => test/script/basic/arrays_int_key.js rename : test/script/basic/arraysIntKey.js.EXPECTED => test/script/basic/arrays_int_key.js.EXPECTED rename : test/script/basic/runsunspider-lazy.js.EXPECTED => test/script/basic/runsunspider.js.EXPECTED rename : test/script/basic/JDK-8010697.js.EXPECTED => test/script/currently-failing/JDK-8010697.js.EXPECTED rename : test/script/maptests/property_delete.js => test/script/currently-failing/property_delete.js
Diffstat (limited to 'src/jdk/nashorn/internal/objects')
-rw-r--r--src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java5
-rw-r--r--src/jdk/nashorn/internal/objects/ArrayBufferView.java328
-rw-r--r--src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java5
-rw-r--r--src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java5
-rw-r--r--src/jdk/nashorn/internal/objects/Global.java427
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArray.java306
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArrayBuffer.java153
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDataView.java202
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDate.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDebug.java174
-rw-r--r--src/jdk/nashorn/internal/objects/NativeError.java38
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFloat32Array.java116
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFloat64Array.java126
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFunction.java89
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt16Array.java109
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt32Array.java112
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt8Array.java101
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJSAdapter.java73
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJava.java69
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJavaImporter.java11
-rw-r--r--src/jdk/nashorn/internal/objects/NativeMath.java28
-rw-r--r--src/jdk/nashorn/internal/objects/NativeNumber.java70
-rw-r--r--src/jdk/nashorn/internal/objects/NativeObject.java71
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRegExp.java38
-rw-r--r--src/jdk/nashorn/internal/objects/NativeStrictArguments.java5
-rw-r--r--src/jdk/nashorn/internal/objects/NativeString.java182
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint16Array.java114
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint32Array.java122
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint8Array.java108
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java160
-rw-r--r--src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java44
-rw-r--r--src/jdk/nashorn/internal/objects/annotations/Optimistic.java62
-rw-r--r--src/jdk/nashorn/internal/objects/annotations/Property.java4
33 files changed, 2376 insertions, 1083 deletions
diff --git a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
index e39c5217..0e8ed350 100644
--- a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
@@ -209,6 +209,11 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr
}
@Override
+ public String toString() {
+ return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + " getter=" + get + " setter=" + set + "}]";
+ }
+
+ @Override
public int hashCode() {
int hash = 7;
hash = 41 * hash + Objects.hashCode(this.configurable);
diff --git a/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index c29af851..445dc19c 100644
--- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -26,7 +26,14 @@
package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
-
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -35,33 +42,46 @@ import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
@ScriptClass("ArrayBufferView")
abstract class ArrayBufferView extends ScriptObject {
+ private final NativeArrayBuffer buffer;
+ private final int byteOffset;
// initialized by nasgen
private static PropertyMap $nasgenmap$;
private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) {
super($nasgenmap$);
- checkConstructorArgs(buffer, byteOffset, elementLength);
- this.setProto(getPrototype(global));
- this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
+
+ final int bytesPerElement = bytesPerElement();
+
+ checkConstructorArgs(buffer.getByteLength(), bytesPerElement, byteOffset, elementLength);
+ setProto(getPrototype(global));
+
+ this.buffer = buffer;
+ this.byteOffset = byteOffset;
+
+ assert byteOffset % bytesPerElement == 0;
+ final int start = byteOffset / bytesPerElement;
+ final ByteBuffer newNioBuffer = buffer.getNioBuffer().duplicate().order(ByteOrder.nativeOrder());
+ final ArrayData data = factory().createArrayData(newNioBuffer, start, start + elementLength);
+
+ setArray(data);
}
- ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
+ protected ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
this(buffer, byteOffset, elementLength, Global.instance());
}
- private void checkConstructorArgs(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
+ private static void checkConstructorArgs(final int byteLength, final int bytesPerElement, final int byteOffset, final int elementLength) {
if (byteOffset < 0 || elementLength < 0) {
- throw new RuntimeException("byteOffset or length must not be negative");
- }
- if (byteOffset + elementLength * bytesPerElement() > buffer.getByteLength()) {
- throw new RuntimeException("byteOffset + byteLength out of range");
- }
- if (byteOffset % bytesPerElement() != 0) {
- throw new RuntimeException("byteOffset must be a multiple of the element size");
+ throw new RuntimeException("byteOffset or length must not be negative, byteOffset=" + byteOffset + ", elementLength=" + elementLength + ", bytesPerElement=" + bytesPerElement);
+ } else if (byteOffset + elementLength * bytesPerElement > byteLength) {
+ throw new RuntimeException("byteOffset + byteLength out of range, byteOffset=" + byteOffset + ", elementLength=" + elementLength + ", bytesPerElement=" + bytesPerElement);
+ } else if (byteOffset % bytesPerElement != 0) {
+ throw new RuntimeException("byteOffset must be a multiple of the element size, byteOffset=" + byteOffset + " bytesPerElement=" + bytesPerElement);
}
}
@@ -71,22 +91,22 @@ abstract class ArrayBufferView extends ScriptObject {
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
public static Object buffer(final Object self) {
- return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).buffer;
+ return ((ArrayBufferView)self).buffer;
}
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object byteOffset(final Object self) {
- return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).byteOffset;
+ public static int byteOffset(final Object self) {
+ return ((ArrayBufferView)self).byteOffset;
}
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object byteLength(final Object self) {
+ public static int byteLength(final Object self) {
final ArrayBufferView view = (ArrayBufferView)self;
- return ((ArrayDataImpl)view.getArray()).elementLength * view.bytesPerElement();
+ return ((TypedArrayData<?>)view.getArray()).getElementLength() * view.bytesPerElement();
}
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object length(final Object self) {
+ public static int length(final Object self) {
return ((ArrayBufferView)self).elementLength();
}
@@ -96,182 +116,7 @@ abstract class ArrayBufferView extends ScriptObject {
}
private int elementLength() {
- return ((ArrayDataImpl)getArray()).elementLength;
- }
-
- protected static abstract class ArrayDataImpl extends ArrayData {
- protected final NativeArrayBuffer buffer;
- protected final int byteOffset;
- private final int elementLength;
-
- protected ArrayDataImpl(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(elementLength);
- this.buffer = buffer;
- this.byteOffset = byteOffset;
- this.elementLength = elementLength;
- }
-
- @Override
- public ArrayData copy() {
- throw new UnsupportedOperationException(); // Not used for ArrayBuffers
- }
-
- @Override
- public Object[] asObjectArray() {
- final Object[] array = new Object[elementLength];
- for (int i = 0; i < elementLength; i++) {
- array[i] = getObjectImpl(i);
- }
- return array;
- }
-
- @Override
- public ArrayData ensure(final long safeIndex) {
- return this;
- }
-
- @Override
- public void setLength(final long length) {
- //empty?
- //TODO is this right?
- }
-
- @Override
- public ArrayData shrink(final long newLength) {
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final Object value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final int value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final double value, final boolean strict) {
- if (has(index)) {
- setImpl(index, value);
- }
- return this;
- }
-
- @Override
- public int getInt(final int index) {
- return getIntImpl(index);
- }
-
- @Override
- public long getLong(final int index) {
- return getLongImpl(index);
- }
-
- @Override
- public double getDouble(final int index) {
- return getDoubleImpl(index);
- }
-
- @Override
- public Object getObject(final int index) {
- return getObjectImpl(index);
- }
-
- @Override
- public boolean has(final int index) {
- return index >= 0 && index < elementLength;
- }
-
- @Override
- public boolean canDelete(final int index, final boolean strict) {
- return false;
- }
-
- @Override
- public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
- return false;
- }
-
- @Override
- public ArrayData delete(final int index) {
- return this;
- }
-
- @Override
- public ArrayData delete(final long fromIndex, final long toIndex) {
- return this;
- }
-
- @Override
- protected ArrayData convert(final Class<?> type) {
- return this;
- }
-
- @Override
- public void shiftLeft(final int by) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ArrayData shiftRight(final int by) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Object pop() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ArrayData slice(final long from, final long to) {
- throw new UnsupportedOperationException();
- }
-
- protected abstract int getIntImpl(int key);
-
- protected long getLongImpl(final int key) {
- return getIntImpl(key);
- }
-
- protected double getDoubleImpl(final int key) {
- return getIntImpl(key);
- }
-
- protected Object getObjectImpl(final int key) {
- return getIntImpl(key);
- }
-
- protected abstract void setImpl(int key, int value);
-
- protected void setImpl(final int key, final long value) {
- setImpl(key, (int)value);
- }
-
- protected void setImpl(final int key, final double value) {
- setImpl(key, JSType.toInt32(value));
- }
-
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toInt32(value));
- }
-
- protected abstract int byteIndex(int index);
+ return ((TypedArrayData<?>)getArray()).getElementLength();
}
protected static abstract class Factory {
@@ -279,12 +124,12 @@ abstract class ArrayBufferView extends ScriptObject {
final int maxElementLength;
public Factory(final int bytesPerElement) {
- this.bytesPerElement = bytesPerElement;
+ this.bytesPerElement = bytesPerElement;
this.maxElementLength = Integer.MAX_VALUE / bytesPerElement;
}
public final ArrayBufferView construct(final int elementLength) {
- if(elementLength > maxElementLength) {
+ if (elementLength > maxElementLength) {
throw rangeError("inappropriate.array.buffer.length", JSType.toString(elementLength));
}
return construct(new NativeArrayBuffer(elementLength * bytesPerElement), 0, elementLength);
@@ -292,25 +137,39 @@ abstract class ArrayBufferView extends ScriptObject {
public abstract ArrayBufferView construct(NativeArrayBuffer buffer, int byteOffset, int elementLength);
- public abstract ArrayData createArrayData(NativeArrayBuffer buffer, int byteOffset, int elementLength);
+ public abstract TypedArrayData<?> createArrayData(ByteBuffer nb, int start, int end);
+
+ public abstract String getClassName();
}
protected abstract Factory factory();
protected abstract ScriptObject getPrototype(final Global global);
+ @Override
+ public final String getClassName() {
+ return factory().getClassName();
+ }
+
protected boolean isFloatArray() {
return false;
}
- protected static ArrayBufferView constructorImpl(final Object[] args, final Factory factory) {
- final Object arg0 = args.length != 0 ? args[0] : 0;
- final ArrayBufferView dst;
- final int length;
+ protected static ArrayBufferView constructorImpl(final boolean newObj, final Object[] args, final Factory factory) {
+ final Object arg0 = args.length != 0 ? args[0] : 0;
+ final ArrayBufferView dest;
+ final int length;
+
+ if (!newObj) {
+ throw typeError("constructor.requires.new", factory.getClassName());
+ }
+
+
if (arg0 instanceof NativeArrayBuffer) {
// Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length)
- final NativeArrayBuffer buffer = (NativeArrayBuffer) arg0;
- final int byteOffset = args.length > 1 ? JSType.toInt32(args[1]) : 0;
+ final NativeArrayBuffer buffer = (NativeArrayBuffer)arg0;
+ final int byteOffset = args.length > 1 ? JSType.toInt32(args[1]) : 0;
+
if (args.length > 2) {
length = JSType.toInt32(args[2]);
} else {
@@ -319,27 +178,30 @@ abstract class ArrayBufferView extends ScriptObject {
}
length = (buffer.getByteLength() - byteOffset) / factory.bytesPerElement;
}
+
return factory.construct(buffer, byteOffset, length);
} else if (arg0 instanceof ArrayBufferView) {
// Constructor(TypedArray array)
length = ((ArrayBufferView)arg0).elementLength();
- dst = factory.construct(length);
+ dest = factory.construct(length);
} else if (arg0 instanceof NativeArray) {
// Constructor(type[] array)
length = lengthToInt(((NativeArray) arg0).getArray().length());
- dst = factory.construct(length);
+ dest = factory.construct(length);
} else {
- // Constructor(unsigned long length)
- length = lengthToInt(JSType.toInt64(arg0));
+ // Constructor(unsigned long length). Treating infinity as 0 is a special case for ArrayBufferView.
+ final double dlen = JSType.toNumber(arg0);
+ length = lengthToInt(Double.isInfinite(dlen) ? 0L : JSType.toLong(dlen));
return factory.construct(length);
}
- copyElements(dst, length, (ScriptObject)arg0, 0);
- return dst;
+ copyElements(dest, length, (ScriptObject)arg0, 0);
+
+ return dest;
}
protected static Object setImpl(final Object self, final Object array, final Object offset0) {
- final ArrayBufferView dest = ((ArrayBufferView)self);
+ final ArrayBufferView dest = (ArrayBufferView)self;
final int length;
if (array instanceof ArrayBufferView) {
// void set(TypedArray array, optional unsigned long offset)
@@ -351,7 +213,7 @@ abstract class ArrayBufferView extends ScriptObject {
throw new RuntimeException("argument is not of array type");
}
- final ScriptObject source = (ScriptObject) array;
+ final ScriptObject source = (ScriptObject)array;
final int offset = JSType.toInt32(offset0); // default=0
if (dest.elementLength() < length + offset || offset < 0) {
@@ -366,11 +228,11 @@ abstract class ArrayBufferView extends ScriptObject {
private static void copyElements(final ArrayBufferView dest, final int length, final ScriptObject source, final int offset) {
if (!dest.isFloatArray()) {
for (int i = 0, j = offset; i < length; i++, j++) {
- dest.set(j, source.getInt(i), false);
+ dest.set(j, source.getInt(i, INVALID_PROGRAM_POINT), false);
}
} else {
for (int i = 0, j = offset; i < length; i++, j++) {
- dest.set(j, source.getDouble(i), false);
+ dest.set(j, source.getDouble(i, INVALID_PROGRAM_POINT), false);
}
}
}
@@ -379,15 +241,39 @@ abstract class ArrayBufferView extends ScriptObject {
if (length > Integer.MAX_VALUE || length < 0) {
throw rangeError("inappropriate.array.buffer.length", JSType.toString(length));
}
- return (int) (length & Integer.MAX_VALUE);
+ return (int)(length & Integer.MAX_VALUE);
}
protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) {
- final ArrayBufferView arrayView = ((ArrayBufferView)self);
- final int elementLength = arrayView.elementLength();
- final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
- final int end = NativeArrayBuffer.adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : elementLength, elementLength);
- final ArrayDataImpl arrayData = (ArrayDataImpl)arrayView.getArray();
- return arrayView.factory().construct(arrayData.buffer, arrayData.byteIndex(begin), Math.max(end - begin, 0));
+ final ArrayBufferView arrayView = (ArrayBufferView)self;
+ final int byteOffset = arrayView.byteOffset;
+ final int bytesPerElement = arrayView.bytesPerElement();
+ final int elementLength = arrayView.elementLength();
+ final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
+ final int end = NativeArrayBuffer.adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : elementLength, elementLength);
+ final int length = Math.max(end - begin, 0);
+
+ assert byteOffset % bytesPerElement == 0;
+
+ //second is byteoffset
+ return arrayView.factory().construct(arrayView.buffer, begin * bytesPerElement + byteOffset, length);
+ }
+
+ @Override
+ protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastGetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findGetIndexMethod(desc, request);
+ }
+
+ @Override
+ protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastSetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findSetIndexMethod(desc, request);
}
}
diff --git a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
index e117c7ed..24722930 100644
--- a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
@@ -197,6 +197,11 @@ public final class DataPropertyDescriptor extends ScriptObject implements Proper
}
@Override
+ public String toString() {
+ return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + " writable=" + writable + " value=" + value + "}]";
+ }
+
+ @Override
public int hashCode() {
int hash = 5;
hash = 43 * hash + Objects.hashCode(this.configurable);
diff --git a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
index 19cc8b6f..39d0b3ec 100644
--- a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
@@ -176,6 +176,11 @@ public final class GenericPropertyDescriptor extends ScriptObject implements Pro
}
@Override
+ public String toString() {
+ return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + "}]";
+ }
+
+ @Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + Objects.hashCode(this.configurable);
diff --git a/src/jdk/nashorn/internal/objects/Global.java b/src/jdk/nashorn/internal/objects/Global.java
index 139d1520..d8f23b1f 100644
--- a/src/jdk/nashorn/internal/objects/Global.java
+++ b/src/jdk/nashorn/internal/objects/Global.java
@@ -25,28 +25,41 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
import java.lang.reflect.Field;
import java.util.Arrays;
-import java.util.List;
+import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.codegen.ApplySpecialization;
+import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.GlobalConstants;
import jdk.nashorn.internal.runtime.GlobalFunctions;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
@@ -55,7 +68,6 @@ import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
@@ -70,9 +82,39 @@ import jdk.nashorn.internal.scripts.JO;
*/
@ScriptClass("Global")
public final class Global extends ScriptObject implements Scope {
+ // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
+ private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
+ /**
+ * Optimistic builtin names that require switchpoint invalidation
+ * upon assignment. Overly conservative, but works for now, to avoid
+ * any complicated scope checks and especially heavy weight guards
+ * like
+ *
+ * <pre>
+ * public boolean setterGuard(final Object receiver) {
+ * final Global global = Global.instance();
+ * final ScriptObject sobj = global.getFunctionPrototype();
+ * final Object apply = sobj.get("apply");
+ * return apply == receiver;
+ * }
+ * </pre>
+ *
+ * Naturally, checking for builtin classes like NativeFunction is cheaper,
+ * it's when you start adding property checks for said builtins you have
+ * problems with guard speed.
+ */
+ public final Map<String, SwitchPoint> optimisticFunctionMap;
+
+ /** Name invalidator for things like call/apply */
+ public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+
+ /** Nashorn extension: arguments array */
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
+ public Object arguments;
+
/** ECMA 15.1.2.2 parseInt (string , radix) */
@Property(attributes = Attribute.NOT_ENUMERABLE)
public Object parseInt;
@@ -135,11 +177,11 @@ public final class Global extends ScriptObject implements Scope {
/** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public final Object NaN = Double.NaN;
+ public final double NaN = Double.NaN;
/** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public final Object Infinity = Double.POSITIVE_INFINITY;
+ public final double Infinity = Double.POSITIVE_INFINITY;
/** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
@@ -303,15 +345,15 @@ public final class Global extends ScriptObject implements Scope {
/** Nashorn extension: current script's file name */
@Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public Object __FILE__;
+ public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
/** Nashorn extension: current script's directory */
@Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public Object __DIR__;
+ public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
/** Nashorn extension: current source line number being executed */
@Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
- public Object __LINE__;
+ public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
/** Used as Date.prototype's default value */
public NativeDate DEFAULT_DATE;
@@ -352,19 +394,19 @@ public final class Global extends ScriptObject implements Scope {
private ScriptObject builtinJavafx;
private ScriptObject builtinJavax;
private ScriptObject builtinOrg;
- private ScriptObject builtinJavaImporter;
+ private ScriptFunction builtinJavaImporter;
private ScriptObject builtinJavaApi;
- private ScriptObject builtinArrayBuffer;
- private ScriptObject builtinDataView;
- private ScriptObject builtinInt8Array;
- private ScriptObject builtinUint8Array;
- private ScriptObject builtinUint8ClampedArray;
- private ScriptObject builtinInt16Array;
- private ScriptObject builtinUint16Array;
- private ScriptObject builtinInt32Array;
- private ScriptObject builtinUint32Array;
- private ScriptObject builtinFloat32Array;
- private ScriptObject builtinFloat64Array;
+ private ScriptFunction builtinArrayBuffer;
+ private ScriptFunction builtinDataView;
+ private ScriptFunction builtinInt8Array;
+ private ScriptFunction builtinUint8Array;
+ private ScriptFunction builtinUint8ClampedArray;
+ private ScriptFunction builtinInt16Array;
+ private ScriptFunction builtinUint16Array;
+ private ScriptFunction builtinInt32Array;
+ private ScriptFunction builtinUint32Array;
+ private ScriptFunction builtinFloat32Array;
+ private ScriptFunction builtinFloat64Array;
/*
* ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
@@ -377,12 +419,16 @@ public final class Global extends ScriptObject implements Scope {
// Used to store the last RegExp result to support deprecated RegExp constructor properties
private RegExpResult lastRegExpResult;
- private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
- private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
- private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
- private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
- private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
- private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
+ private static final MethodHandle EVAL = findOwnMH_S("eval", Object.class, Object.class, Object.class);
+ private static final MethodHandle NO_SUCH_PROPERTY = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
+ private static final MethodHandle PRINT = findOwnMH_S("print", Object.class, Object.class, Object[].class);
+ private static final MethodHandle PRINTLN = findOwnMH_S("println", Object.class, Object.class, Object[].class);
+ private static final MethodHandle LOAD = findOwnMH_S("load", Object.class, Object.class, Object.class);
+ private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
+ private static final MethodHandle EXIT = findOwnMH_S("exit", Object.class, Object.class, Object.class);
+
+ /** Invalidate a reserved name, such as "apply" or "call" if assigned */
+ public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this);
// initialized by nasgen
private static PropertyMap $nasgenmap$;
@@ -390,6 +436,23 @@ public final class Global extends ScriptObject implements Scope {
// context to which this global belongs to
private final Context context;
+ // current ScriptContext to use - can be null.
+ private ScriptContext scontext;
+ // associated Property object for "context" property.
+ private jdk.nashorn.internal.runtime.Property scontextProperty;
+
+ /**
+ * Set the current script context
+ * @param scontext script context
+ */
+ public void setScriptContext(final ScriptContext scontext) {
+ this.scontext = scontext;
+ scontextProperty.setValue(this, this, scontext, false);
+ }
+
+ // global constants for this global - they can be replaced with MethodHandle.constant until invalidated
+ private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
+
@Override
protected Context getContext() {
return context;
@@ -407,12 +470,7 @@ public final class Global extends ScriptObject implements Scope {
// null check on context
context.getClass();
- /*
- * Duplicate global's map and use it. This way the initial Map filled
- * by nasgen (referenced from static field in this class) is retained
- * 'as is' (as that one is process wide singleton.
- */
- return $nasgenmap$.duplicate();
+ return $nasgenmap$;
}
/**
@@ -424,6 +482,12 @@ public final class Global extends ScriptObject implements Scope {
super(checkAndGetMap(context));
this.context = context;
this.setIsScope();
+ this.optimisticFunctionMap = new HashMap<>();
+ //we can only share one instance of Global constants between globals, or we consume way too much
+ //memory - this is good enough for most programs
+ while (gcsInstance.get() == null) {
+ gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class)));
+ }
}
/**
@@ -437,6 +501,27 @@ public final class Global extends ScriptObject implements Scope {
return global;
}
+ private static Global instanceFrom(final Object self) {
+ return self instanceof Global? (Global)self : instance();
+ }
+
+ /**
+ * Return the global constants map for fields that
+ * can be accessed as MethodHandle.constant
+ * @return constant map
+ */
+ public static GlobalConstants getConstants() {
+ return gcsInstance.get();
+ }
+
+ /**
+ * Check if we have a Global instance
+ * @return true if one exists
+ */
+ public static boolean hasInstance() {
+ return Context.getGlobal() != null;
+ }
+
/**
* Script access to {@link ScriptEnvironment}
*
@@ -478,28 +563,16 @@ public final class Global extends ScriptObject implements Scope {
* Initialize standard builtin objects like "Object", "Array", "Function" etc.
* as well as our extension builtin objects like "Java", "JSAdapter" as properties
* of the global scope object.
+ *
+ * @param engine ScriptEngine to initialize
*/
- public void initBuiltinObjects() {
+ public void initBuiltinObjects(final ScriptEngine engine) {
if (this.builtinObject != null) {
// already initialized, just return
return;
}
- init();
- }
-
- /**
- * Create a new ScriptFunction object
- *
- * @param name function name
- * @param handle invocation handle for function
- * @param scope the scope
- * @param strict are we in strict mode
- *
- * @return new script function
- */
- public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
- return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR);
+ init(engine);
}
/**
@@ -537,7 +610,7 @@ public final class Global extends ScriptObject implements Scope {
*
* @return guarded invocation
*/
- public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
+ public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
if (self instanceof String || self instanceof ConsString) {
return NativeString.lookupPrimitive(request, self);
} else if (self instanceof Number) {
@@ -729,6 +802,7 @@ public final class Global extends ScriptObject implements Scope {
* @param value of the data property
* @param configurable is the property configurable?
* @param enumerable is the property enumerable?
+ * @param writable is the property writable?
* @return newly created DataPropertyDescriptor object
*/
public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
@@ -758,7 +832,6 @@ public final class Global extends ScriptObject implements Scope {
return desc;
}
-
private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
final T obj = map.get(key);
if (obj != null) {
@@ -800,6 +873,32 @@ public final class Global extends ScriptObject implements Scope {
}
/**
+ * Hook to search missing variables in ScriptContext if available
+ * @param self used to detect if scope call or not (this function is 'strict')
+ * @param name name of the variable missing
+ * @return value of the missing variable or undefined (or TypeError for scope search)
+ */
+ public static Object __noSuchProperty__(final Object self, final Object name) {
+ final Global global = Global.instance();
+ final ScriptContext sctxt = global.scontext;
+ final String nameStr = name.toString();
+
+ if (sctxt != null) {
+ final int scope = sctxt.getAttributesScope(nameStr);
+ if (scope != -1) {
+ return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
+ }
+ }
+
+ if (self == UNDEFINED) {
+ // scope access and so throw ReferenceError
+ throw referenceError(global, "not.defined", nameStr);
+ }
+
+ return UNDEFINED;
+ }
+
+ /**
* This is the eval used when 'indirect' eval call is made.
*
* var global = this;
@@ -811,7 +910,7 @@ public final class Global extends ScriptObject implements Scope {
* @return the result of eval
*/
public static Object eval(final Object self, final Object str) {
- return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
+ return directEval(self, str, UNDEFINED, UNDEFINED, false);
}
/**
@@ -827,14 +926,14 @@ public final class Global extends ScriptObject implements Scope {
*
* This is directly invoked from generated when eval(code) is called in user code
*/
- public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
+ public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
if (!(str instanceof String || str instanceof ConsString)) {
return str;
}
- final Global global = Global.instance();
- final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
+ final Global global = Global.instanceFrom(self);
+ final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
- return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
+ return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
}
/**
@@ -846,7 +945,7 @@ public final class Global extends ScriptObject implements Scope {
* @return result of print (undefined)
*/
public static Object print(final Object self, final Object... objects) {
- return printImpl(false, objects);
+ return Global.instanceFrom(self).printImpl(false, objects);
}
/**
@@ -858,7 +957,7 @@ public final class Global extends ScriptObject implements Scope {
* @return result of println (undefined)
*/
public static Object println(final Object self, final Object... objects) {
- return printImpl(true, objects);
+ return Global.instanceFrom(self).printImpl(true, objects);
}
/**
@@ -872,8 +971,8 @@ public final class Global extends ScriptObject implements Scope {
* @throws IOException if source could not be read
*/
public static Object load(final Object self, final Object source) throws IOException {
- final Global global = Global.instance();
- final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
+ final Global global = Global.instanceFrom(self);
+ final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
return global.getContext().load(scope, source);
}
@@ -888,7 +987,7 @@ public final class Global extends ScriptObject implements Scope {
* @throws IOException if source could not be read
*/
public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
- final Global global = Global.instance();
+ final Global global = Global.instanceFrom(self);
final int length = args.length;
final boolean hasArgs = 0 < length;
final Object from = hasArgs ? args[0] : UNDEFINED;
@@ -903,7 +1002,7 @@ public final class Global extends ScriptObject implements Scope {
* @param self self reference
* @param code exit code
*
- * @return undefined (will never be reacheD)
+ * @return undefined (will never be reached)
*/
public static Object exit(final Object self, final Object code) {
System.exit(JSType.toInt32(code));
@@ -1457,6 +1556,26 @@ public final class Global extends ScriptObject implements Scope {
}
/**
+ * Called from generated to replace a location property placeholder with the actual location property value.
+ *
+ * @param placeholder the value tested for being a placeholder for a location property
+ * @param locationProperty the actual value for the location property
+ * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
+ */
+ public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
+ return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
+ }
+
+ /**
+ * Called from runtime internals to check if the passed value is a location property placeholder.
+ * @param placeholder the value tested for being a placeholder for a location property
+ * @return true if the value is a placeholder, false otherwise.
+ */
+ public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
+ return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
+ }
+
+ /**
* Create a new RegExp object.
*
* @param expression Regular expression.
@@ -1494,11 +1613,13 @@ public final class Global extends ScriptObject implements Scope {
* not the case
*
* @param obj and object to check
+ * @return the script object
*/
- public static void checkObject(final Object obj) {
+ public static ScriptObject checkObject(final Object obj) {
if (!(obj instanceof ScriptObject)) {
throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
}
+ return (ScriptObject)obj;
}
/**
@@ -1533,7 +1654,7 @@ public final class Global extends ScriptObject implements Scope {
splitState = state;
}
- private void init() {
+ private void init(final ScriptEngine engine) {
assert Context.getGlobal() == this : "this global is not set as current";
final ScriptEnvironment env = getContext().getEnv();
@@ -1547,7 +1668,8 @@ public final class Global extends ScriptObject implements Scope {
// initialize global function properties
this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
- this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT);
+ this.parseInt = ScriptFunctionImpl.makeFunction("parseInt", GlobalFunctions.PARSEINT,
+ new MethodHandle[] { GlobalFunctions.PARSEINT_OI, GlobalFunctions.PARSEINT_O });
this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
this.isNaN = ScriptFunctionImpl.makeFunction("isNaN", GlobalFunctions.IS_NAN);
this.isFinite = ScriptFunctionImpl.makeFunction("isFinite", GlobalFunctions.IS_FINITE);
@@ -1564,15 +1686,15 @@ public final class Global extends ScriptObject implements Scope {
this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
// built-in constructors
- this.builtinArray = (ScriptFunction)initConstructor("Array");
- this.builtinBoolean = (ScriptFunction)initConstructor("Boolean");
- this.builtinDate = (ScriptFunction)initConstructor("Date");
- this.builtinJSON = initConstructor("JSON");
- this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
- this.builtinMath = initConstructor("Math");
- this.builtinNumber = (ScriptFunction)initConstructor("Number");
- this.builtinRegExp = (ScriptFunction)initConstructor("RegExp");
- this.builtinString = (ScriptFunction)initConstructor("String");
+ this.builtinArray = initConstructor("Array", ScriptFunction.class);
+ this.builtinBoolean = initConstructor("Boolean", ScriptFunction.class);
+ this.builtinDate = initConstructor("Date", ScriptFunction.class);
+ this.builtinJSON = initConstructor("JSON", ScriptObject.class);
+ this.builtinJSAdapter = initConstructor("JSAdapter", ScriptFunction.class);
+ this.builtinMath = initConstructor("Math", ScriptObject.class);
+ this.builtinNumber = initConstructor("Number", ScriptFunction.class);
+ this.builtinRegExp = initConstructor("RegExp", ScriptFunction.class);
+ this.builtinString = initConstructor("String", ScriptFunction.class);
// initialize String.prototype.length to 0
// add String.prototype.length
@@ -1632,25 +1754,28 @@ public final class Global extends ScriptObject implements Scope {
copyBuiltins();
- // initialized with strings so that typeof will work as expected.
- this.__FILE__ = "";
- this.__DIR__ = "";
- this.__LINE__ = 0.0;
-
// expose script (command line) arguments as "arguments" property of global
- final List<String> arguments = env.getArguments();
- final Object argsObj = wrapAsObject(arguments.toArray());
-
- addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
+ arguments = wrapAsObject(env.getArguments().toArray());
if (env._scripting) {
// synonym for "arguments" in scripting mode
- addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
+ addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
+ }
+
+ if (engine != null) {
+ final int NOT_ENUMERABLE_NOT_CONFIG = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE;
+ scontextProperty = addOwnProperty("context", NOT_ENUMERABLE_NOT_CONFIG, null);
+ addOwnProperty("engine", NOT_ENUMERABLE_NOT_CONFIG, engine);
+ // default file name
+ addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
+ // __noSuchProperty__ hook for ScriptContext search of missing variables
+ final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
+ addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
}
}
private void initErrorObjects() {
// Error objects
- this.builtinError = (ScriptFunction)initConstructor("Error");
+ this.builtinError = initConstructor("Error", ScriptFunction.class);
final ScriptObject errorProto = getErrorPrototype();
// Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
@@ -1683,12 +1808,12 @@ public final class Global extends ScriptObject implements Scope {
}
private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
- final ScriptObject cons = initConstructor(name);
+ final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
final ScriptObject prototype = ScriptFunction.getPrototype(cons);
prototype.set(NativeError.NAME, name, false);
prototype.set(NativeError.MESSAGE, "", false);
prototype.setInitialProto(errorProto);
- return (ScriptFunction)cons;
+ return cons;
}
private void initJavaAccess() {
@@ -1700,8 +1825,8 @@ public final class Global extends ScriptObject implements Scope {
this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
this.builtinJavax = new NativeJavaPackage("javax", objectProto);
this.builtinOrg = new NativeJavaPackage("org", objectProto);
- this.builtinJavaImporter = initConstructor("JavaImporter");
- this.builtinJavaApi = initConstructor("Java");
+ this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
+ this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
}
private void initScripting(final ScriptEnvironment scriptEnv) {
@@ -1754,17 +1879,17 @@ public final class Global extends ScriptObject implements Scope {
}
private void initTypedArray() {
- this.builtinArrayBuffer = initConstructor("ArrayBuffer");
- this.builtinDataView = initConstructor("DataView");
- this.builtinInt8Array = initConstructor("Int8Array");
- this.builtinUint8Array = initConstructor("Uint8Array");
- this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
- this.builtinInt16Array = initConstructor("Int16Array");
- this.builtinUint16Array = initConstructor("Uint16Array");
- this.builtinInt32Array = initConstructor("Int32Array");
- this.builtinUint32Array = initConstructor("Uint32Array");
- this.builtinFloat32Array = initConstructor("Float32Array");
- this.builtinFloat64Array = initConstructor("Float64Array");
+ this.builtinArrayBuffer = initConstructor("ArrayBuffer", ScriptFunction.class);
+ this.builtinDataView = initConstructor("DataView", ScriptFunction.class);
+ this.builtinInt8Array = initConstructor("Int8Array", ScriptFunction.class);
+ this.builtinUint8Array = initConstructor("Uint8Array", ScriptFunction.class);
+ this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray", ScriptFunction.class);
+ this.builtinInt16Array = initConstructor("Int16Array", ScriptFunction.class);
+ this.builtinUint16Array = initConstructor("Uint16Array", ScriptFunction.class);
+ this.builtinInt32Array = initConstructor("Int32Array", ScriptFunction.class);
+ this.builtinUint32Array = initConstructor("Uint32Array", ScriptFunction.class);
+ this.builtinFloat32Array = initConstructor("Float32Array", ScriptFunction.class);
+ this.builtinFloat64Array = initConstructor("Float64Array", ScriptFunction.class);
}
private void copyBuiltins() {
@@ -1809,20 +1934,20 @@ public final class Global extends ScriptObject implements Scope {
}
private void initDebug() {
- this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
+ this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
}
- @SuppressWarnings("resource")
- private static Object printImpl(final boolean newLine, final Object... objects) {
- final PrintWriter out = Global.getEnv().getOut();
+ private Object printImpl(final boolean newLine, final Object... objects) {
+ @SuppressWarnings("resource")
+ final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
final StringBuilder sb = new StringBuilder();
- for (final Object object : objects) {
+ for (final Object obj : objects) {
if (sb.length() != 0) {
sb.append(' ');
}
- sb.append(JSType.toString(object));
+ sb.append(JSType.toString(obj));
}
// Print all at once to ensure thread friendly result.
@@ -1841,7 +1966,7 @@ public final class Global extends ScriptObject implements Scope {
* These classes are generated by nasgen tool and so we have to use
* reflection to load and create new instance of these classes.
*/
- private ScriptObject initConstructor(final String name) {
+ private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
try {
// Assuming class name pattern for built-in JS constructors.
final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
@@ -1850,8 +1975,8 @@ public final class Global extends ScriptObject implements Scope {
sb.append(name);
sb.append("$Constructor");
- final Class<?> funcClass = Class.forName(sb.toString());
- final ScriptObject res = (ScriptObject)funcClass.newInstance();
+ final Class<?> funcClass = Class.forName(sb.toString());
+ final T res = clazz.cast(funcClass.newInstance());
if (res instanceof ScriptFunction) {
// All global constructor prototypes are not-writable,
@@ -1864,8 +1989,8 @@ public final class Global extends ScriptObject implements Scope {
res.setInitialProto(getObjectPrototype());
}
+ res.setIsBuiltin();
return res;
-
} catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
@@ -1879,10 +2004,10 @@ public final class Global extends ScriptObject implements Scope {
// to play with object references carefully!!
private void initFunctionAndObject() {
// First-n-foremost is Function
- this.builtinFunction = (ScriptFunction)initConstructor("Function");
+ this.builtinFunction = initConstructor("Function", ScriptFunction.class);
// create global anonymous function
- final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
+ final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
// need to copy over members of Function.prototype to anon function
anon.addBoundProperties(getFunctionPrototype());
@@ -1901,7 +2026,7 @@ public final class Global extends ScriptObject implements Scope {
typeErrorThrower.preventExtensions();
// now initialize Object
- this.builtinObject = (ScriptFunction)initConstructor("Object");
+ this.builtinObject = initConstructor("Object", ScriptFunction.class);
final ScriptObject ObjectPrototype = getObjectPrototype();
// Object.getPrototypeOf(Function.prototype) === Object.prototype
anon.setInitialProto(ObjectPrototype);
@@ -1912,7 +2037,6 @@ public final class Global extends ScriptObject implements Scope {
final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
-
// Function valued properties of Function.prototype were not properly
// initialized. Because, these were created before global.function and
// global.object were not initialized.
@@ -1946,15 +2070,22 @@ public final class Global extends ScriptObject implements Scope {
}
}
+ //make sure apply and call have the same invalidation switchpoint
+ final SwitchPoint sp = new SwitchPoint();
+ optimisticFunctionMap.put("apply", sp);
+ optimisticFunctionMap.put("call", sp);
+ getFunctionPrototype().getProperty("apply").setChangeCallback(sp);
+ getFunctionPrototype().getProperty("call").setChangeCallback(sp);
+
properties = getObjectPrototype().getMap().getProperties();
+
for (final jdk.nashorn.internal.runtime.Property property : properties) {
final Object key = property.getKey();
- final Object value = ObjectPrototype.get(key);
-
if (key.equals("constructor")) {
continue;
}
+ final Object value = ObjectPrototype.get(key);
if (value instanceof ScriptFunction) {
final ScriptFunction func = (ScriptFunction)value;
final ScriptObject prototype = ScriptFunction.getPrototype(func);
@@ -1965,7 +2096,11 @@ public final class Global extends ScriptObject implements Scope {
}
}
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+ private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findVirtual(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
+ }
+
+ private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
}
@@ -1977,4 +2112,66 @@ public final class Global extends ScriptObject implements Scope {
this.lastRegExpResult = regExpResult;
}
+ @Override
+ protected boolean isGlobal() {
+ return true;
+ }
+
+ /**
+ * Check if there is a switchpoint for a reserved name. If there
+ * is, it must be invalidated upon properties with this name
+ * @param name property name
+ * @return switchpoint for invalidating this property, or null if not registered
+ */
+ public SwitchPoint getChangeCallback(final String name) {
+ return optimisticFunctionMap.get(name);
+ }
+
+ /**
+ * Is this a special name, that might be subject to invalidation
+ * on write, such as "apply" or "call"
+ * @param name name to check
+ * @return true if special name
+ */
+ public boolean isSpecialName(final String name) {
+ return getChangeCallback(name) != null;
+ }
+
+ /**
+ * Check if a reserved property name is invalidated
+ * @param name property name
+ * @return true if someone has written to it since Global was instantiated
+ */
+ public boolean isSpecialNameValid(final String name) {
+ final SwitchPoint sp = getChangeCallback(name);
+ return sp != null && !sp.hasBeenInvalidated();
+ }
+
+ /**
+ * Tag a reserved name as invalidated - used when someone writes
+ * to a property with this name - overly conservative, but link time
+ * is too late to apply e.g. apply-&gt;call specialization
+ * @param name property name
+ */
+ public void invalidateReservedName(final String name) {
+ final SwitchPoint sp = getChangeCallback(name);
+ if (sp != null) {
+ getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
+ SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+ }
+ }
+
+ /**
+ * Bootstrapper for invalidating a builtin name
+ * @param lookup lookup
+ * @param name name to invalidate
+ * @param type methodhandle type
+ * @return callsite for invalidator
+ */
+ public static CallSite invalidateNameBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type) {
+ final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name);
+ return new ConstantCallSite(target);
+ }
+
+
}
diff --git a/src/jdk/nashorn/internal/objects/NativeArray.java b/src/jdk/nashorn/internal/objects/NativeArray.java
index 80a3daa4..776803b3 100644
--- a/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -41,6 +41,9 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -49,7 +52,10 @@ import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Setter;
import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -80,6 +86,87 @@ public final class NativeArray extends ScriptObject {
private static final Object CALL_CMP = new Object();
private static final Object TO_LOCALE_STRING = new Object();
+ /*
+ * Constructors.
+ */
+ NativeArray() {
+ this(ArrayData.initialArray());
+ }
+
+ NativeArray(final long length) {
+ // TODO assert valid index in long before casting
+ this(ArrayData.allocate((int)length));
+ }
+
+ NativeArray(final int[] array) {
+ this(ArrayData.allocate(array));
+ }
+
+ NativeArray(final long[] array) {
+ this(ArrayData.allocate(array));
+ }
+
+ NativeArray(final double[] array) {
+ this(ArrayData.allocate(array));
+ }
+
+ NativeArray(final Object[] array) {
+ this(ArrayData.allocate(array.length));
+
+ ArrayData arrayData = this.getArray();
+ arrayData.ensure(array.length - 1);
+
+ for (int index = 0; index < array.length; index++) {
+ final Object value = array[index];
+
+ if (value == ScriptRuntime.EMPTY) {
+ arrayData = arrayData.delete(index);
+ } else {
+ arrayData = arrayData.set(index, value, false);
+ }
+ }
+
+ this.setArray(arrayData);
+ }
+
+ NativeArray(final ArrayData arrayData) {
+ this(arrayData, Global.instance());
+ }
+
+ NativeArray(final ArrayData arrayData, final Global global) {
+ super(global.getArrayPrototype(), $nasgenmap$);
+ setArray(arrayData);
+ setIsArray();
+ }
+
+ @Override
+ protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+ final GuardedInvocation inv = getArray().findFastGetMethod(getArray().getClass(), desc, request, operator);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findGetMethod(desc, request, operator);
+ }
+
+ @Override
+ protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastGetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+ return super.findGetIndexMethod(desc, request);
+ }
+
+ @Override
+ protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ final GuardedInvocation inv = getArray().findFastSetIndexMethod(getArray().getClass(), desc, request);
+ if (inv != null) {
+ return inv;
+ }
+
+ return super.findSetIndexMethod(desc, request);
+ }
+
private static InvokeByName getJOIN() {
return Global.instance().getInvokeByName(JOIN,
new Callable<InvokeByName>() {
@@ -156,59 +243,6 @@ public final class NativeArray extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- /*
- * Constructors.
- */
- NativeArray() {
- this(ArrayData.initialArray());
- }
-
- NativeArray(final long length) {
- // TODO assert valid index in long before casting
- this(ArrayData.allocate((int) length));
- }
-
- NativeArray(final int[] array) {
- this(ArrayData.allocate(array));
- }
-
- NativeArray(final long[] array) {
- this(ArrayData.allocate(array));
- }
-
- NativeArray(final double[] array) {
- this(ArrayData.allocate(array));
- }
-
- NativeArray(final Object[] array) {
- this(ArrayData.allocate(array.length));
-
- ArrayData arrayData = this.getArray();
- arrayData.ensure(array.length - 1);
-
- for (int index = 0; index < array.length; index++) {
- final Object value = array[index];
-
- if (value == ScriptRuntime.EMPTY) {
- arrayData = arrayData.delete(index);
- } else {
- arrayData = arrayData.set(index, value, false);
- }
- }
-
- this.setArray(arrayData);
- }
-
- NativeArray(final ArrayData arrayData) {
- this(arrayData, Global.instance());
- }
-
- NativeArray(final ArrayData arrayData, final Global global) {
- super(global.getArrayPrototype(), $nasgenmap$);
- this.setArray(arrayData);
- this.setIsArray();
- }
-
@Override
public String getClassName() {
return "Array";
@@ -216,7 +250,11 @@ public final class NativeArray extends ScriptObject {
@Override
public Object getLength() {
- return getArray().length() & JSType.MAX_UINT;
+ final long length = getArray().length() & JSType.MAX_UINT;
+ if(length < Integer.MAX_VALUE) {
+ return (int)length;
+ }
+ return length;
}
/**
@@ -270,7 +308,7 @@ public final class NativeArray extends ScriptObject {
}
// Step 3h and 3i
- final boolean newWritable = (!newLenDesc.has(WRITABLE) || newLenDesc.isWritable());
+ final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();
if (!newWritable) {
newLenDesc.setWritable(true);
}
@@ -481,6 +519,19 @@ public final class NativeArray extends ScriptObject {
}
/**
+ * Assert that an array is numeric, if not throw type error
+ * @param self self array to check
+ * @return true if numeric
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE)
+ public static Object assertNumeric(final Object self) {
+ if(!(self instanceof NativeArray && ((NativeArray)self).getArray().getOptimisticType().isNumeric())) {
+ throw typeError("not.a.numeric.array", ScriptRuntime.safeToString(self));
+ }
+ return Boolean.TRUE;
+ }
+
+ /**
* ECMA 15.4.4.3 Array.prototype.toLocaleString ( )
*
* @param self self reference
@@ -593,6 +644,21 @@ public final class NativeArray extends ScriptObject {
/**
* ECMA 15.4.2.2 new Array (len)
*
+ * Specialized constructor for zero arguments - empty array
+ *
+ * @param newObj was the new operator used to instantiate this array
+ * @param self self reference
+ * @param element first element
+ * @return the new NativeArray
+ */
+ @SpecializedConstructor
+ public static Object construct(final boolean newObj, final Object self, final boolean element) {
+ return new NativeArray(new Object[] { element });
+ }
+
+ /**
+ * ECMA 15.4.2.2 new Array (len)
+ *
* Specialized constructor for one integer argument (length)
*
* @param newObj was the new operator used to instantiate this array
@@ -668,16 +734,16 @@ public final class NativeArray extends ScriptObject {
return new NativeArray(list.toArray());
}
- @SuppressWarnings("null")
private static void concatToList(final ArrayList<Object> list, final Object obj) {
- final boolean isScriptArray = isArray(obj);
+ final boolean isScriptArray = isArray(obj);
final boolean isScriptObject = isScriptArray || obj instanceof ScriptObject;
if (isScriptArray || obj instanceof Iterable || (obj != null && obj.getClass().isArray())) {
final Iterator<Object> iter = arrayLikeIterator(obj, true);
if (iter.hasNext()) {
for (int i = 0; iter.hasNext(); ++i) {
final Object value = iter.next();
- if (value == ScriptRuntime.UNDEFINED && isScriptObject && !((ScriptObject)obj).has(i)) {
+ final boolean lacksIndex = obj != null && !((ScriptObject)obj).has(i);
+ if (value == ScriptRuntime.UNDEFINED && isScriptObject && lacksIndex) {
// TODO: eventually rewrite arrayLikeIterator to use a three-state enum for handling
// UNDEFINED instead of an "includeUndefined" boolean with states SKIP, INCLUDE,
// RETURN_EMPTY. Until then, this is how we'll make sure that empty elements don't make it
@@ -763,20 +829,17 @@ public final class NativeArray extends ScriptObject {
*
* @param self self reference
* @param args arguments to push
- * @return array after pushes
+ * @return array length after pushes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static Object push(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)self;
- if (bulkable(sobj)) {
- if (sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
- final ArrayData newData = sobj.getArray().push(true, args);
- sobj.setArray(newData);
- return newData.length();
- }
- //fallthru
+ if (bulkable(sobj) && sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
+ final ArrayData newData = sobj.getArray().push(true, args);
+ sobj.setArray(newData);
+ return newData.length();
}
long len = JSType.toUint32(sobj.getLength());
@@ -787,6 +850,88 @@ public final class NativeArray extends ScriptObject {
return len;
} catch (final ClassCastException | NullPointerException e) {
+ throw typeError(Context.getGlobal(), e, "not.an.object", ScriptRuntime.safeToString(self));
+ }
+ }
+
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single int argument
+ *
+ * @param self self reference
+ * @param arg argument to push
+ * @return array after pushes
+ */
+/* @SpecializedFunction
+ public static long push(final Object self, final int arg) {
+ try {
+ final ScriptObject sobj = (ScriptObject)self;
+ final ArrayData arrayData = sobj.getArray();
+ final long length = arrayData.length();
+
+ if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) {
+ sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true));
+ return length + 1;
+ }
+
+ long len = JSType.toUint32(sobj.getLength());
+ sobj.set(len++, arg, true);
+ sobj.set("length", len, true);
+ return len;
+ } catch (final ClassCastException | NullPointerException e) {
+ throw typeError("not.an.object", ScriptRuntime.safeToString(self));
+ }
+ }
+*/
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single number argument
+ *
+ * @param self self reference
+ * @param arg argument to push
+ * @return array after pushes
+ */
+ /* @SpecializedFunction
+ public static long push(final Object self, final double arg) {
+ try {
+ final ScriptObject sobj = (ScriptObject)self; final ArrayData arrayData = sobj.getArray();
+ final long length = arrayData.length();
+
+ if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) {
+ sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true));
+ return length + 1;
+ }
+
+ long len = JSType.toUint32(sobj.getLength());
+ sobj.set(len++, arg, true);
+ sobj.set("length", len, true);
+ return len;
+ } catch (final ClassCastException | NullPointerException e) {
+ throw typeError("not.an.object", ScriptRuntime.safeToString(self));
+ }
+ }
+*/
+ /**
+ * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single object argument
+ *
+ * @param self self reference
+ * @param arg argument to push
+ * @return array after pushes
+ */
+ @SpecializedFunction
+ public static long push(final Object self, final Object arg) {
+ try {
+ final ScriptObject sobj = (ScriptObject)self;
+ final ArrayData arrayData = sobj.getArray();
+ final long length = arrayData.length();
+ if (bulkable(sobj) && length < JSType.MAX_UINT) {
+ sobj.setArray(arrayData.push(true, arg)); //ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true));
+ return length + 1;
+ }
+
+ long len = JSType.toUint32(sobj.getLength());
+ sobj.set(len++, arg, true);
+ sobj.set("length", len, true);
+ return len;
+ } catch (final ClassCastException | NullPointerException e) {
throw typeError("not.an.object", ScriptRuntime.safeToString(self));
}
}
@@ -893,7 +1038,7 @@ public final class NativeArray extends ScriptObject {
final ScriptObject sobj = (ScriptObject)obj;
final long len = JSType.toUint32(sobj.getLength());
final long relativeStart = JSType.toLong(start);
- final long relativeEnd = (end == ScriptRuntime.UNDEFINED) ? len : JSType.toLong(end);
+ final long relativeEnd = end == ScriptRuntime.UNDEFINED ? len : JSType.toLong(end);
long k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
final long finale = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
@@ -1000,7 +1145,7 @@ public final class NativeArray extends ScriptObject {
}
sobj.setArray(array);
- }
+ }
return sobj;
} catch (final ClassCastException | NullPointerException e) {
@@ -1023,8 +1168,8 @@ public final class NativeArray extends ScriptObject {
return ScriptRuntime.UNDEFINED;
}
- final Object start = (args.length > 0) ? args[0] : ScriptRuntime.UNDEFINED;
- final Object deleteCount = (args.length > 1) ? args[1] : ScriptRuntime.UNDEFINED;
+ final Object start = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED;
+ final Object deleteCount = args.length > 1 ? args[1] : ScriptRuntime.UNDEFINED;
Object[] items;
@@ -1076,7 +1221,7 @@ public final class NativeArray extends ScriptObject {
}
if (items.length < deleteCount) {
- for (long k = start; k < (len - deleteCount); k++) {
+ for (long k = start; k < len - deleteCount; k++) {
final long from = k + deleteCount;
final long to = k + items.length;
@@ -1087,7 +1232,7 @@ public final class NativeArray extends ScriptObject {
}
}
- for (long k = len; k > (len - deleteCount + items.length); k--) {
+ for (long k = len; k > len - deleteCount + items.length; k--) {
sobj.delete(k - 1, true);
}
} else if (items.length > deleteCount) {
@@ -1157,7 +1302,7 @@ public final class NativeArray extends ScriptObject {
}
for (int j = 0; j < items.length; j++) {
- sobj.set(j, items[j], true);
+ sobj.set(j, items[j], true);
}
}
@@ -1190,7 +1335,7 @@ public final class NativeArray extends ScriptObject {
}
- for (long k = Math.max(0, (n < 0) ? (len - Math.abs(n)) : n); k < len; k++) {
+ for (long k = Math.max(0, n < 0 ? len - Math.abs(n) : n); k < len; k++) {
if (sobj.has(k)) {
if (ScriptRuntime.EQ_STRICT(sobj.get(k), searchElement)) {
return k;
@@ -1221,10 +1366,10 @@ public final class NativeArray extends ScriptObject {
return -1;
}
- final Object searchElement = (args.length > 0) ? args[0] : ScriptRuntime.UNDEFINED;
- final long n = (args.length > 1) ? JSType.toLong(args[1]) : (len - 1);
+ final Object searchElement = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED;
+ final long n = args.length > 1 ? JSType.toLong(args[1]) : len - 1;
- for (long k = (n < 0) ? (len - Math.abs(n)) : Math.min(n, len - 1); k >= 0; k--) {
+ for (long k = n < 0 ? len - Math.abs(n) : Math.min(n, len - 1); k >= 0; k--) {
if (sobj.has(k)) {
if (ScriptRuntime.EQ_STRICT(sobj.get(k), searchElement)) {
return k;
@@ -1257,7 +1402,7 @@ public final class NativeArray extends ScriptObject {
@Override
protected boolean forEach(final Object val, final long i) throws Throwable {
- return (result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self));
+ return result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self);
}
}.apply();
}
@@ -1434,4 +1579,9 @@ public final class NativeArray extends ScriptObject {
return false;
}
+
+ @Override
+ public String toString() {
+ return "NativeArray@" + Debug.id(this) + '@' + getArray().getClass().getSimpleName();
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
index 70c97daf..4d16ca54 100644
--- a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
+++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
@@ -25,27 +25,81 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
import java.nio.ByteBuffer;
-import java.util.Arrays;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+/**
+ * NativeArrayBuffer - ArrayBuffer as described in the JS typed
+ * array spec
+ */
@ScriptClass("ArrayBuffer")
-final class NativeArrayBuffer extends ScriptObject {
- private final byte[] buffer;
+public final class NativeArrayBuffer extends ScriptObject {
+ private final ByteBuffer nb;
// initialized by nasgen
private static PropertyMap $nasgenmap$;
+ /**
+ * Constructor
+ * @param nb native byte buffer to wrap
+ * @param global global instance
+ */
+ protected NativeArrayBuffer(final ByteBuffer nb, final Global global) {
+ super(global.getArrayBufferPrototype(), $nasgenmap$);
+ this.nb = nb;
+ }
+
+ /**
+ * Constructor
+ * @param nb native byte buffer to wrap
+ */
+ protected NativeArrayBuffer(final ByteBuffer nb) {
+ this(nb, Global.instance());
+ }
+
+ /**
+ * Constructor
+ * @param byteLength byteLength for buffer
+ */
+ protected NativeArrayBuffer(final int byteLength) {
+ this(ByteBuffer.allocateDirect(byteLength));
+ }
+
+ /**
+ * Clone constructor
+ * Used only for slice
+ * @param other original buffer
+ * @param begin begin byte index
+ * @param end end byte index
+ */
+ protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) {
+ this(cloneBuffer(other.getNioBuffer(), begin, end));
+ }
+
+ /**
+ * Constructor
+ * @param newObj is this invoked with new
+ * @param self self reference
+ * @param args arguments to constructor
+ * @return new NativeArrayBuffer
+ */
@Constructor(arity = 1)
public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) {
+ if (!newObj) {
+ throw typeError("constructor.requires.new", "ArrayBuffer");
+ }
+
if (args.length == 0) {
throw new RuntimeException("missing length argument");
}
@@ -53,21 +107,19 @@ final class NativeArrayBuffer extends ScriptObject {
return new NativeArrayBuffer(JSType.toInt32(args[0]));
}
- protected NativeArrayBuffer(final byte[] byteArray, final Global global) {
- super(global.getArrayBufferPrototype(), $nasgenmap$);
- this.buffer = byteArray;
- }
-
- protected NativeArrayBuffer(final byte[] byteArray) {
- this(byteArray, Global.instance());
- }
-
- protected NativeArrayBuffer(final int byteLength) {
- this(new byte[byteLength]);
+ private static ByteBuffer cloneBuffer(final ByteBuffer original, final int begin, final int end) {
+ final ByteBuffer clone = ByteBuffer.allocateDirect(original.capacity());
+ original.rewind();//copy from the beginning
+ clone.put(original);
+ original.rewind();
+ clone.flip();
+ clone.position(begin);
+ clone.limit(end);
+ return clone.slice();
}
- protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) {
- this(Arrays.copyOfRange(other.buffer, begin, end));
+ ByteBuffer getNioBuffer() {
+ return nb;
}
@Override
@@ -75,19 +127,55 @@ final class NativeArrayBuffer extends ScriptObject {
return "ArrayBuffer";
}
+ /**
+ * Byte length for native array buffer
+ * @param self native array buffer
+ * @return byte length
+ */
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object byteLength(final Object self) {
- return ((NativeArrayBuffer)self).buffer.length;
+ public static int byteLength(final Object self) {
+ return ((NativeArrayBuffer)self).getByteLength();
}
+ /**
+ * Slice function
+ * @param self native array buffer
+ * @param begin0 start byte index
+ * @param end0 end byte index
+ * @return new array buffer, sliced
+ */
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) {
final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
- int begin = JSType.toInt32(begin0);
- int end = end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : arrayBuffer.getByteLength();
- begin = adjustIndex(begin, arrayBuffer.getByteLength());
- end = adjustIndex(end, arrayBuffer.getByteLength());
- return new NativeArrayBuffer((NativeArrayBuffer) self, begin, Math.max(end, begin));
+ final int byteLength = arrayBuffer.getByteLength();
+ final int begin = adjustIndex(JSType.toInt32(begin0), byteLength);
+ final int end = adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : byteLength, byteLength);
+ return new NativeArrayBuffer(arrayBuffer, begin, Math.max(end, begin));
+ }
+
+ /**
+ * Specialized slice function
+ * @param self native array buffer
+ * @param begin start byte index
+ * @param end end byte index
+ * @return new array buffer, sliced
+ */
+ @SpecializedFunction
+ public static Object slice(final Object self, final int begin, final int end) {
+ final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
+ final int byteLength = arrayBuffer.getByteLength();
+ return new NativeArrayBuffer(arrayBuffer, adjustIndex(begin, byteLength), Math.max(adjustIndex(end, byteLength), begin));
+ }
+
+ /**
+ * Specialized slice function
+ * @param self native array buffer
+ * @param begin start byte index
+ * @return new array buffer, sliced
+ */
+ @SpecializedFunction
+ public static Object slice(final Object self, final int begin) {
+ return slice(self, begin, ((NativeArrayBuffer)self).getByteLength());
}
/**
@@ -100,10 +188,7 @@ final class NativeArrayBuffer extends ScriptObject {
* @return valid index index in the range [0, length).
*/
static int adjustIndex(final int index, final int length) {
- if (index < 0) {
- return clamp(index + length, length);
- }
- return clamp(index, length);
+ return index < 0 ? clamp(index + length, length) : clamp(index, length);
}
/**
@@ -118,23 +203,19 @@ final class NativeArrayBuffer extends ScriptObject {
return index;
}
- public byte[] getByteArray() {
- return buffer;
- }
-
- public int getByteLength() {
- return buffer.length;
+ int getByteLength() {
+ return nb.limit();
}
ByteBuffer getBuffer() {
- return ByteBuffer.wrap(buffer);
+ return nb;
}
ByteBuffer getBuffer(final int offset) {
- return ByteBuffer.wrap(buffer, offset, buffer.length - offset);
+ return (ByteBuffer)nb.duplicate().position(offset);
}
ByteBuffer getBuffer(final int offset, final int length) {
- return ByteBuffer.wrap(buffer, offset, length);
+ return (ByteBuffer)getBuffer(offset).limit(length);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeDataView.java b/src/jdk/nashorn/internal/objects/NativeDataView.java
index f64bccde..470803ef 100644
--- a/src/jdk/nashorn/internal/objects/NativeDataView.java
+++ b/src/jdk/nashorn/internal/objects/NativeDataView.java
@@ -204,8 +204,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt8(final Object self, final Object byteOffset) {
try {
return getBuffer(self).get(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -220,8 +220,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt8(final Object self, final int byteOffset) {
try {
return getBuffer(self).get(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -235,9 +235,9 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static int getUint8(final Object self, final Object byteOffset) {
try {
- return (0xFF & getBuffer(self).get(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFF & getBuffer(self).get(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -251,9 +251,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static int getUint8(final Object self, final int byteOffset) {
try {
- return (0xFF & getBuffer(self).get(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFF & getBuffer(self).get(byteOffset);
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -269,8 +269,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt16(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -285,8 +285,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt16(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getShort(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -302,8 +302,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt16(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getShort(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -318,9 +318,9 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static int getUint16(final Object self, final Object byteOffset, final Object littleEndian) {
try {
- return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -334,9 +334,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static int getUint16(final Object self, final int byteOffset) {
try {
- return (int) (0xFFFF & getBuffer(self, false).getShort(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFF & getBuffer(self, false).getShort(byteOffset);
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -351,9 +351,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static int getUint16(final Object self, final int byteOffset, final boolean littleEndian) {
try {
- return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset);
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -369,8 +369,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt32(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -385,8 +385,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt32(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getInt(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -402,8 +402,8 @@ public class NativeDataView extends ScriptObject {
public static int getInt32(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getInt(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -418,9 +418,9 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static long getUint32(final Object self, final Object byteOffset, final Object littleEndian) {
try {
- return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return 0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -434,9 +434,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static long getUint32(final Object self, final int byteOffset) {
try {
- return (long) (0xFFFFFFFFL & getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return JSType.MAX_UINT & getBuffer(self, false).getInt(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -451,9 +451,9 @@ public class NativeDataView extends ScriptObject {
@SpecializedFunction
public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
try {
- return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ return JSType.MAX_UINT & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -469,8 +469,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat32(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getFloat(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -485,8 +485,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat32(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getFloat(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -502,8 +502,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat32(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getFloat(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -519,8 +519,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat64(final Object self, final Object byteOffset, final Object littleEndian) {
try {
return getBuffer(self, littleEndian).getDouble(JSType.toInt32(byteOffset));
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -535,8 +535,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat64(final Object self, final int byteOffset) {
try {
return getBuffer(self, false).getDouble(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -552,8 +552,8 @@ public class NativeDataView extends ScriptObject {
public static double getFloat64(final Object self, final int byteOffset, final boolean littleEndian) {
try {
return getBuffer(self, littleEndian).getDouble(byteOffset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -582,8 +582,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -600,8 +600,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(byteOffset, (byte)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -618,8 +618,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -636,8 +636,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self).put(byteOffset, (byte)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -655,8 +655,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -673,8 +673,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -692,8 +692,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -711,8 +711,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -729,8 +729,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -748,8 +748,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -765,10 +765,10 @@ public class NativeDataView extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
public static Object setInt32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
try {
- getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toInt32(value));
+ getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), JSType.toInt32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -785,8 +785,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putInt(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -804,8 +804,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putInt(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -823,8 +823,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toUint32(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -841,8 +841,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putInt(byteOffset, (int)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -860,8 +860,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putInt(byteOffset, (int)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -879,8 +879,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putFloat((int)JSType.toUint32(byteOffset), (float)JSType.toNumber(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -897,8 +897,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putFloat(byteOffset, (float)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -916,8 +916,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putFloat(byteOffset, (float)value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -935,8 +935,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putDouble((int)JSType.toUint32(byteOffset), JSType.toNumber(value));
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -953,8 +953,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, false).putDouble(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -972,8 +972,8 @@ public class NativeDataView extends ScriptObject {
try {
getBuffer(self, littleEndian).putDouble(byteOffset, value);
return UNDEFINED;
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.offset");
}
}
@@ -981,16 +981,16 @@ public class NativeDataView extends ScriptObject {
private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset) {
try {
return nab.getBuffer(offset);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.constructor.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.constructor.offset");
}
}
private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset, final int length) {
try {
return nab.getBuffer(offset, length);
- } catch (final IndexOutOfBoundsException ioe) {
- throw rangeError(ioe, "dataview.constructor.offset");
+ } catch (final IllegalArgumentException iae) {
+ throw rangeError(iae, "dataview.constructor.offset");
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeDate.java b/src/jdk/nashorn/internal/objects/NativeDate.java
index b3661df7..eac59c46 100644
--- a/src/jdk/nashorn/internal/objects/NativeDate.java
+++ b/src/jdk/nashorn/internal/objects/NativeDate.java
@@ -909,6 +909,7 @@ public final class NativeDate extends ScriptObject {
sb.append(n);
}
+ @SuppressWarnings("fallthrough")
private static String toStringImpl(final Object self, final int format) {
final NativeDate nd = getNativeDate(self);
@@ -934,7 +935,6 @@ public final class NativeDate extends ScriptObject {
}
sb.append(' ');
- //$FALL-THROUGH$
case FORMAT_TIME:
final TimeZone tz = nd.getTimeZone();
final double utcTime = nd.getTime();
diff --git a/src/jdk/nashorn/internal/objects/NativeDebug.java b/src/jdk/nashorn/internal/objects/NativeDebug.java
index 5d80c37b..dc6ba044 100644
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java
+++ b/src/jdk/nashorn/internal/objects/NativeDebug.java
@@ -28,16 +28,19 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.io.PrintWriter;
+import java.util.LinkedList;
import java.util.Objects;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
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.events.RuntimeEvent;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
/**
@@ -93,21 +96,6 @@ public final class NativeDebug extends ScriptObject {
}
/**
- * Nashorn extension: get spill vector from {@link ScriptObject}
- *
- * @param self self reference
- * @param obj script object
- * @return the spill vector for the given ScriptObject
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object spill(final Object self, final Object obj) {
- if (obj instanceof ScriptObject) {
- return ((ScriptObject)obj).spill;
- }
- return UNDEFINED;
- }
-
- /**
* Check object identity comparison regardless of type
*
* @param self self reference
@@ -121,6 +109,31 @@ public final class NativeDebug extends ScriptObject {
}
/**
+ * Returns true if if the two objects are both property maps, and they have identical properties in the same order,
+ * but allows the properties to differ in their types.
+ * @param self self
+ * @param m1 first property map
+ * @param m2 second property map
+ * @return true if they have identical properties in same order, with possibly different types.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object equalWithoutType(final Object self, final Object m1, final Object m2) {
+ return ((PropertyMap)m1).equalsWithoutType((PropertyMap)m2);
+ }
+
+ /**
+ * Returns a diagnostic string representing the difference of two property maps.
+ * @param self self
+ * @param m1 first property map
+ * @param m2 second property map
+ * @return a diagnostic string representing the difference of two property maps.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object diffPropertyMaps(final Object self, final Object m1, final Object m2) {
+ return PropertyMap.diff((PropertyMap)m1, (PropertyMap)m2);
+ }
+
+ /**
* Object util - getClass
*
* @param self self reference
@@ -196,7 +209,6 @@ public final class NativeDebug extends ScriptObject {
* @param self self reference
* @return undefined
*/
- @SuppressWarnings("resource")
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object dumpCounters(final Object self) {
final PrintWriter out = Context.getCurrentErr();
@@ -210,7 +222,6 @@ public final class NativeDebug extends ScriptObject {
out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
out.println("PropertyMap count " + PropertyMap.getCount());
out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
- out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit());
@@ -223,4 +234,133 @@ public final class NativeDebug extends ScriptObject {
return UNDEFINED;
}
+
+ /*
+ * Framework for logging runtime events
+ */
+
+ private static final String EVENT_QUEUE = "__eventQueue__";
+ private static final String EVENT_QUEUE_CAPACITY = "__eventQueueCapacity__";
+
+ /**
+ * Get the capacity of the event queue
+ * @param self self reference
+ * @return capacity of event queue as an integer
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getEventQueueCapacity(final Object self) {
+ final ScriptObject sobj = (ScriptObject)self;
+ Integer cap;
+ if (sobj.has(EVENT_QUEUE_CAPACITY)) {
+ cap = JSType.toInt32(sobj.get(EVENT_QUEUE_CAPACITY));
+ } else {
+ setEventQueueCapacity(self, cap = RuntimeEvent.RUNTIME_EVENT_QUEUE_SIZE);
+ }
+ return cap;
+ }
+
+ /**
+ * Set the event queue capacity
+ * @param self
+ * @param newCapacity
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
+ ((ScriptObject)self).set(EVENT_QUEUE_CAPACITY, newCapacity, true);
+ }
+
+ /**
+ * Add a runtime event to the runtime event queue. The queue has a fixed
+ * size {@link RuntimeEvent#RUNTIME_EVENT_QUEUE_SIZE} and the oldest
+ * entry will be thrown out of the queue is about to overflow
+ * @param self self reference
+ * @param event event to add
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void addRuntimeEvent(final Object self, final Object event) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ final int cap = (Integer)getEventQueueCapacity(self);
+ while (q.size() >= cap) {
+ q.removeFirst();
+ }
+ q.addLast(getEvent(event));
+ }
+
+ /**
+ * Expands the event queue capacity, or truncates if capacity is lower than
+ * current capacity. Then only the newest entries are kept
+ * @param self self reference
+ * @param newCapacity new capacity
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void expandEventQueueCapacity(final Object self, final Object newCapacity) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ final int nc = JSType.toInt32(newCapacity);
+ while (q.size() > nc) {
+ q.removeFirst();
+ }
+ setEventQueueCapacity(self, nc);
+ }
+
+ /**
+ * Clear the runtime event queue
+ * @param self self reference
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void clearRuntimeEvents(final Object self) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ q.clear();
+ }
+
+ /**
+ * Remove a specific runtime event from the event queue
+ * @param self self reference
+ * @param event event to remove
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static void removeRuntimeEvent(final Object self, final Object event) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ final RuntimeEvent<?> re = getEvent(event);
+ if (!q.remove(re)) {
+ throw new IllegalStateException("runtime event " + re + " was not in event queue");
+ }
+ }
+
+ /**
+ * Return all runtime events in the queue as an array
+ * @param self self reference
+ * @return array of events
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getRuntimeEvents(final Object self) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ return q.toArray(new RuntimeEvent<?>[q.size()]);
+ }
+
+ /**
+ * Return the last runtime event in the queue
+ * @param self self reference
+ * @return the freshest event, null if queue is empty
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getLastRuntimeEvent(final Object self) {
+ final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+ return q.isEmpty() ? null : q.getLast();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static LinkedList<RuntimeEvent<?>> getEventQueue(final Object self) {
+ final ScriptObject sobj = (ScriptObject)self;
+ LinkedList<RuntimeEvent<?>> q;
+ if (sobj.has(EVENT_QUEUE)) {
+ q = (LinkedList<RuntimeEvent<?>>)((ScriptObject)self).get(EVENT_QUEUE);
+ } else {
+ ((ScriptObject)self).set(EVENT_QUEUE, q = new LinkedList<>(), true);
+ }
+ return q;
+ }
+
+ private static RuntimeEvent<?> getEvent(final Object event) {
+ return (RuntimeEvent<?>)event;
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeError.java b/src/jdk/nashorn/internal/objects/NativeError.java
index 81f0006e..e1d95ce0 100644
--- a/src/jdk/nashorn/internal/objects/NativeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeError.java
@@ -146,8 +146,7 @@ public final class NativeError extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object captureStackTrace(final Object self, final Object errorObj) {
- Global.checkObject(errorObj);
- final ScriptObject sobj = (ScriptObject)errorObj;
+ final ScriptObject sobj = Global.checkObject(errorObj);
initException(sobj);
sobj.delete(STACK, false);
if (! sobj.has("stack")) {
@@ -183,8 +182,7 @@ public final class NativeError extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object printStackTrace(final Object self) {
- Global.checkObject(self);
- return ECMAException.printStackTrace((ScriptObject)self);
+ return ECMAException.printStackTrace(Global.checkObject(self));
}
/**
@@ -198,8 +196,7 @@ public final class NativeError extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object getStackTrace(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
final Object exception = ECMAException.getException(sobj);
Object[] res;
if (exception instanceof Throwable) {
@@ -219,8 +216,7 @@ public final class NativeError extends ScriptObject {
* @return line number from which error was thrown
*/
public static Object getLineNumber(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
return sobj.has(LINENUMBER) ? sobj.get(LINENUMBER) : ECMAException.getLineNumber(sobj);
}
@@ -233,8 +229,7 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setLineNumber(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(LINENUMBER)) {
sobj.put(LINENUMBER, value, false);
} else {
@@ -251,8 +246,7 @@ public final class NativeError extends ScriptObject {
* @return column number from which error was thrown
*/
public static Object getColumnNumber(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
return sobj.has(COLUMNNUMBER) ? sobj.get(COLUMNNUMBER) : ECMAException.getColumnNumber((ScriptObject)self);
}
@@ -265,8 +259,7 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setColumnNumber(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(COLUMNNUMBER)) {
sobj.put(COLUMNNUMBER, value, false);
} else {
@@ -283,8 +276,7 @@ public final class NativeError extends ScriptObject {
* @return file name from which error was thrown
*/
public static Object getFileName(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
return sobj.has(FILENAME) ? sobj.get(FILENAME) : ECMAException.getFileName((ScriptObject)self);
}
@@ -297,8 +289,7 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setFileName(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(FILENAME)) {
sobj.put(FILENAME, value, false);
} else {
@@ -317,8 +308,7 @@ public final class NativeError extends ScriptObject {
* @return value of "stack" property
*/
public static Object getStack(final Object self) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.has(STACK)) {
return sobj.get(STACK);
}
@@ -348,14 +338,12 @@ public final class NativeError extends ScriptObject {
* @return value that was set
*/
public static Object setStack(final Object self, final Object value) {
- Global.checkObject(self);
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
if (sobj.hasOwnProperty(STACK)) {
sobj.put(STACK, value, false);
} else {
sobj.addOwnProperty(STACK, Attribute.NOT_ENUMERABLE, value);
}
-
return value;
}
@@ -369,9 +357,7 @@ public final class NativeError extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object toString(final Object self) {
// Step 1 and 2 : check if 'self' is object it not throw TypeError
- Global.checkObject(self);
-
- final ScriptObject sobj = (ScriptObject)self;
+ final ScriptObject sobj = Global.checkObject(self);
// Step 3 & 4 : get "name" and convert to String.
// But if message is undefined make it "Error".
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
index a9dfb7a4..b2639c45 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
@@ -25,6 +25,12 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +41,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Float32 array for the TypedArray extension
@@ -56,73 +63,103 @@ public final class NativeFloat32Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeFloat32Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Float32ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Float32ArrayData(nb.asFloatBuffer(), start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Float32ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Float32Array";
}
};
- private static final class Float32ArrayData extends ArrayDataImpl {
- private Float32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Float32ArrayData extends TypedArrayData<FloatBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Float32ArrayData.class, "getElem", double.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Float32ArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+ private Float32ArrayData(final FloatBuffer nb, final int start, final int end) {
+ super(((FloatBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private double getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final double elem) {
+ try {
+ nb.put(index, (float)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class || returnType == long.class) {
+ return null;
+ }
+ return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
}
@Override
- protected double getDoubleImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- final int bits = byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 |
- byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
- byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
- return Float.intBitsToFloat(bits);
+ public int getInt(final int index) {
+ return (int)getDouble(index);
}
@Override
- protected int getIntImpl(final int index) {
- return (int)getDoubleImpl(index);
+ public long getLong(final int index) {
+ return (long)getDouble(index);
}
@Override
- protected long getLongImpl(final int key) {
- return (long)getDoubleImpl(key);
+ public double getDouble(final int index) {
+ return getElem(index);
}
@Override
- protected Object getObjectImpl(final int key) {
- return getDoubleImpl(key);
+ public Object getObject(final int index) {
+ return getDouble(index);
}
@Override
- protected void setImpl(final int index, final double value) {
- final int bits = Float.floatToRawIntBits((float)value);
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(bits & 0xff);
- byteArray[byteIndex+1] = (byte)(bits >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(bits >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(bits >>> 24 & 0xff);
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toNumber(value), strict);
}
@Override
- protected void setImpl(final int key, final int value) {
- setImpl(key, (double)value);
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ return set(index, (double)value, strict);
}
@Override
- protected void setImpl(final int key, final long value) {
- setImpl(key, (double)value);
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (double)value, strict);
}
@Override
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toNumber(value));
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ setElem(index, value);
+ return this;
}
}
@@ -137,7 +174,7 @@ public final class NativeFloat32Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeFloat32Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeFloat32Array)constructorImpl(args, FACTORY);
+ return (NativeFloat32Array)constructorImpl(newObj, args, FACTORY);
}
NativeFloat32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -145,11 +182,6 @@ public final class NativeFloat32Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Float32Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
index 61b58807..93162952 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
@@ -25,6 +25,12 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.DoubleBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +41,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Float64 array for the TypedArray extension
@@ -56,83 +63,103 @@ public final class NativeFloat64Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeFloat64Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Float64ArrayData createArrayData(final ByteBuffer nb, final int start, final int length) {
+ return new Float64ArrayData(nb.asDoubleBuffer(), start, length);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Float64ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Float64Array";
}
};
- private static final class Float64ArrayData extends ArrayDataImpl {
- private Float64ArrayData(final NativeArrayBuffer buffer,
- final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Float64ArrayData extends TypedArrayData<DoubleBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Float64ArrayData.class, "getElem", double.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Float64ArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+ private Float64ArrayData(final DoubleBuffer nb, final int start, final int end) {
+ super(((DoubleBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private double getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final double elem) {
+ try {
+ nb.put(index, elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class || returnType == long.class) {
+ return null;
+ }
+ return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
}
@Override
- protected double getDoubleImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- final long bits;
- bits = byteArray[byteIndex ] & 0x0000_0000_0000_00ffL |
- (long)byteArray[byteIndex+1] << 8 & 0x0000_0000_0000_ff00L |
- (long)byteArray[byteIndex+2] << 16 & 0x0000_0000_00ff_0000L |
- (long)byteArray[byteIndex+3] << 24 & 0x0000_0000_ff00_0000L |
- (long)byteArray[byteIndex+4] << 32 & 0x0000_00ff_0000_0000L |
- (long)byteArray[byteIndex+5] << 40 & 0x0000_ff00_0000_0000L |
- (long)byteArray[byteIndex+6] << 48 & 0x00ff_0000_0000_0000L |
- (long)byteArray[byteIndex+7] << 56 & 0xff00_0000_0000_0000L ;
- return Double.longBitsToDouble(bits);
+ public int getInt(final int index) {
+ return (int)getDouble(index);
}
@Override
- protected int getIntImpl(final int index) {
- return (int)getDoubleImpl(index);
+ public long getLong(final int index) {
+ return (long)getDouble(index);
}
@Override
- protected long getLongImpl(final int key) {
- return (long)getDoubleImpl(key);
+ public double getDouble(final int index) {
+ return getElem(index);
}
@Override
- protected Object getObjectImpl(final int key) {
- return getDoubleImpl(key);
+ public Object getObject(final int index) {
+ return getDouble(index);
}
@Override
- protected void setImpl(final int index, final double value) {
- final long bits = Double.doubleToRawLongBits(value);
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(bits & 0xff);
- byteArray[byteIndex+1] = (byte)(bits >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(bits >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(bits >>> 24 & 0xff);
- byteArray[byteIndex+4] = (byte)(bits >>> 32 & 0xff);
- byteArray[byteIndex+5] = (byte)(bits >>> 40 & 0xff);
- byteArray[byteIndex+6] = (byte)(bits >>> 48 & 0xff);
- byteArray[byteIndex+7] = (byte)(bits >>> 56 & 0xff);
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toNumber(value), strict);
}
@Override
- protected void setImpl(final int key, final int value) {
- setImpl(key, (double)value);
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ return set(index, (double)value, strict);
}
@Override
- protected void setImpl(final int key, final long value) {
- setImpl(key, (double)value);
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (double)value, strict);
}
@Override
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toNumber(value));
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ setElem(index, value);
+ return this;
}
}
@@ -147,7 +174,7 @@ public final class NativeFloat64Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeFloat64Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeFloat64Array)constructorImpl(args, FACTORY);
+ return (NativeFloat64Array)constructorImpl(newObj, args, FACTORY);
}
NativeFloat64Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -155,11 +182,6 @@ public final class NativeFloat64Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Float64Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeFunction.java b/src/jdk/nashorn/internal/objects/NativeFunction.java
index afde4bd5..c4a79a56 100644
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/src/jdk/nashorn/internal/objects/NativeFunction.java
@@ -25,11 +25,15 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.util.List;
+import jdk.internal.dynalink.support.Lookup;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -40,10 +44,10 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.Source;
/**
* ECMA 15.3 Function Objects
@@ -55,6 +59,9 @@ import jdk.nashorn.internal.runtime.Source;
@ScriptClass("Function")
public final class NativeFunction {
+ /** apply arg converter handle */
+ public static final MethodHandle TO_APPLY_ARGS = Lookup.findOwnStatic(MethodHandles.lookup(), "toApplyArgs", Object[].class, Object.class);
+
// initialized by nasgen
@SuppressWarnings("unused")
private static PropertyMap $nasgenmap$;
@@ -88,50 +95,75 @@ public final class NativeFunction {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object apply(final Object self, final Object thiz, final Object array) {
- if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) {
- throw typeError("not.a.function", ScriptRuntime.safeToString(self));
- }
+ checkCallable(self);
- Object[] args = null;
+ final Object[] args = toApplyArgs(array);
+
+ if (self instanceof ScriptFunction) {
+ return ScriptRuntime.apply((ScriptFunction)self, thiz, args);
+ } else if (self instanceof JSObject) {
+ return ((JSObject)self).call(thiz, args);
+ }
+ throw new AssertionError("Should not reach here");
+ }
- if (array instanceof ScriptObject) {
+ /**
+ * Given an array-like object, converts it into a Java object array suitable for invocation of ScriptRuntime.apply
+ * or for direct invocation of the applied function.
+ * @param array the array-like object. Can be null in which case a zero-length array is created.
+ * @return the Java array
+ */
+ public static Object[] toApplyArgs(final Object array) {
+ if (array instanceof NativeArguments) {
+ return ((NativeArguments)array).getArray().asObjectArray();
+ } else if (array instanceof ScriptObject) {
// look for array-like object
final ScriptObject sobj = (ScriptObject)array;
- final Object len = sobj.getLength();
- final int n = (int)JSType.toUint32(len);
+ final int n = lengthToInt(sobj.getLength());
- args = new Object[n];
+ final Object[] args = new Object[n];
for (int i = 0; i < args.length; i++) {
args[i] = sobj.get(i);
}
+ return args;
} else if (array instanceof Object[]) {
- args = (Object[])array;
+ return (Object[])array;
} else if (array instanceof List) {
final List<?> list = (List<?>)array;
- list.toArray(args = new Object[list.size()]);
+ return list.toArray(new Object[list.size()]);
} else if (array == null || array == UNDEFINED) {
- args = ScriptRuntime.EMPTY_ARRAY;
+ return ScriptRuntime.EMPTY_ARRAY;
} else if (array instanceof JSObject) {
// look for array-like JSObject object
final JSObject jsObj = (JSObject)array;
- final Object len = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0);
- final int n = (int)JSType.toUint32(len);
+ final Object len = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0);
+ final int n = lengthToInt(len);
- args = new Object[n];
+ final Object[] args = new Object[n];
for (int i = 0; i < args.length; i++) {
args[i] = jsObj.hasSlot(i)? jsObj.getSlot(i) : UNDEFINED;
}
+ return args;
} else {
throw typeError("function.apply.expects.array");
}
+ }
- if (self instanceof ScriptFunction) {
- return ScriptRuntime.apply((ScriptFunction)self, thiz, args);
- } else if (self instanceof JSObject) {
- return ((JSObject)self).call(thiz, args);
+ private static int lengthToInt(final Object len) {
+ final long ln = JSType.toUint32(len);
+ // NOTE: ECMASCript 5.1 section 15.3.4.3 says length should be treated as Uint32, but we wouldn't be able to
+ // allocate a Java array of more than MAX_VALUE elements anyway, so at this point we have to throw an error.
+ // People applying a function to more than 2^31 arguments will unfortunately be out of luck.
+ if (ln > Integer.MAX_VALUE) {
+ throw rangeError("range.error.inappropriate.array.length", JSType.toString(len));
}
+ return (int)ln;
+ }
- throw new AssertionError("should not reach here");
+ private static void checkCallable(final Object self) {
+ if (!(self instanceof ScriptFunction || (self instanceof JSObject && ((JSObject)self).isFunction()))) {
+ throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+ }
}
/**
@@ -143,9 +175,7 @@ public final class NativeFunction {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static Object call(final Object self, final Object... args) {
- if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) {
- throw typeError("not.a.function", ScriptRuntime.safeToString(self));
- }
+ checkCallable(self);
final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
Object[] arguments;
@@ -235,7 +265,7 @@ public final class NativeFunction {
funcBody = JSType.toString(args[args.length - 1]);
final String paramList = paramListBuf.toString();
- if (! paramList.isEmpty()) {
+ if (!paramList.isEmpty()) {
checkFunctionParameters(paramList);
sb.append(paramList);
}
@@ -257,8 +287,7 @@ public final class NativeFunction {
}
private static void checkFunctionParameters(final String params) {
- final Source src = sourceFor("<function>", params);
- final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
+ final Parser parser = getParser(params);
try {
parser.parseFormalParameterList();
} catch (final ParserException pe) {
@@ -267,12 +296,16 @@ public final class NativeFunction {
}
private static void checkFunctionBody(final String funcBody) {
- final Source src = sourceFor("<function>", funcBody);
- final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
+ final Parser parser = getParser(funcBody);
try {
parser.parseFunctionBody();
} catch (final ParserException pe) {
pe.throwAsEcmaException();
}
}
+
+ private static Parser getParser(final String sourceText) {
+ final ScriptEnvironment env = Global.getEnv();
+ return new Parser(env, sourceFor("<function>", sourceText), new Context.ThrowErrorManager(), env._strict, null);
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeInt16Array.java b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
index f6aa2054..ad61cbd2 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
@@ -25,15 +25,23 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Int16 array for the TypedArray extension
@@ -56,37 +64,95 @@ public final class NativeInt16Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeInt16Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Int16ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Int16ArrayData(nb.asShortBuffer(), start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Int16ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Int16Array";
}
};
- private static final class Int16ArrayData extends ArrayDataImpl {
- private Int16ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Int16ArrayData extends TypedArrayData<ShortBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Int16ArrayData(final ShortBuffer nb, final int start, final int end) {
+ super(((ShortBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (short)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & (short)0x00ff |
- byteArray[byteIndex+1] << 8 & (short)0xff00 ;
+ public int getInt(final int index) {
+ return getElem(index);
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -101,7 +167,7 @@ public final class NativeInt16Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeInt16Array)constructorImpl(args, FACTORY);
+ return (NativeInt16Array)constructorImpl(newObj, args, FACTORY);
}
NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) {
@@ -109,11 +175,6 @@ public final class NativeInt16Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Int16Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeInt32Array.java b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
index 643bd816..b018f04e 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
@@ -25,15 +25,23 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Int32 array for the TypedArray extension
@@ -55,41 +63,94 @@ public final class NativeInt32Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeInt32Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Int32ArrayData createArrayData(final ByteBuffer nb, final int start, final int length) {
+ return new Int32ArrayData(nb.asIntBuffer(), start, length);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Int32ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Int32Array";
}
};
- private static final class Int32ArrayData extends ArrayDataImpl {
- private Int32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Int32ArrayData extends TypedArrayData<IntBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int32ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Int32ArrayData(final IntBuffer nb, final int start, final int end) {
+ super(((IntBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, elem);
+ } catch (final IndexOutOfBoundsException e) {
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 |
- byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
- byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
+ public int getInt(final int index) {
+ return getElem(index);
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(value >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(value >>> 24 & 0xff);
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -104,7 +165,7 @@ public final class NativeInt32Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeInt32Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeInt32Array)constructorImpl(args, FACTORY);
+ return (NativeInt32Array)constructorImpl(newObj, args, FACTORY);
}
NativeInt32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -112,11 +173,6 @@ public final class NativeInt32Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Int32Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeInt8Array.java b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
index 5822c6d5..6f9f6e7b 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
@@ -25,15 +25,22 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Int8Array for the TypedArray extension
@@ -57,32 +64,97 @@ public final class NativeInt8Array extends ArrayBufferView {
}
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Int8ArrayData(buffer, byteOffset, length);
+ public Int8ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Int8ArrayData(nb, start, end);
+ }
+
+ @Override
+ public String getClassName() {
+ return "Int8Array";
}
};
- private static final class Int8ArrayData extends ArrayDataImpl {
- private Int8ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Int8ArrayData extends TypedArrayData<ByteBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int8ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int8ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Int8ArrayData(final ByteBuffer nb, final int start, final int end) {
+ super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (byte)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public int getInt(final int index) {
+ return getElem(index);
}
@Override
- protected int getIntImpl(final int index) {
- return buffer.getByteArray()[byteIndex(index)];
+ public long getLong(final int index) {
+ return getInt(index);
}
@Override
- protected void setImpl(final int index, final int value) {
- buffer.getByteArray()[byteIndex(index)] = (byte)value;
+ public double getDouble(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
+
/**
* Constructor
*
@@ -94,7 +166,7 @@ public final class NativeInt8Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeInt8Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeInt8Array)constructorImpl(args, FACTORY);
+ return (NativeInt8Array)constructorImpl(newObj, args, FACTORY);
}
NativeInt8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -102,11 +174,6 @@ public final class NativeInt8Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Int8Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
index 150f6bd4..134ff8d1 100644
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
@@ -47,6 +47,7 @@ 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.UnwarrantedOptimismException;
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
import jdk.nashorn.internal.scripts.JO;
@@ -168,63 +169,63 @@ public final class NativeJSAdapter extends ScriptObject {
}
@Override
- public int getInt(final Object key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final Object key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public int getInt(final double key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final double key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public int getInt(final long key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final long key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public int getInt(final int key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+ public int getInt(final int key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public long getLong(final Object key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final Object key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public long getLong(final double key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final double key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public long getLong(final long key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final long key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public long getLong(final int key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+ public long getLong(final int key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
}
@Override
- public double getDouble(final Object key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final Object key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
- public double getDouble(final double key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final double key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
- public double getDouble(final long key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final long key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
- public double getDouble(final int key) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+ public double getDouble(final int key, final int programPoint) {
+ return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@Override
@@ -577,7 +578,7 @@ public final class NativeJSAdapter extends ScriptObject {
}
@Override
- protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
+ protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
return findHook(desc, __new__, false);
}
@@ -625,8 +626,8 @@ public final class NativeJSAdapter extends ScriptObject {
// to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
- adaptee.getProtoSwitchPoint(__call__, find.getOwner()),
- testJSAdaptor(adaptee, null, null, null));
+ testJSAdaptor(adaptee, null, null, null),
+ adaptee.getProtoSwitchPoint(__call__, find.getOwner()));
}
}
throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
@@ -658,16 +659,16 @@ public final class NativeJSAdapter extends ScriptObject {
return callAdaptee(UNDEFINED, name, args);
}
- private double callAdapteeDouble(final String name, final Object... args) {
- return JSType.toNumber(callAdaptee(name, args));
+ private double callAdapteeDouble(final int programPoint, final String name, final Object... args) {
+ return JSType.toNumberMaybeOptimistic(callAdaptee(name, args), programPoint);
}
- private long callAdapteeLong(final String name, final Object... args) {
- return JSType.toLong(callAdaptee(name, args));
+ private long callAdapteeLong(final int programPoint, final String name, final Object... args) {
+ return JSType.toLongMaybeOptimistic(callAdaptee(name, args), programPoint);
}
- private int callAdapteeInt(final String name, final Object... args) {
- return JSType.toInt32(callAdaptee(name, args));
+ private int callAdapteeInt(final int programPoint, final String name, final Object... args) {
+ return JSType.toInt32MaybeOptimistic(callAdaptee(name, args), programPoint);
}
private Object callAdaptee(final Object retValue, final String name, final Object... args) {
@@ -696,8 +697,8 @@ public final class NativeJSAdapter extends ScriptObject {
if (methodHandle != null) {
return new GuardedInvocation(
methodHandle,
- adaptee.getProtoSwitchPoint(hook, findData.getOwner()),
- testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
+ testJSAdaptor(adaptee, findData.getGetter(Object.class, UnwarrantedOptimismException.INVALID_PROGRAM_POINT), findData.getOwner(), func),
+ adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
}
}
}
@@ -709,7 +710,7 @@ public final class NativeJSAdapter extends ScriptObject {
final MethodHandle methodHandle = hook.equals(__put__) ?
MH.asType(Lookup.EMPTY_SETTER, type) :
Lookup.emptyGetter(type.returnType());
- return new GuardedInvocation(methodHandle, adaptee.getProtoSwitchPoint(hook, null), testJSAdaptor(adaptee, null, null, null));
+ return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoint(hook, null));
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJava.java b/src/jdk/nashorn/internal/objects/NativeJava.java
index be0349af..4395e081 100644
--- a/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -36,6 +36,7 @@ import java.util.List;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.support.TypeUtilities;
import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptUtils;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -44,6 +45,7 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ListAdapter;
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.linker.Bootstrap;
@@ -80,6 +82,73 @@ public final class NativeJava {
}
/**
+ * Returns synchronized wrapper version of the given ECMAScript function.
+ * @param self not used
+ * @param func the ECMAScript function whose synchronized version is returned.
+ * @param obj the object (i.e, lock) on which the function synchronizes.
+ * @return synchronized wrapper version of the given ECMAScript function.
+ */
+ @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
+ return ScriptUtils.makeSynchronizedFunction(func, obj);
+ }
+
+ /**
+ * Returns true if the specified object is a Java method.
+ * @param self not used
+ * @param obj the object that is checked if it is a Java method object or not
+ * @return tells whether given object is a Java method object or not.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isJavaMethod(final Object self, final Object obj) {
+ return Bootstrap.isDynamicMethod(obj);
+ }
+
+ /**
+ * Returns true if the specified object is a java function (but not script function)
+ * @param self not used
+ * @param obj the object that is checked if it is a Java function or not
+ * @return tells whether given object is a Java function or not
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isJavaFunction(final Object self, final Object obj) {
+ return Bootstrap.isCallable(obj) && !(obj instanceof ScriptFunction);
+ }
+
+ /**
+ * Returns true if the specified object is a Java object but not a script object
+ * @param self not used
+ * @param obj the object that is checked
+ * @return tells whether given object is a Java object but not a script object
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isJavaObject(final Object self, final Object obj) {
+ return obj != null && !(obj instanceof ScriptObject);
+ }
+
+ /**
+ * Returns true if the specified object is a ECMAScript object, that is an instance of {@link ScriptObject}.
+ * @param self not used
+ * @param obj the object that is checked if it is a ECMAScript object or not
+ * @return tells whether given object is a ECMAScript object or not.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isScriptObject(final Object self, final Object obj) {
+ return obj instanceof ScriptObject;
+ }
+
+ /**
+ * Returns true if the specified object is a ECMAScript function, that is an instance of {@link ScriptFunction}.
+ * @param self not used
+ * @param obj the object that is checked if it is a ECMAScript function or not
+ * @return tells whether given object is a ECMAScript function or not.
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static boolean isScriptFunction(final Object self, final Object obj) {
+ return obj instanceof ScriptFunction;
+ }
+
+ /**
* <p>
* Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
* used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
diff --git a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
index 40ecbffc..1443c943 100644
--- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -37,6 +39,7 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
/**
* This is "JavaImporter" constructor. This constructor allows you to use Java types omitting explicit package names.
@@ -131,8 +134,12 @@ public final class NativeJavaImporter extends ScriptObject {
}
@Override
- protected Object invokeNoSuchProperty(final String name) {
- return createProperty(name);
+ protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+ final Object retval = createProperty(name);
+ if (isValid(programPoint)) {
+ throw new UnwarrantedOptimismException(retval, programPoint);
+ }
+ return retval;
}
private boolean createAndSetProperty(final CallSiteDescriptor desc) {
diff --git a/src/jdk/nashorn/internal/objects/NativeMath.java b/src/jdk/nashorn/internal/objects/NativeMath.java
index ec53965a..83b336ca 100644
--- a/src/jdk/nashorn/internal/objects/NativeMath.java
+++ b/src/jdk/nashorn/internal/objects/NativeMath.java
@@ -489,6 +489,20 @@ public final class NativeMath extends ScriptObject {
}
/**
+ * ECMA 15.8.2.11 max(x) - specialized version for two Object args
+ *
+ * @param self self reference
+ * @param x first argument
+ * @param y second argument
+ *
+ * @return largest value of x and y
+ */
+ @SpecializedFunction
+ public static double max(final Object self, final Object x, final Object y) {
+ return Math.max(JSType.toNumber(x), JSType.toNumber(y));
+ }
+
+ /**
* ECMA 15.8.2.12 min(x)
*
* @param self self reference
@@ -567,6 +581,20 @@ public final class NativeMath extends ScriptObject {
}
/**
+ * ECMA 15.8.2.12 min(x) - specialized version for two Object args
+ *
+ * @param self self reference
+ * @param x first argument
+ * @param y second argument
+ *
+ * @return smallest value of x and y
+ */
+ @SpecializedFunction
+ public static double min(final Object self, final Object x, final Object y) {
+ return Math.min(JSType.toNumber(x), JSType.toNumber(y));
+ }
+
+ /**
* ECMA 15.8.2.13 pow(x,y)
*
* @param self self reference
diff --git a/src/jdk/nashorn/internal/objects/NativeNumber.java b/src/jdk/nashorn/internal/objects/NativeNumber.java
index 163a3085..b4cff41e 100644
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java
+++ b/src/jdk/nashorn/internal/objects/NativeNumber.java
@@ -28,8 +28,6 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
-import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsLong;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
@@ -44,6 +42,7 @@ import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -84,8 +83,6 @@ public final class NativeNumber extends ScriptObject {
public static final double POSITIVE_INFINITY = Double.POSITIVE_INFINITY;
private final double value;
- private final boolean isInt;
- private final boolean isLong;
// initialized by nasgen
private static PropertyMap $nasgenmap$;
@@ -93,8 +90,6 @@ public final class NativeNumber extends ScriptObject {
private NativeNumber(final double value, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.value = value;
- this.isInt = isRepresentableAsInt(value);
- this.isLong = isRepresentableAsLong(value);
}
NativeNumber(final double value, final Global global) {
@@ -132,30 +127,6 @@ public final class NativeNumber extends ScriptObject {
return value;
}
- /**
- * Get the value of this Number as a {@code int}
- * @return an {@code int} representing the Number value
- * @throws ClassCastException If number is not representable as an {@code int}
- */
- public int intValue() throws ClassCastException {
- if (isInt) {
- return (int)value;
- }
- throw new ClassCastException();
- }
-
- /**
- * Get the value of this Number as a {@code long}
- * @return a {@code long} representing the Number value
- * @throws ClassCastException If number is not representable as an {@code long}
- */
- public long longValue() throws ClassCastException {
- if (isLong) {
- return (long)value;
- }
- throw new ClassCastException();
- }
-
@Override
public String getClassName() {
return "Number";
@@ -186,8 +157,20 @@ public final class NativeNumber extends ScriptObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static String toFixed(final Object self, final Object fractionDigits) {
- final int f = JSType.toInteger(fractionDigits);
- if (f < 0 || f > 20) {
+ return toFixed(self, JSType.toInteger(fractionDigits));
+ }
+
+ /**
+ * ECMA 15.7.4.5 Number.prototype.toFixed (fractionDigits) specialized for int fractionDigits
+ *
+ * @param self self reference
+ * @param fractionDigits how many digits should be after the decimal point, 0 if undefined
+ *
+ * @return number in decimal fixed point notation
+ */
+ @SpecializedFunction
+ public static String toFixed(final Object self, final int fractionDigits) {
+ if (fractionDigits < 0 || fractionDigits > 20) {
throw rangeError("invalid.fraction.digits", "toFixed");
}
@@ -201,8 +184,8 @@ public final class NativeNumber extends ScriptObject {
}
final NumberFormat format = NumberFormat.getNumberInstance(Locale.US);
- format.setMinimumFractionDigits(f);
- format.setMaximumFractionDigits(f);
+ format.setMinimumFractionDigits(fractionDigits);
+ format.setMaximumFractionDigits(fractionDigits);
format.setGroupingUsed(false);
return format.format(x);
@@ -240,7 +223,7 @@ public final class NativeNumber extends ScriptObject {
* ECMA 15.7.4.7 Number.prototype.toPrecision (precision)
*
* @param self self reference
- * @param precision use {@code precision - 1} digits after the significand's decimal point or call {@link NativeDate#toString} if undefined
+ * @param precision use {@code precision - 1} digits after the significand's decimal point or call {@link JSType#toString} if undefined
*
* @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
*/
@@ -250,8 +233,23 @@ public final class NativeNumber extends ScriptObject {
if (precision == UNDEFINED) {
return JSType.toString(x);
}
+ return (toPrecision(x, JSType.toInteger(precision)));
+ }
+
+ /**
+ * ECMA 15.7.4.7 Number.prototype.toPrecision (precision) specialized f
+ *
+ * @param self self reference
+ * @param precision use {@code precision - 1} digits after the significand's decimal point.
+ *
+ * @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
+ */
+ @SpecializedFunction
+ public static String toPrecision(final Object self, final int precision) {
+ return toPrecision(getNumberValue(self), precision);
+ }
- final int p = JSType.toInteger(precision);
+ private static String toPrecision(final double x, final int p) {
if (Double.isNaN(x)) {
return "NaN";
} else if (Double.isInfinite(x)) {
diff --git a/src/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk/nashorn/internal/objects/NativeObject.java
index 8047e5f0..5667e6ac 100644
--- a/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -75,7 +75,10 @@ import jdk.nashorn.internal.runtime.linker.NashornBeansLinker;
*/
@ScriptClass("Object")
public final class NativeObject {
+ /** Methodhandle to proto getter */
public static final MethodHandle GET__PROTO__ = findOwnMH("get__proto__", ScriptObject.class, Object.class);
+
+ /** Methodhandle to proto setter */
public static final MethodHandle SET__PROTO__ = findOwnMH("set__proto__", Object.class, Object.class, Object.class);
private static final Object TO_STRING = new Object();
@@ -94,9 +97,7 @@ public final class NativeObject {
private static ScriptObject get__proto__(final Object self) {
// See ES6 draft spec: B.2.2.1.1 get Object.prototype.__proto__
// Step 1 Let O be the result of calling ToObject passing the this.
- final Object obj = Global.toObject(self);
- Global.checkObject(obj);
- final ScriptObject sobj = (ScriptObject)obj;
+ final ScriptObject sobj = Global.checkObject(Global.toObject(self));
return sobj.getProto();
}
@@ -282,8 +283,7 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
- Global.checkObject(obj);
- final ScriptObject sobj = (ScriptObject)obj;
+ final ScriptObject sobj = Global.checkObject(obj);
sobj.defineOwnProperty(JSType.toString(prop), attr, true);
return sobj;
}
@@ -298,9 +298,7 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
- Global.checkObject(obj);
-
- final ScriptObject sobj = (ScriptObject)obj;
+ final ScriptObject sobj = Global.checkObject(obj);
final Object propsObj = Global.toObject(props);
if (propsObj instanceof ScriptObject) {
@@ -454,18 +452,17 @@ public final class NativeObject {
*/
@Constructor
public static Object construct(final boolean newObj, final Object self, final Object value) {
- final JSType type = JSType.of(value);
+ final JSType type = JSType.ofNoFunction(value);
// Object(null), Object(undefined), Object() are same as "new Object()"
- if (newObj || (type == JSType.NULL || type == JSType.UNDEFINED)) {
+ if (newObj || type == JSType.NULL || type == JSType.UNDEFINED) {
switch (type) {
case BOOLEAN:
case NUMBER:
case STRING:
return Global.toObject(value);
case OBJECT:
- case FUNCTION:
return value;
case NULL:
case UNDEFINED:
@@ -546,7 +543,7 @@ public final class NativeObject {
final Object key = JSType.toPrimitive(v, String.class);
final Object obj = Global.toObject(self);
- return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(key);
+ return obj instanceof ScriptObject && ((ScriptObject)obj).hasOwnProperty(key);
}
/**
@@ -660,25 +657,29 @@ public final class NativeObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object bindProperties(final Object self, final Object target, final Object source) {
// target object has to be a ScriptObject
- Global.checkObject(target);
+ final ScriptObject targetObj = Global.checkObject(target);
// check null or undefined source object
Global.checkObjectCoercible(source);
- final ScriptObject targetObj = (ScriptObject)target;
-
if (source instanceof ScriptObject) {
- final ScriptObject sourceObj = (ScriptObject)source;
- final Property[] properties = sourceObj.getMap().getProperties();
+ final ScriptObject sourceObj = (ScriptObject)source;
+
+ final PropertyMap sourceMap = sourceObj.getMap();
+ final Property[] properties = sourceMap.getProperties();
+ //replace the map and blow up everything to objects to work with dual fields :-(
// filter non-enumerable properties
final ArrayList<Property> propList = new ArrayList<>();
for (final Property prop : properties) {
if (prop.isEnumerable()) {
+ final Object value = sourceObj.get(prop.getKey());
+ prop.setCurrentType(Object.class);
+ prop.setValue(sourceObj, sourceObj, value, false);
propList.add(prop);
}
}
- if (! propList.isEmpty()) {
+ if (!propList.isEmpty()) {
targetObj.addBoundProperties(sourceObj, propList.toArray(new Property[propList.size()]));
}
} else if (source instanceof ScriptObjectMirror) {
@@ -696,7 +697,7 @@ public final class NativeObject {
final String name = keys[idx];
final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
- props[idx] = (AccessorProperty.create(name, 0, getter, setter));
+ props[idx] = AccessorProperty.create(name, 0, getter, setter);
}
targetObj.addBoundProperties(source, props);
@@ -715,6 +716,32 @@ public final class NativeObject {
return target;
}
+ /**
+ * Binds the source mirror object's properties to the target object. Binding
+ * properties allows two-way read/write for the properties of the source object.
+ * All inherited, enumerable properties are also bound. This method is used to
+ * to make 'with' statement work with ScriptObjectMirror as scope object.
+ *
+ * @param target the target object to which the source object's properties are bound
+ * @param source the source object whose properties are bound to the target
+ * @return the target object after property binding
+ */
+ public static Object bindAllProperties(final ScriptObject target, final ScriptObjectMirror source) {
+ final Set<String> keys = source.keySet();
+ // make accessor properties using dynamic invoker getters and setters
+ final AccessorProperty[] props = new AccessorProperty[keys.size()];
+ int idx = 0;
+ for (final String name : keys) {
+ final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
+ final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
+ props[idx] = AccessorProperty.create(name, 0, getter, setter);
+ idx++;
+ }
+
+ target.addBoundProperties(source, props);
+ return target;
+ }
+
private static void bindBeanProperties(final ScriptObject targetObj, final Object source,
final Collection<String> readablePropertyNames, final Collection<String> writablePropertyNames,
final Collection<String> methodNames) {
@@ -797,7 +824,7 @@ public final class NativeObject {
} catch(final Throwable t) {
throw new RuntimeException(t);
}
- assert inv.getSwitchPoint() == null; // Linkers in Dynalink's beans package don't use switchpoints.
+ assert inv.getSwitchPoints() == null; // Linkers in Dynalink's beans package don't use switchpoints.
// We discard the guard, as all method handles will be bound to a specific object.
return inv.getInvocation();
}
@@ -808,10 +835,10 @@ public final class NativeObject {
private static LinkRequest createLinkRequest(final String operation, final MethodType methodType, final Object source) {
return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation,
- methodType), false, source);
+ methodType), null, 0, false, source);
}
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types));
+ return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types));
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExp.java b/src/jdk/nashorn/internal/objects/NativeRegExp.java
index be016705..01806d44 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java
@@ -28,9 +28,11 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.Callable;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -46,6 +48,7 @@ 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.linker.Bootstrap;
import jdk.nashorn.internal.runtime.regexp.RegExp;
import jdk.nashorn.internal.runtime.regexp.RegExpFactory;
import jdk.nashorn.internal.runtime.regexp.RegExpMatcher;
@@ -595,7 +598,7 @@ public final class NativeRegExp extends ScriptObject {
for (int i = 0, lastGroupStart = matcher.start(); i <= groupCount; i++) {
final int groupStart = matcher.start(i);
if (lastGroupStart > groupStart
- || (groupsInNegativeLookahead != null && groupsInNegativeLookahead.isSet(i))) {
+ || groupsInNegativeLookahead != null && groupsInNegativeLookahead.isSet(i)) {
// (1) ECMA 15.10.2.5 NOTE 3: need to clear Atom's captures each time Atom is repeated.
// (2) ECMA 15.10.2.8 NOTE 3: Backreferences to captures in (?!Disjunction) from elsewhere
// in the pattern always return undefined because the negative lookahead must fail.
@@ -648,7 +651,7 @@ public final class NativeRegExp extends ScriptObject {
* @param replacement Replacement string.
* @return String with substitutions.
*/
- String replace(final String string, final String replacement, final ScriptFunction function) {
+ String replace(final String string, final String replacement, final ScriptFunction function) throws Throwable {
final RegExpMatcher matcher = regexp.match(string);
if (matcher == null) {
@@ -664,7 +667,8 @@ public final class NativeRegExp extends ScriptObject {
sb.append(string, 0, matcher.start());
if (function != null) {
- sb.append(callReplaceValue(function, matcher, string));
+ final Object self = function.isStrict() ? UNDEFINED : Global.instance();
+ sb.append(callReplaceValue(getReplaceValueInvoker(), function, self, matcher, string));
} else {
appendReplacement(matcher, string, replacement, sb);
}
@@ -682,10 +686,13 @@ public final class NativeRegExp extends ScriptObject {
int previousLastIndex = 0;
final StringBuilder sb = new StringBuilder();
+ final MethodHandle invoker = function == null ? null : getReplaceValueInvoker();
+ final Object self = function == null || function.isStrict() ? UNDEFINED : Global.instance();
+
do {
sb.append(string, thisIndex, matcher.start());
if (function != null) {
- sb.append(callReplaceValue(function, matcher, string));
+ sb.append(callReplaceValue(invoker, function, self, matcher, string));
} else {
appendReplacement(matcher, string, replacement, sb);
}
@@ -745,8 +752,8 @@ public final class NativeRegExp extends ScriptObject {
cursor++;
if (cursor < replacement.length() && firstDigit < matcher.groupCount()) {
final int secondDigit = replacement.charAt(cursor) - '0';
- if ((secondDigit >= 0) && (secondDigit <= 9)) {
- final int newRefNum = (firstDigit * 10) + secondDigit;
+ if (secondDigit >= 0 && secondDigit <= 9) {
+ final int newRefNum = firstDigit * 10 + secondDigit;
if (newRefNum <= matcher.groupCount() && newRefNum > 0) {
// $nn ($01-$99)
refNum = newRefNum;
@@ -789,16 +796,26 @@ public final class NativeRegExp extends ScriptObject {
}
}
- private String callReplaceValue(final ScriptFunction function, final RegExpMatcher matcher, final String string) {
+ private static final Object REPLACE_VALUE = new Object();
+
+ private static final MethodHandle getReplaceValueInvoker() {
+ return Global.instance().getDynamicInvoker(REPLACE_VALUE,
+ new Callable<MethodHandle>() {
+ @Override
+ public MethodHandle call() {
+ return Bootstrap.createDynamicInvoker("dyn:call", String.class, ScriptFunction.class, Object.class, Object[].class);
+ }
+ });
+ }
+
+ private String callReplaceValue(final MethodHandle invoker, final ScriptFunction function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable {
final Object[] groups = groups(matcher);
final Object[] args = Arrays.copyOf(groups, groups.length + 2);
args[groups.length] = matcher.start();
args[groups.length + 1] = string;
- final Object self = function.isStrict() ? UNDEFINED : Global.instance();
-
- return JSType.toString(ScriptRuntime.apply(function, self, args));
+ return (String)invoker.invokeExact(function, self, args);
}
/**
@@ -907,7 +924,6 @@ public final class NativeRegExp extends ScriptObject {
}
private static NativeRegExp checkRegExp(final Object self) {
- Global.checkObjectCoercible(self);
if (self instanceof NativeRegExp) {
return (NativeRegExp)self;
} else if (self != null && self == Global.instance().getRegExpPrototype()) {
diff --git a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
index 5e65568c..7f32c10f 100644
--- a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
+++ b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
@@ -79,8 +79,9 @@ public final class NativeStrictArguments extends ScriptObject {
final ScriptFunction func = Global.instance().getTypeErrorThrower();
// We have to fill user accessor functions late as these are stored
// in this object rather than in the PropertyMap of this object.
- setUserAccessors("caller", func, func);
- setUserAccessors("callee", func, func);
+ final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
+ initUserAccessors("caller", flags, func, func);
+ initUserAccessors("callee", flags, func, func);
setArray(ArrayData.allocate(values));
this.length = values.length;
diff --git a/src/jdk/nashorn/internal/objects/NativeString.java b/src/jdk/nashorn/internal/objects/NativeString.java
index b7f62303..0ae7fdc8 100644
--- a/src/jdk/nashorn/internal/objects/NativeString.java
+++ b/src/jdk/nashorn/internal/objects/NativeString.java
@@ -39,6 +39,7 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
@@ -155,10 +156,9 @@ public final class NativeString extends ScriptObject {
if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) {
try {
- final MethodHandle mh = MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType());
- return new GuardedInvocation(mh, NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
+ return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
} catch (final LookupException e) {
- // Shouldn't happen. Fall back to super
+ //empty. Shouldn't happen. Fall back to super
}
}
return super.findGetIndexMethod(desc, request);
@@ -236,111 +236,111 @@ public final class NativeString extends ScriptObject {
}
@Override
- public int getInt(final Object key) {
- return JSType.toInt32(get(key));
+ public int getInt(final Object key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public int getInt(final double key) {
- return JSType.toInt32(get(key));
+ public int getInt(final double key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public int getInt(final long key) {
- return JSType.toInt32(get(key));
+ public int getInt(final long key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public int getInt(final int key) {
- return JSType.toInt32(get(key));
+ public int getInt(final int key, final int programPoint) {
+ return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final Object key) {
- return JSType.toUint32(get(key));
+ public long getLong(final Object key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final double key) {
- return JSType.toUint32(get(key));
+ public long getLong(final double key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final long key) {
- return JSType.toUint32(get(key));
+ public long getLong(final long key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final int key) {
- return JSType.toUint32(get(key));
+ public long getLong(final int key, final int programPoint) {
+ return JSType.toLongMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final Object key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final Object key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final double key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final double key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final long key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final long key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
- public double getDouble(final int key) {
- return JSType.toNumber(get(key));
+ public double getDouble(final int key, final int programPoint) {
+ return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@Override
public boolean has(final Object key) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
final int index = ArrayIndex.getArrayIndex(primitiveKey);
- return isValid(index) || super.has(primitiveKey);
+ return isValidStringIndex(index) || super.has(primitiveKey);
}
@Override
public boolean has(final int key) {
- return isValid(key) || super.has(key);
+ return isValidStringIndex(key) || super.has(key);
}
@Override
public boolean has(final long key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.has(key);
+ return isValidStringIndex(index) || super.has(key);
}
@Override
public boolean has(final double key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.has(key);
+ return isValidStringIndex(index) || super.has(key);
}
@Override
public boolean hasOwnProperty(final Object key) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
final int index = ArrayIndex.getArrayIndex(primitiveKey);
- return isValid(index) || super.hasOwnProperty(primitiveKey);
+ return isValidStringIndex(index) || super.hasOwnProperty(primitiveKey);
}
@Override
public boolean hasOwnProperty(final int key) {
- return isValid(key) || super.hasOwnProperty(key);
+ return isValidStringIndex(key) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final long key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.hasOwnProperty(key);
+ return isValidStringIndex(index) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final double key) {
final int index = ArrayIndex.getArrayIndex(key);
- return isValid(index) || super.hasOwnProperty(key);
+ return isValidStringIndex(index) || super.hasOwnProperty(key);
}
@Override
@@ -368,7 +368,7 @@ public final class NativeString extends ScriptObject {
}
private boolean checkDeleteIndex(final int index, final boolean strict) {
- if (isValid(index)) {
+ if (isValidStringIndex(index)) {
if (strict) {
throw typeError("cant.delete.property", Integer.toString(index), ScriptRuntime.safeToString(this));
}
@@ -392,10 +392,12 @@ public final class NativeString extends ScriptObject {
/**
* return a List of own keys associated with the object.
* @param all True if to include non-enumerable keys.
+ * @param nonEnumerable set of non-enumerable properties seen already.Used
+ * to filter out shadowed, but enumerable properties from proto children.
* @return Array of keys.
*/
@Override
- public String[] getOwnKeys(final boolean all) {
+ protected String[] getOwnKeys(final boolean all, final Set<String> nonEnumerable) {
final List<Object> keys = new ArrayList<>();
// add string index keys
@@ -404,7 +406,7 @@ public final class NativeString extends ScriptObject {
}
// add super class properties
- keys.addAll(Arrays.asList(super.getOwnKeys(all)));
+ keys.addAll(Arrays.asList(super.getOwnKeys(all, nonEnumerable)));
return keys.toArray(new String[keys.size()]);
}
@@ -441,12 +443,11 @@ public final class NativeString extends ScriptObject {
* @return string with one charcode
*/
@SpecializedFunction
- public static String fromCharCode(final Object self, final Object value) {
- try {
- return "" + (char)JSType.toUint16(((Number)value).doubleValue());
- } catch (final ClassCastException e) {
- return fromCharCode(self, new Object[] { value });
+ public static Object fromCharCode(final Object self, final Object value) {
+ if (value instanceof Integer) {
+ return fromCharCode(self, (int)value);
}
+ return Character.toString((char)JSType.toUint16(value));
}
/**
@@ -457,18 +458,46 @@ public final class NativeString extends ScriptObject {
*/
@SpecializedFunction
public static String fromCharCode(final Object self, final int value) {
- return "" + (char)(value & 0xffff);
+ return Character.toString((char)(value & 0xffff));
}
/**
- * ECMA 15.5.3.2 - specialization for one char of long type
+ * ECMA 15.5.3.2 - specialization for two chars of int type
* @param self self reference
- * @param value one argument to be interpreted as char
+ * @param ch1 first char
+ * @param ch2 second char
+ * @return string with one charcode
+ */
+ @SpecializedFunction
+ public static Object fromCharCode(final Object self, final int ch1, final int ch2) {
+ return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff));
+ }
+
+ /**
+ * ECMA 15.5.3.2 - specialization for three chars of int type
+ * @param self self reference
+ * @param ch1 first char
+ * @param ch2 second char
+ * @param ch3 third char
+ * @return string with one charcode
+ */
+ @SpecializedFunction
+ public static Object fromCharCode(final Object self, final int ch1, final int ch2, final int ch3) {
+ return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff)) + Character.toString((char)(ch3 & 0xffff));
+ }
+
+ /**
+ * ECMA 15.5.3.2 - specialization for four chars of int type
+ * @param self self reference
+ * @param ch1 first char
+ * @param ch2 second char
+ * @param ch3 third char
+ * @param ch4 fourth char
* @return string with one charcode
*/
@SpecializedFunction
- public static String fromCharCode(final Object self, final long value) {
- return "" + (char)((int)value & 0xffff);
+ public static String fromCharCode(final Object self, final int ch1, final int ch2, final int ch3, final int ch4) {
+ return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff)) + Character.toString((char)(ch3 & 0xffff)) + Character.toString((char)(ch4 & 0xffff));
}
/**
@@ -479,7 +508,7 @@ public final class NativeString extends ScriptObject {
*/
@SpecializedFunction
public static String fromCharCode(final Object self, final double value) {
- return "" + (char)JSType.toUint16(value);
+ return Character.toString((char)JSType.toUint16(value));
}
/**
@@ -536,7 +565,7 @@ public final class NativeString extends ScriptObject {
}
private static String charAtImpl(final String str, final int pos) {
- return (pos < 0 || pos >= str.length()) ? "" : String.valueOf(str.charAt(pos));
+ return pos < 0 || pos >= str.length() ? "" : String.valueOf(str.charAt(pos));
}
/**
@@ -573,7 +602,7 @@ public final class NativeString extends ScriptObject {
}
private static double charCodeAtImpl(final String str, final int pos) {
- return (pos < 0 || pos >= str.length()) ? Double.NaN : str.charAt(pos);
+ return pos < 0 || pos >= str.length() ? Double.NaN : str.charAt(pos);
}
/**
@@ -688,7 +717,7 @@ public final class NativeString extends ScriptObject {
collator.setStrength(Collator.IDENTICAL);
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
- return (double)collator.compare(str, JSType.toString(that));
+ return collator.compare(str, JSType.toString(that));
}
/**
@@ -743,9 +772,10 @@ public final class NativeString extends ScriptObject {
* @param string item to replace
* @param replacement item to replace it with
* @return string after replacement
+ * @throws Throwable if replacement fails
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String replace(final Object self, final Object string, final Object replacement) {
+ public static String replace(final Object self, final Object string, final Object replacement) throws Throwable {
final String str = checkObjectToString(self);
@@ -807,7 +837,7 @@ public final class NativeString extends ScriptObject {
@SpecializedFunction
public static String slice(final Object self, final int start) {
final String str = checkObjectToString(self);
- final int from = (start < 0) ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
+ final int from = start < 0 ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
return str.substring(from);
}
@@ -838,8 +868,8 @@ public final class NativeString extends ScriptObject {
final String str = checkObjectToString(self);
final int len = str.length();
- final int from = (start < 0) ? Math.max(len + start, 0) : Math.min(start, len);
- final int to = (end < 0) ? Math.max(len + end, 0) : Math.min(end, len);
+ final int from = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
+ final int to = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);
return str.substring(Math.min(from, to), to);
}
@@ -868,7 +898,7 @@ public final class NativeString extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static ScriptObject split(final Object self, final Object separator, final Object limit) {
final String str = checkObjectToString(self);
- final long lim = (limit == UNDEFINED) ? JSType.MAX_UINT : JSType.toUint32(limit);
+ final long lim = limit == UNDEFINED ? JSType.MAX_UINT : JSType.toUint32(limit);
if (separator == UNDEFINED) {
return lim == 0 ? new NativeArray() : new NativeArray(new Object[]{str});
@@ -932,7 +962,7 @@ public final class NativeString extends ScriptObject {
intStart = Math.max(intStart + strLength, 0);
}
- final int intLen = Math.min(Math.max((length == UNDEFINED) ? Integer.MAX_VALUE : JSType.toInteger(length), 0), strLength - intStart);
+ final int intLen = Math.min(Math.max(length == UNDEFINED ? Integer.MAX_VALUE : JSType.toInteger(length), 0), strLength - intStart);
return intLen <= 0 ? "" : str.substring(intStart, intStart + intLen);
}
@@ -998,8 +1028,8 @@ public final class NativeString extends ScriptObject {
public static String substring(final Object self, final int start, final int end) {
final String str = checkObjectToString(self);
final int len = str.length();
- final int validStart = start < 0 ? 0 : (start > len ? len : start);
- final int validEnd = end < 0 ? 0 : (end > len ? len : end);
+ final int validStart = start < 0 ? 0 : start > len ? len : start;
+ final int validEnd = end < 0 ? 0 : end > len ? len : end;
if (validStart < validEnd) {
return str.substring(validStart, validEnd);
@@ -1120,7 +1150,7 @@ public final class NativeString extends ScriptObject {
return str.substring(start, end + 1);
}
- private static ScriptObject newObj(final Object self, final CharSequence str) {
+ private static ScriptObject newObj(final CharSequence str) {
return new NativeString(str);
}
@@ -1137,8 +1167,8 @@ public final class NativeString extends ScriptObject {
*/
@Constructor(arity = 1)
public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- final CharSequence str = (args.length > 0) ? JSType.toCharSequence(args[0]) : "";
- return newObj ? newObj(self, str) : str.toString();
+ final CharSequence str = args.length > 0 ? JSType.toCharSequence(args[0]) : "";
+ return newObj ? newObj(str) : str.toString();
}
/**
@@ -1153,7 +1183,7 @@ public final class NativeString extends ScriptObject {
*/
@SpecializedConstructor
public static Object constructor(final boolean newObj, final Object self) {
- return newObj ? newObj(self, "") : "";
+ return newObj ? newObj("") : "";
}
/**
@@ -1170,7 +1200,7 @@ public final class NativeString extends ScriptObject {
@SpecializedConstructor
public static Object constructor(final boolean newObj, final Object self, final Object arg) {
final CharSequence str = JSType.toCharSequence(arg);
- return newObj ? newObj(self, str) : str.toString();
+ return newObj ? newObj(str) : str.toString();
}
/**
@@ -1187,7 +1217,24 @@ public final class NativeString extends ScriptObject {
@SpecializedConstructor
public static Object constructor(final boolean newObj, final Object self, final int arg) {
final String str = JSType.toString(arg);
- return newObj ? newObj(self, str) : str;
+ return newObj ? newObj(str) : str;
+ }
+
+ /**
+ * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code boolean} arg
+ *
+ * Constructor
+ *
+ * @param newObj is this constructor invoked with the new operator
+ * @param self self reference
+ * @param arg the arg
+ *
+ * @return new NativeString containing the string representation of the arg
+ */
+ @SpecializedConstructor
+ public static Object constructor(final boolean newObj, final Object self, final boolean arg) {
+ final String str = JSType.toString(arg);
+ return newObj ? newObj(str) : str;
}
/**
@@ -1255,11 +1302,12 @@ public final class NativeString extends ScriptObject {
}
}
- private boolean isValid(final int key) {
+ private boolean isValidStringIndex(final int key) {
return key >= 0 && key < value.length();
}
private static MethodHandle findOwnMH(final String name, final MethodType type) {
return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type);
}
+
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint16Array.java b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
index 8aa3d628..68bd410c 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
@@ -25,15 +25,23 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint16 array for TypedArray extension
@@ -55,37 +63,100 @@ public final class NativeUint16Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeUint16Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Uint16ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint16ArrayData(nb.asCharBuffer(), start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint16ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Uint16Array";
}
};
- private static final class Uint16ArrayData extends ArrayDataImpl {
- private Uint16ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint16ArrayData extends TypedArrayData<CharBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint16ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint16ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Uint16ArrayData(final CharBuffer nb, final int start, final int end) {
+ super(((CharBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index);
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (char)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public boolean isUnsigned() {
+ return true;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public Object getObject(final int index) {
+ return getInt(index);
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 ;
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- @SuppressWarnings("MismatchedReadAndWriteOfArray")
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -100,7 +171,7 @@ public final class NativeUint16Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint16Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint16Array)constructorImpl(args, FACTORY);
+ return (NativeUint16Array)constructorImpl(newObj, args, FACTORY);
}
NativeUint16Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -108,11 +179,6 @@ public final class NativeUint16Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint16Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint32Array.java b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
index 73812246..47ee08da 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
@@ -25,6 +25,13 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +42,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint32 array for TypedArray extension
@@ -56,55 +64,108 @@ public final class NativeUint32Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteBegin, final int length) {
return new NativeUint32Array(buffer, byteBegin, length);
}
+
+ @Override
+ public Uint32ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint32ArrayData(nb.order(ByteOrder.nativeOrder()).asIntBuffer(), start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint32ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Uint32Array";
}
};
- private static final class Uint32ArrayData extends ArrayDataImpl {
- private Uint32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint32ArrayData extends TypedArrayData<IntBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "getElem", long.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Uint32ArrayData(final IntBuffer nb, final int start, final int end) {
+ super(((IntBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ @Override
+ public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+ if (returnType == int.class) {
+ return null;
+ }
+ return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
+ }
+
+ private long getElem(final int index) {
+ try {
+ return nb.get(index) & JSType.MAX_UINT;
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public boolean isUnsigned() {
+ return true;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return (int)getLong(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getElem(index);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public double getDouble(final int index) {
+ return getLong(index);
}
@Override
- protected int getIntImpl(final int index) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- return byteArray[byteIndex ] & 0x0000_00ff |
- byteArray[byteIndex+1] << 8 & 0x0000_ff00 |
- byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
- byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
+ public Object getObject(final int index) {
+ return getLong(index);
}
@Override
- protected long getLongImpl(final int key) {
- return getIntImpl(key) & JSType.MAX_UINT;
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
}
@Override
- protected double getDoubleImpl(final int key) {
- return getIntImpl(key) & JSType.MAX_UINT;
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
}
@Override
- protected Object getObjectImpl(final int key) {
- return getIntImpl(key) & JSType.MAX_UINT;
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
}
@Override
- protected void setImpl(final int index, final int value) {
- final int byteIndex = byteIndex(index);
- final byte[] byteArray = buffer.getByteArray();
- byteArray[byteIndex ] = (byte)(value & 0xff);
- byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
- byteArray[byteIndex+2] = (byte)(value >>> 16 & 0xff);
- byteArray[byteIndex+3] = (byte)(value >>> 24 & 0xff);
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
}
}
@@ -119,7 +180,7 @@ public final class NativeUint32Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint32Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint32Array)constructorImpl(args, FACTORY);
+ return (NativeUint32Array)constructorImpl(newObj, args, FACTORY);
}
NativeUint32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -127,11 +188,6 @@ public final class NativeUint32Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint32Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8Array.java b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
index 1f304563..15e01245 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
@@ -25,21 +25,29 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint8 array for TypedArray extension
*/
@ScriptClass("Uint8Array")
public final class NativeUint8Array extends ArrayBufferView {
+
/**
* The size in bytes of each element in the array.
*/
@@ -55,31 +63,102 @@ public final class NativeUint8Array extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeUint8Array(buffer, byteOffset, length);
}
+
+ @Override
+ public Uint8ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint8ArrayData(nb, start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint8ArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Uint8Array";
}
};
- private static final class Uint8ArrayData extends ArrayDataImpl {
- private Uint8ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint8ArrayData extends TypedArrayData<ByteBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint8ArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+ private Uint8ArrayData(final ByteBuffer nb, final int start, final int end) {
+ super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
+ }
+
+ @Override
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
+ }
+
+ @Override
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
+ }
+
+ private int getElem(final int index) {
+ try {
+ return nb.get(index) & 0xff;
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
+ }
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ nb.put(index, (byte)elem);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
+ }
+ }
+
+ @Override
+ public boolean isUnsigned() {
+ return true;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ public Object getObject(final int index) {
+ return getInt(index);
}
@Override
- protected int getIntImpl(final int index) {
- return buffer.getByteArray()[byteIndex(index)] & 0xff;
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toInt32(value), strict);
}
@Override
- protected void setImpl(final int index, final int value) {
- buffer.getByteArray()[byteIndex(index)] = (byte)value;
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
}
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
}
/**
@@ -93,7 +172,7 @@ public final class NativeUint8Array extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint8Array constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint8Array)constructorImpl(args, FACTORY);
+ return (NativeUint8Array)constructorImpl(newObj, args, FACTORY);
}
NativeUint8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -101,11 +180,6 @@ public final class NativeUint8Array extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint8Array";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
index d69adc10..db19ab37 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
@@ -25,6 +25,13 @@
package jdk.nashorn.internal.objects;
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +42,7 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* Uint8 clamped array for TypedArray extension
@@ -56,55 +64,148 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
return new NativeUint8ClampedArray(buffer, byteOffset, length);
}
+
+ @Override
+ public Uint8ClampedArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+ return new Uint8ClampedArrayData(nb, start, end);
+ }
+
@Override
- public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
- return new Uint8ClampedArrayData(buffer, byteOffset, length);
+ public String getClassName() {
+ return "Uint8ClampedArray";
}
};
- private static final class Uint8ClampedArrayData extends ArrayDataImpl {
- private Uint8ClampedArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
- super(buffer, byteOffset, elementLength);
+ private static final class Uint8ClampedArrayData extends TypedArrayData<ByteBuffer> {
+
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "getElem", int.class, int.class).methodHandle();
+ private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+ private static final MethodHandle RINT_D = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", double.class, double.class).methodHandle();
+ private static final MethodHandle RINT_O = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", Object.class, Object.class).methodHandle();
+ private static final MethodHandle CLAMP_LONG = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "clampLong", long.class, long.class).methodHandle();
+
+ private Uint8ClampedArrayData(final ByteBuffer nb, final int start, final int end) {
+ super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
}
@Override
- protected int byteIndex(final int index) {
- return index * BYTES_PER_ELEMENT + byteOffset;
+ protected MethodHandle getGetElem() {
+ return GET_ELEM;
}
@Override
- protected int getIntImpl(final int index) {
- return buffer.getByteArray()[byteIndex(index)] & 0xff;
+ protected MethodHandle getSetElem() {
+ return SET_ELEM;
}
- @Override
- protected void setImpl(final int index, final int value) {
- final byte clamped;
- if ((value & 0xffff_ff00) == 0) {
- clamped = (byte) value;
- } else {
- clamped = value < 0 ? 0 : (byte)0xff;
+ private int getElem(final int index) {
+ try {
+ return nb.get(index) & 0xff;
+ } catch (final IndexOutOfBoundsException e) {
+ throw new ClassCastException(); //force relink - this works for unoptimistic too
}
- buffer.getByteArray()[byteIndex(index)] = clamped;
}
@Override
- protected void setImpl(final int index, final long value) {
- if (JSType.isRepresentableAsInt(value)) {
- setImpl(index, (int)value);
- } else {
- buffer.getByteArray()[byteIndex(index)] = value > 0 ? (byte)0xff : 0;
+ public MethodHandle getElementSetter(final Class<?> elementType) {
+ final MethodHandle setter = super.getElementSetter(elementType); //getContinuousElementSetter(getClass(), setElem(), elementType);
+ if (setter != null) {
+ if (elementType == Object.class) {
+ return MH.filterArguments(setter, 2, RINT_O);
+ } else if (elementType == double.class) {
+ return MH.filterArguments(setter, 2, RINT_D);
+ } else if (elementType == long.class) {
+ return MH.filterArguments(setter, 2, CLAMP_LONG);
+ }
+ }
+ return setter;
+ }
+
+ private void setElem(final int index, final int elem) {
+ try {
+ final byte clamped;
+ if ((elem & 0xffff_ff00) == 0) {
+ clamped = (byte)elem;
+ } else {
+ clamped = elem < 0 ? 0 : (byte)0xff;
+ }
+ nb.put(index, clamped);
+ } catch (final IndexOutOfBoundsException e) {
+ //swallow valid array indexes. it's ok.
+ if (index < 0) {
+ throw new ClassCastException();
+ }
}
}
@Override
- protected void setImpl(final int key, final double value) {
- setImpl(key, (int)Math.rint(value));
+ public boolean isClamped() {
+ return true;
+ }
+
+ @Override
+ public boolean isUnsigned() {
+ return true;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ return getElem(index);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ return getInt(index);
}
@Override
- protected void setImpl(final int key, final Object value) {
- setImpl(key, JSType.toNumber(value));
+ public Object getObject(final int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ return set(index, JSType.toNumber(value), strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ setElem(index, value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ return set(index, (int)value, strict);
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ return set(index, rint(value), strict);
+ }
+
+ private static double rint(final double rint) {
+ return (int)Math.rint(rint);
+ }
+
+ @SuppressWarnings("unused")
+ private static Object rint(final Object rint) {
+ return rint(JSType.toNumber(rint));
+ }
+
+ @SuppressWarnings("unused")
+ private static long clampLong(final long l) {
+ if(l < 0L) {
+ return 0L;
+ } else if(l > 0xffL) {
+ return 0xffL;
+ }
+ return l;
}
}
@@ -119,7 +220,7 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
*/
@Constructor(arity = 1)
public static NativeUint8ClampedArray constructor(final boolean newObj, final Object self, final Object... args) {
- return (NativeUint8ClampedArray)constructorImpl(args, FACTORY);
+ return (NativeUint8ClampedArray)constructorImpl(newObj, args, FACTORY);
}
NativeUint8ClampedArray(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -127,11 +228,6 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
}
@Override
- public String getClassName() {
- return "Uint8ClampedArray";
- }
-
- @Override
protected Factory factory() {
return FACTORY;
}
diff --git a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
index d6043de3..a52051ca 100644
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
+++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
@@ -175,13 +175,22 @@ public class ScriptFunctionImpl extends ScriptFunction {
private static class AnonymousFunction extends ScriptFunctionImpl {
private static final PropertyMap anonmap$ = PropertyMap.newMap();
- AnonymousFunction(final Global global) {
+ AnonymousFunction() {
super("", GlobalFunctions.ANONYMOUS, anonmap$, null);
}
}
- static ScriptFunctionImpl newAnonymousFunction(final Global global) {
- return new AnonymousFunction(global);
+ static ScriptFunctionImpl newAnonymousFunction() {
+ return new AnonymousFunction();
+ }
+
+ private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final int flags) {
+ final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags);
+ func.setPrototype(UNDEFINED);
+ // Non-constructor built-in functions do not have "prototype" property
+ func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+
+ return func;
}
/**
@@ -193,12 +202,18 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @return new ScriptFunction
*/
static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
- final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN);
- func.setPrototype(UNDEFINED);
- // Non-constructor built-in functions do not have "prototype" property
- func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+ return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
+ }
- return func;
+ /**
+ * Factory method for non-constructor built-in, strict functions
+ *
+ * @param name function name
+ * @param methodHandle handle for invocation
+ * @return new ScriptFunction
+ */
+ static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) {
+ return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT );
}
/**
@@ -272,14 +287,13 @@ public class ScriptFunctionImpl extends ScriptFunction {
// We have to fill user accessor functions late as these are stored
// in this object rather than in the PropertyMap of this object.
-
- final ScriptFunction errorThrower = global.getTypeErrorThrower();
+ assert objectSpill == null;
+ final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
if (findProperty("arguments", true) != null) {
- setUserAccessors("arguments", errorThrower, errorThrower);
- }
-
+ initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+ }
if (findProperty("caller", true) != null) {
- setUserAccessors("caller", errorThrower, errorThrower);
- }
+ initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+ }
}
}
diff --git a/src/jdk/nashorn/internal/objects/annotations/Optimistic.java b/src/jdk/nashorn/internal/objects/annotations/Optimistic.java
new file mode 100644
index 00000000..09e3b2a5
--- /dev/null
+++ b/src/jdk/nashorn/internal/objects/annotations/Optimistic.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+package jdk.nashorn.internal.objects.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The Optimistic annotation is used for builtins that can throw UnwarrantedOptimism
+ * exception if they are wrong, whose callsite is optimistic and contains a program
+ * point. Every optimistic builtin callsite needs to bind its programPoint to an
+ * argument of the implementation at compile time
+ *
+ * Typical use case would be something like: if you want to do an optimistic "push" function
+ * in NativeArray that takes an int, write
+ *
+ * <pre>
+ * {@literal @}SpecializedFunction {@literal @}Optimistic
+ * public static int push(final Object self, final int x, final int programPoint) {
+ * try {
+ * //push code assuming that this is an int array
+ * //return new length of array, assuming it's an int
+ * } catch (ArrayWasWrong e) {
+ * //undo any array modifications
+ * throw new UnwarrantedOptimismExceptionArrayType(x, programPoint);
+ * } catch (LengthOverFlowed e) {
+ * //undo any array modifications
+ * throw new UnwarratnedOptimismExceptionArrayLength(uint32lenThatOverFlowed, programPoint)
+ * }
+ * }
+ * </pre>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Optimistic {
+ //empty
+}
diff --git a/src/jdk/nashorn/internal/objects/annotations/Property.java b/src/jdk/nashorn/internal/objects/annotations/Property.java
index 6aec2052..7da82fe1 100644
--- a/src/jdk/nashorn/internal/objects/annotations/Property.java
+++ b/src/jdk/nashorn/internal/objects/annotations/Property.java
@@ -40,21 +40,25 @@ import java.lang.annotation.Target;
public @interface Property {
/**
* Name of the script property. If empty, the name is inferred.
+ * @return name
*/
public String name() default "";
/**
* Attribute flags for this function.
+ * @return attribute
*/
public int attributes() default DEFAULT_ATTRIBUTES;
/**
* Initialize this property with the object of given class.
+ * @return class
*/
public String clazz() default "";
/**
* Where this property lives?
+ * @return location of property
*/
public Where where() default Where.INSTANCE;
}