From eb669292855a9400cae6a47f546761c15344b330 Mon Sep 17 00:00:00 2001
From: Paul Sandoz
Date: Wed, 15 May 2013 10:15:28 +0200
Subject: [PATCH 001/101] 8013334: Spliterator behavior for LinkedList
contradicts Spliterator.trySplit
This changeset also contains some minor, non spec, related fixes to tidy up other areas of the JavaDoc.
Co-authored-by: John Rose
Co-authored-by: Mike Duigou
Reviewed-by: plevart, darcy
---
.../share/classes/java/util/Spliterator.java | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/jdk/src/share/classes/java/util/Spliterator.java b/jdk/src/share/classes/java/util/Spliterator.java
index 588b8176d47..0b41f9f0a8f 100644
--- a/jdk/src/share/classes/java/util/Spliterator.java
+++ b/jdk/src/share/classes/java/util/Spliterator.java
@@ -140,32 +140,32 @@ import java.util.function.LongConsumer;
* (in approximate order of decreasing desirability):
*
*
The source cannot be structurally interfered with.
- * For example, an instance of
+ * For example, an instance of
* {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source.
* A Spliterator created from the source reports a characteristic of
* {@code IMMUTABLE}.
*
The source manages concurrent modifications.
- * For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
+ * For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
* is a concurrent source. A Spliterator created from the source reports a
* characteristic of {@code CONCURRENT}.
*
The mutable source provides a late-binding and fail-fast Spliterator.
- * Late binding narrows the window during which interference can affect
+ * Late binding narrows the window during which interference can affect
* the calculation; fail-fast detects, on a best-effort basis, that structural
* interference has occurred after traversal has commenced and throws
* {@link ConcurrentModificationException}. For example, {@link ArrayList},
* and many other non-concurrent {@code Collection} classes in the JDK, provide
* a late-binding, fail-fast spliterator.
*
The mutable source provides a non-late-binding but fail-fast Spliterator.
- * The source increases the likelihood of throwing
+ * The source increases the likelihood of throwing
* {@code ConcurrentModificationException} since the window of potential
* interference is larger.
*
The mutable source provides a late-binding and non-fail-fast Spliterator.
- * The source risks arbitrary, non-deterministic behavior after traversal
+ * The source risks arbitrary, non-deterministic behavior after traversal
* has commenced since interference is not detected.
*
*
The mutable source provides a non-late-binding and non-fail-fast
* Spliterator.
- * The source increases the risk of arbitrary, non-deterministic behavior
+ * The source increases the risk of arbitrary, non-deterministic behavior
* since non-detected interference may occur after construction.
*
*
@@ -284,6 +284,8 @@ import java.util.function.LongConsumer;
* is set to {@code true} then diagnostic warnings are reported if boxing of
* primitive values occur when operating on primitive subtype specializations.
*
+ * @param the type of elements returned by this Spliterator
+ *
* @see Collection
* @since 1.8
*/
@@ -333,9 +335,8 @@ public interface Spliterator {
* Upon non-null return:
*
*
the value reported for {@code estimateSize()} before splitting,
- * if not already zero or {@code Long.MAX_VALUE}, must, after splitting, be
- * greater than {@code estimateSize()} for this and the returned
- * Spliterator; and
+ * must, after splitting, be greater than or equal to {@code estimateSize()}
+ * for this and the returned Spliterator; and
*
if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
* for this spliterator before splitting must be equal to the sum of
* {@code estimateSize()} for this and the returned Spliterator after
From b175321e7dcb90ce57930247ce1f661e84ce603b Mon Sep 17 00:00:00 2001
From: Paul Sandoz
Date: Wed, 15 May 2013 10:25:59 +0200
Subject: [PATCH 002/101] 8014133: Spliterator.OfPrimitive
Co-authored-by: Brian Goetz
Reviewed-by: mduigou, forax
---
.../share/classes/java/util/Spliterator.java | 105 ++++++++----------
1 file changed, 44 insertions(+), 61 deletions(-)
diff --git a/jdk/src/share/classes/java/util/Spliterator.java b/jdk/src/share/classes/java/util/Spliterator.java
index 0b41f9f0a8f..5ed0b1243de 100644
--- a/jdk/src/share/classes/java/util/Spliterator.java
+++ b/jdk/src/share/classes/java/util/Spliterator.java
@@ -567,13 +567,28 @@ public interface Spliterator {
public static final int SUBSIZED = 0x00004000;
/**
- * A Spliterator specialized for {@code int} values.
+ * A Spliterator specialized for primitive values.
+ *
+ * @param the type of elements returned by this Spliterator. The
+ * type must be a wrapper type for a primitive type, such as {@code Integer}
+ * for the primitive {@code int} type.
+ * @param the type of primitive consumer. The type must be a
+ * primitive specialization of {@link java.util.function.Consumer} for
+ * {@code T}, such as {@link java.util.function.IntConsumer} for
+ * {@code Integer}.
+ * @param the type of primitive Spliterator. The type must be
+ * a primitive specialization of Spliterator for {@code T}, such as
+ * {@link Spliterator.OfInt} for {@code Integer}.
+ *
+ * @see Spliterator.OfInt
+ * @see Spliterator.OfLong
+ * @see Spliterator.OfDouble
* @since 1.8
*/
- public interface OfInt extends Spliterator {
-
+ public interface OfPrimitive>
+ extends Spliterator {
@Override
- OfInt trySplit();
+ T_SPLITR trySplit();
/**
* If a remaining element exists, performs the given action on it,
@@ -587,7 +602,7 @@ public interface Spliterator {
* upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null
*/
- boolean tryAdvance(IntConsumer action);
+ boolean tryAdvance(T_CONS action);
/**
* Performs the given action for each remaining element, sequentially in
@@ -604,6 +619,24 @@ public interface Spliterator {
* @param action The action
* @throws NullPointerException if the specified action is null
*/
+ default void forEachRemaining(T_CONS action) {
+ do { } while (tryAdvance(action));
+ }
+ }
+
+ /**
+ * A Spliterator specialized for {@code int} values.
+ * @since 1.8
+ */
+ public interface OfInt extends OfPrimitive {
+
+ @Override
+ OfInt trySplit();
+
+ @Override
+ boolean tryAdvance(IntConsumer action);
+
+ @Override
default void forEachRemaining(IntConsumer action) {
do { } while (tryAdvance(action));
}
@@ -659,40 +692,15 @@ public interface Spliterator {
* A Spliterator specialized for {@code long} values.
* @since 1.8
*/
- public interface OfLong extends Spliterator {
+ public interface OfLong extends OfPrimitive {
@Override
OfLong trySplit();
- /**
- * If a remaining element exists, performs the given action on it,
- * returning {@code true}; else returns {@code false}. If this
- * Spliterator is {@link #ORDERED} the action is performed on the
- * next element in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @param action The action
- * @return {@code false} if no remaining elements existed
- * upon entry to this method, else {@code true}.
- * @throws NullPointerException if the specified action is null
- */
+ @Override
boolean tryAdvance(LongConsumer action);
- /**
- * Performs the given action for each remaining element, sequentially in
- * the current thread, until all elements have been processed or the
- * action throws an exception. If this Spliterator is {@link #ORDERED},
- * actions are performed in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @implSpec
- * The default implementation repeatedly invokes {@link #tryAdvance}
- * until it returns {@code false}. It should be overridden whenever
- * possible.
- *
- * @param action The action
- * @throws NullPointerException if the specified action is null
- */
+ @Override
default void forEachRemaining(LongConsumer action) {
do { } while (tryAdvance(action));
}
@@ -748,40 +756,15 @@ public interface Spliterator {
* A Spliterator specialized for {@code double} values.
* @since 1.8
*/
- public interface OfDouble extends Spliterator {
+ public interface OfDouble extends OfPrimitive {
@Override
OfDouble trySplit();
- /**
- * If a remaining element exists, performs the given action on it,
- * returning {@code true}; else returns {@code false}. If this
- * Spliterator is {@link #ORDERED} the action is performed on the
- * next element in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @param action The action
- * @return {@code false} if no remaining elements existed
- * upon entry to this method, else {@code true}.
- * @throws NullPointerException if the specified action is null
- */
+ @Override
boolean tryAdvance(DoubleConsumer action);
- /**
- * Performs the given action for each remaining element, sequentially in
- * the current thread, until all elements have been processed or the
- * action throws an exception. If this Spliterator is {@link #ORDERED},
- * actions are performed in encounter order. Exceptions thrown by the
- * action are relayed to the caller.
- *
- * @implSpec
- * The default implementation repeatedly invokes {@link #tryAdvance}
- * until it returns {@code false}. It should be overridden whenever
- * possible.
- *
- * @param action The action
- * @throws NullPointerException if the specified action is null
- */
+ @Override
default void forEachRemaining(DoubleConsumer action) {
do { } while (tryAdvance(action));
}
From 5a95645a18bb762010733469e2453c1d1eb770b6 Mon Sep 17 00:00:00 2001
From: Mike Duigou
Date: Fri, 17 May 2013 10:36:04 -0700
Subject: [PATCH 003/101] 8004015: Additional static and instance utils for
functional interfaces 8011010: Spec j.u.f.Predicate doesn't specify NPEs
thrown by the SE8's Reference Implementation
Reviewed-by: briangoetz, dholmes, chegar
---
.../java/util/function/BiConsumer.java | 30 ++++++++++-
.../java/util/function/BiFunction.java | 26 ++++++++--
.../java/util/function/BiPredicate.java | 41 ++++++---------
.../java/util/function/BooleanSupplier.java | 2 +-
.../classes/java/util/function/Consumer.java | 24 ++++++++-
.../util/function/DoubleBinaryOperator.java | 2 +-
.../java/util/function/DoubleConsumer.java | 25 ++++++++-
.../java/util/function/DoubleFunction.java | 2 +-
.../java/util/function/DoublePredicate.java | 45 ++++++++--------
.../java/util/function/DoubleSupplier.java | 2 +-
.../util/function/DoubleUnaryOperator.java | 45 +++++++++++++++-
.../classes/java/util/function/Function.java | 52 +++++++++++++++++--
.../java/util/function/IntBinaryOperator.java | 2 +-
.../java/util/function/IntConsumer.java | 25 ++++++++-
.../java/util/function/IntFunction.java | 2 +-
.../java/util/function/IntPredicate.java | 43 +++++++--------
.../java/util/function/IntSupplier.java | 2 +-
.../java/util/function/IntUnaryOperator.java | 47 ++++++++++++++++-
.../util/function/LongBinaryOperator.java | 2 +-
.../java/util/function/LongConsumer.java | 25 ++++++++-
.../java/util/function/LongFunction.java | 2 +-
.../java/util/function/LongPredicate.java | 44 +++++++---------
.../java/util/function/LongSupplier.java | 2 +-
.../java/util/function/LongUnaryOperator.java | 45 +++++++++++++++-
.../java/util/function/ObjDoubleConsumer.java | 2 +-
.../java/util/function/ObjIntConsumer.java | 4 +-
.../java/util/function/ObjLongConsumer.java | 4 +-
.../classes/java/util/function/Predicate.java | 44 ++++++++++------
.../classes/java/util/function/Supplier.java | 2 +-
.../util/function/ToDoubleBiFunction.java | 2 +-
.../java/util/function/ToDoubleFunction.java | 2 +-
.../java/util/function/ToIntBiFunction.java | 10 ++--
.../java/util/function/ToIntFunction.java | 2 +-
.../java/util/function/ToLongBiFunction.java | 2 +-
.../java/util/function/ToLongFunction.java | 2 +-
.../java/util/function/UnaryOperator.java | 9 ++++
36 files changed, 467 insertions(+), 155 deletions(-)
diff --git a/jdk/src/share/classes/java/util/function/BiConsumer.java b/jdk/src/share/classes/java/util/function/BiConsumer.java
index 80bdcfa3b15..afc0ba34d1e 100644
--- a/jdk/src/share/classes/java/util/function/BiConsumer.java
+++ b/jdk/src/share/classes/java/util/function/BiConsumer.java
@@ -24,14 +24,16 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts two input arguments and returns no result. This is
* the two-arity specialization of {@link Consumer}. Unlike most other
* functional interfaces, {@code BiConsumer} is expected to operate via
* side-effects.
*
- * @param the type of the first argument to the {@code accept} operation.
- * @param the type of the second argument to the {@code accept} operation.
+ * @param the type of the first argument to the {@code accept} operation
+ * @param the type of the second argument to the {@code accept} operation
*
* @see Consumer
* @since 1.8
@@ -47,4 +49,28 @@ public interface BiConsumer {
* @param u an input object
*/
void accept(T t, U u);
+
+ /**
+ * Returns a {@code BiConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * the other {@code BiConsumer}.
+ *
+ *
Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a BiConsumer which will be chained after this BiConsumer
+ * @return a BiConsumer which performs in sequence the {@code accept} method
+ * of this BiConsumer and the {@code accept} method of the specified
+ * BiConsumer operation
+ * @throws NullPointerException if other is null
+ */
+ default BiConsumer chain(BiConsumer super T, ? super U> other) {
+ Objects.requireNonNull(other);
+
+ return (l, r) -> {
+ accept(l, r);
+ other.accept(l, r);
+ };
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/BiFunction.java b/jdk/src/share/classes/java/util/function/BiFunction.java
index 85dc2a0a3cb..fb66ec0e8bb 100644
--- a/jdk/src/share/classes/java/util/function/BiFunction.java
+++ b/jdk/src/share/classes/java/util/function/BiFunction.java
@@ -24,15 +24,17 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* Apply a function to the input arguments, yielding an appropriate result. This
* is the two-arity specialization of {@link Function}. A function may
* variously provide a mapping between types, object instances or keys and
* values or any other form of transformation upon the input.
*
- * @param the type of the first argument to the {@code apply} operation.
- * @param the type of the second argument to the {@code apply} operation.
- * @param the type of results returned by the {@code apply} operation.
+ * @param the type of the first argument to the {@code apply} operation
+ * @param the type of the second argument to the {@code apply} operation
+ * @param the type of results returned by the {@code apply} operation
*
* @see Function
* @since 1.8
@@ -48,4 +50,22 @@ public interface BiFunction {
* @return the function result
*/
R apply(T t, U u);
+
+ /**
+ * Returns a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param Type of output objects to the combined function. May be the
+ * same type as {@code }, {@code } or {@code }
+ * @param after An additional function to be applied after this function is
+ * applied
+ * @return A function which performs this function followed by the provided
+ * function
+ * @throws NullPointerException if after is null
+ */
+ default BiFunction andThen(Function super R, ? extends V> after) {
+ Objects.requireNonNull(after);
+ return (T t, U u) -> after.apply(apply(t, u));
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/BiPredicate.java b/jdk/src/share/classes/java/util/function/BiPredicate.java
index 9a8665fa151..29e92b875f7 100644
--- a/jdk/src/share/classes/java/util/function/BiPredicate.java
+++ b/jdk/src/share/classes/java/util/function/BiPredicate.java
@@ -30,8 +30,8 @@ import java.util.Objects;
* Determines if the input objects match some criteria. This is the two-arity
* specialization of {@link Predicate}.
*
- * @param the type of the first argument to {@code test}.
- * @param the type of the second argument to {@code test}.
+ * @param the type of the first argument to {@code test}
+ * @param the type of the second argument to {@code test}
*
* @see Predicate
* @since 1.8
@@ -42,9 +42,9 @@ public interface BiPredicate {
/**
* Return {@code true} if the inputs match some criteria.
*
- * @param t an input object.
- * @param u an input object.
- * @return {@code true} if the inputs match some criteria.
+ * @param t an input object
+ * @param u an input object
+ * @return {@code true} if the inputs match some criteria
*/
boolean test(T t, U u);
@@ -54,11 +54,12 @@ public interface BiPredicate {
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default BiPredicate and(BiPredicate super T, ? super U> p) {
+ default BiPredicate and(BiPredicate super T, ? super U> p) {
Objects.requireNonNull(p);
return (T t, U u) -> test(t, u) && p.test(t, u);
}
@@ -67,9 +68,9 @@ public interface BiPredicate {
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default BiPredicate negate() {
+ default BiPredicate negate() {
return (T t, U u) -> !test(t, u);
}
@@ -79,25 +80,13 @@ public interface BiPredicate {
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default BiPredicate or(BiPredicate super T, ? super U> p) {
+ default BiPredicate or(BiPredicate super T, ? super U> p) {
Objects.requireNonNull(p);
return (T t, U u) -> test(t, u) || p.test(t, u);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- */
- public default BiPredicate xor(BiPredicate super T, ? super U> p) {
- Objects.requireNonNull(p);
- return (T t, U u) -> test(t, u) ^ p.test(t, u);
- }
}
diff --git a/jdk/src/share/classes/java/util/function/BooleanSupplier.java b/jdk/src/share/classes/java/util/function/BooleanSupplier.java
index f145b621156..875ac748628 100644
--- a/jdk/src/share/classes/java/util/function/BooleanSupplier.java
+++ b/jdk/src/share/classes/java/util/function/BooleanSupplier.java
@@ -40,5 +40,5 @@ public interface BooleanSupplier {
*
* @return a {@code boolean} value
*/
- public boolean getAsBoolean();
+ boolean getAsBoolean();
}
diff --git a/jdk/src/share/classes/java/util/function/Consumer.java b/jdk/src/share/classes/java/util/function/Consumer.java
index e9cb175d59b..69add851dcc 100644
--- a/jdk/src/share/classes/java/util/function/Consumer.java
+++ b/jdk/src/share/classes/java/util/function/Consumer.java
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single input argument and returns no result.
* Unlike most other functional interfaces, {@code Consumer} is expected to
@@ -41,5 +43,25 @@ public interface Consumer {
*
* @param t the input object
*/
- public void accept(T t);
+ void accept(T t);
+
+ /**
+ * Returns a {@code Consumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * the other {@code Consumer}.
+ *
+ *
Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a Consumer which will be chained after this Consumer
+ * @return a Consumer which performs in sequence the {@code accept} method
+ * of this Consumer and the {@code accept} method of the specified Consumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default Consumer chain(Consumer super T> other) {
+ Objects.requireNonNull(other);
+ return (T t) -> { accept(t); other.accept(t); };
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java
index de9855bd4d1..7d1e68aaced 100644
--- a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java
+++ b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java
@@ -43,5 +43,5 @@ public interface DoubleBinaryOperator {
* @param right the right operand value
* @return the result of the operation
*/
- public double applyAsDouble(double left, double right);
+ double applyAsDouble(double left, double right);
}
diff --git a/jdk/src/share/classes/java/util/function/DoubleConsumer.java b/jdk/src/share/classes/java/util/function/DoubleConsumer.java
index 2ea35749737..665b80a3d20 100644
--- a/jdk/src/share/classes/java/util/function/DoubleConsumer.java
+++ b/jdk/src/share/classes/java/util/function/DoubleConsumer.java
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single double argument and returns no result.
* This is the primitive type specialization of {@link Consumer} for
@@ -41,5 +43,26 @@ public interface DoubleConsumer {
*
* @param value the input value
*/
- public void accept(double value);
+ void accept(double value);
+
+ /**
+ * Returns a {@code DoubleConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * another {@code DoubleConsumer}.
+ *
+ *
Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a DoubleConsumer which will be chained after this
+ * DoubleConsumer
+ * @return an DoubleConsumer which performs in sequence the {@code accept} method
+ * of this DoubleConsumer and the {@code accept} method of the specified IntConsumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default DoubleConsumer chain(DoubleConsumer other) {
+ Objects.requireNonNull(other);
+ return (double t) -> { accept(t); other.accept(t); };
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/DoubleFunction.java b/jdk/src/share/classes/java/util/function/DoubleFunction.java
index fcc6bb9dfde..d8141d0a8a2 100644
--- a/jdk/src/share/classes/java/util/function/DoubleFunction.java
+++ b/jdk/src/share/classes/java/util/function/DoubleFunction.java
@@ -43,5 +43,5 @@ public interface DoubleFunction {
* @param value the input value
* @return the function result
*/
- public R apply(double value);
+ R apply(double value);
}
diff --git a/jdk/src/share/classes/java/util/function/DoublePredicate.java b/jdk/src/share/classes/java/util/function/DoublePredicate.java
index 48f4504828f..8156b65cb93 100644
--- a/jdk/src/share/classes/java/util/function/DoublePredicate.java
+++ b/jdk/src/share/classes/java/util/function/DoublePredicate.java
@@ -40,11 +40,11 @@ public interface DoublePredicate {
/**
* Returns {@code true} if the input value matches some criteria.
*
- * @param value the value to be tested.
+ * @param value the value to be tested
* @return {@code true} if the input value matches some criteria, otherwise
- * {@code false}.
+ * {@code false}
*/
- public boolean test(double value);
+ boolean test(double value);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -52,11 +52,16 @@ public interface DoublePredicate {
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default DoublePredicate and(DoublePredicate p) {
+ default DoublePredicate and(DoublePredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) && p.test(value);
}
@@ -65,9 +70,9 @@ public interface DoublePredicate {
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default DoublePredicate negate() {
+ default DoublePredicate negate() {
return (value) -> !test(value);
}
@@ -77,25 +82,17 @@ public interface DoublePredicate {
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default DoublePredicate or(DoublePredicate p) {
+ default DoublePredicate or(DoublePredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) || p.test(value);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if all or none of the
- * component predicates evaluate to {@code true}.
- */
- public default DoublePredicate xor(DoublePredicate p) {
- Objects.requireNonNull(p);
- return (value) -> test(value) ^ p.test(value);
- }
}
diff --git a/jdk/src/share/classes/java/util/function/DoubleSupplier.java b/jdk/src/share/classes/java/util/function/DoubleSupplier.java
index 9f9ab4e9f5a..c661fdff927 100644
--- a/jdk/src/share/classes/java/util/function/DoubleSupplier.java
+++ b/jdk/src/share/classes/java/util/function/DoubleSupplier.java
@@ -39,5 +39,5 @@ public interface DoubleSupplier {
*
* @return a {@code double} value
*/
- public double getAsDouble();
+ double getAsDouble();
}
diff --git a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java
index e9be79f5bb9..39dfa6ab6a7 100644
--- a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java
+++ b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation on a {@code double} operand yielding a {@code double}
* result. This is the primitive type specialization of {@link UnaryOperator}
@@ -42,5 +44,46 @@ public interface DoubleUnaryOperator {
* @param operand the operand value
* @return the operation result value
*/
- public double applyAsDouble(double operand);
+ double applyAsDouble(double operand);
+
+ /**
+ * Compose a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param before An additional function to be applied before this function
+ * is applied
+ * @return A function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default DoubleUnaryOperator compose(DoubleUnaryOperator before) {
+ Objects.requireNonNull(before);
+ return (double v) -> applyAsDouble(before.applyAsDouble(v));
+ }
+
+ /**
+ * Compose a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param after An additional function to be applied after this function is
+ * applied
+ * @return A function which performs this function followed by the provided
+ * function followed
+ * @throws NullPointerException if after is null
+ */
+ default DoubleUnaryOperator andThen(DoubleUnaryOperator after) {
+ Objects.requireNonNull(after);
+ return (double t) -> after.applyAsDouble(applyAsDouble(t));
+ }
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static DoubleUnaryOperator identity() {
+ return t -> t;
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/Function.java b/jdk/src/share/classes/java/util/function/Function.java
index ff4b538c1a9..3cab4bf99d8 100644
--- a/jdk/src/share/classes/java/util/function/Function.java
+++ b/jdk/src/share/classes/java/util/function/Function.java
@@ -24,14 +24,15 @@
*/
package java.util.function;
+import java.util.Objects;
/**
* Apply a function to the input argument, yielding an appropriate result. A
* function may variously provide a mapping between types, object instances or
* keys and values or any other form of transformation upon the input.
*
- * @param the type of the input to the {@code apply} operation.
- * @param the type of the result of the {@code apply} operation.
+ * @param the type of the input to the {@code apply} operation
+ * @param the type of the result of the {@code apply} operation
*
* @since 1.8
*/
@@ -44,5 +45,50 @@ public interface Function {
* @param t the input object
* @return the function result
*/
- public R apply(T t);
+ R apply(T t);
+
+ /**
+ * Returns a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param type of input objects to the combined function. May be the
+ * same type as {@code } or {@code }
+ * @param before an additional function to be applied before this function
+ * is applied
+ * @return a function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default Function compose(Function super V, ? extends T> before) {
+ Objects.requireNonNull(before);
+ return (V v) -> apply(before.apply(v));
+ }
+
+ /**
+ * Returns a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param type of output objects to the combined function. May be the
+ * same type as {@code } or {@code }
+ * @param after an additional function to be applied after this function is
+ * applied
+ * @return a function which performs this function followed by the provided
+ * function
+ * @throws NullPointerException if after is null
+ */
+ default Function andThen(Function super R, ? extends V> after) {
+ Objects.requireNonNull(after);
+ return (T t) -> after.apply(apply(t));
+ }
+
+ /**
+ * Returns a {@code Function} whose {@code apply} method returns its input.
+ *
+ * @param the type of the input and output objects to the function
+ */
+ static Function identity() {
+ return t -> t;
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java
index f139118e3f1..a0788a1d734 100644
--- a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java
+++ b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java
@@ -44,5 +44,5 @@ public interface IntBinaryOperator {
* @param right the right operand value
* @return the result of the operation
*/
- public int applyAsInt(int left, int right);
+ int applyAsInt(int left, int right);
}
diff --git a/jdk/src/share/classes/java/util/function/IntConsumer.java b/jdk/src/share/classes/java/util/function/IntConsumer.java
index 28a6ec46e2f..3c2a770332f 100644
--- a/jdk/src/share/classes/java/util/function/IntConsumer.java
+++ b/jdk/src/share/classes/java/util/function/IntConsumer.java
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single integer argument and returns no result.
* This is the primitive type specialization of {@link Consumer} for {@code int}.
@@ -41,5 +43,26 @@ public interface IntConsumer {
*
* @param value the input value
*/
- public void accept(int value);
+ void accept(int value);
+
+ /**
+ * Returns an {@code IntConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * another {@code IntConsumer}.
+ *
+ *
Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other an IntConsumer which will be chained after this
+ * IntConsumer
+ * @return an IntConsumer which performs in sequence the {@code accept} method
+ * of this IntConsumer and the {@code accept} method of the specified IntConsumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default IntConsumer chain(IntConsumer other) {
+ Objects.requireNonNull(other);
+ return (int t) -> { accept(t); other.accept(t); };
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/IntFunction.java b/jdk/src/share/classes/java/util/function/IntFunction.java
index b5faecc0ea7..ec2ffcae249 100644
--- a/jdk/src/share/classes/java/util/function/IntFunction.java
+++ b/jdk/src/share/classes/java/util/function/IntFunction.java
@@ -43,5 +43,5 @@ public interface IntFunction {
* @param value the input value
* @return the function result
*/
- public R apply(int value);
+ R apply(int value);
}
diff --git a/jdk/src/share/classes/java/util/function/IntPredicate.java b/jdk/src/share/classes/java/util/function/IntPredicate.java
index 4351c75ffe7..0e7ec0737d5 100644
--- a/jdk/src/share/classes/java/util/function/IntPredicate.java
+++ b/jdk/src/share/classes/java/util/function/IntPredicate.java
@@ -39,11 +39,11 @@ public interface IntPredicate {
/**
* Returns {@code true} if the input value matches some criteria.
*
- * @param value the value to be tested.
+ * @param value the value to be tested
* @return {@code true} if the input value matches some criteria, otherwise
* {@code false}
*/
- public boolean test(int value);
+ boolean test(int value);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@ public interface IntPredicate {
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default IntPredicate and(IntPredicate p) {
+ default IntPredicate and(IntPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) && p.test(value);
}
@@ -64,9 +69,9 @@ public interface IntPredicate {
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default IntPredicate negate() {
+ default IntPredicate negate() {
return (value) -> !test(value);
}
@@ -76,25 +81,17 @@ public interface IntPredicate {
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default IntPredicate or(IntPredicate p) {
+ default IntPredicate or(IntPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) || p.test(value);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}
- */
- public default IntPredicate xor(IntPredicate p) {
- Objects.requireNonNull(p);
- return (value) -> test(value) ^ p.test(value);
- }
}
diff --git a/jdk/src/share/classes/java/util/function/IntSupplier.java b/jdk/src/share/classes/java/util/function/IntSupplier.java
index d857b7882b4..3165d3f4061 100644
--- a/jdk/src/share/classes/java/util/function/IntSupplier.java
+++ b/jdk/src/share/classes/java/util/function/IntSupplier.java
@@ -39,5 +39,5 @@ public interface IntSupplier {
*
* @return an {@code int} value
*/
- public int getAsInt();
+ int getAsInt();
}
diff --git a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java
index a3b868dff54..2e14c151b1f 100644
--- a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java
+++ b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation on a single {@code int} operand yielding an {@code int} result.
* This is the primitive type specialization of {@link UnaryOperator} for
@@ -37,10 +39,51 @@ public interface IntUnaryOperator {
/**
* Returns the {@code int} value result of the operation upon the
- * {@code int} operand.
+ * {@code int} operand.
*
* @param operand the operand value
* @return the operation result value
*/
- public int applyAsInt(int operand);
+ int applyAsInt(int operand);
+
+ /**
+ * Compose a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param before an additional function to be applied before this function
+ * is applied
+ * @return a function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default IntUnaryOperator compose(IntUnaryOperator before) {
+ Objects.requireNonNull(before);
+ return (int v) -> applyAsInt(before.applyAsInt(v));
+ }
+
+ /**
+ * Compose a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param after an additional function to be applied after this function is
+ * applied
+ * @return a function which performs this function followed by the provided
+ * function followed
+ * @throws NullPointerException if after is null
+ */
+ default IntUnaryOperator andThen(IntUnaryOperator after) {
+ Objects.requireNonNull(after);
+ return (int t) -> after.applyAsInt(applyAsInt(t));
+ }
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static IntUnaryOperator identity() {
+ return t -> t;
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java
index d08271d30b1..f35258bea60 100644
--- a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java
+++ b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java
@@ -44,5 +44,5 @@ public interface LongBinaryOperator {
* @param right the right operand value
* @return the result of the operation
*/
- public long applyAsLong(long left, long right);
+ long applyAsLong(long left, long right);
}
diff --git a/jdk/src/share/classes/java/util/function/LongConsumer.java b/jdk/src/share/classes/java/util/function/LongConsumer.java
index 072c0972a60..754af39d918 100644
--- a/jdk/src/share/classes/java/util/function/LongConsumer.java
+++ b/jdk/src/share/classes/java/util/function/LongConsumer.java
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation which accepts a single long argument and returns no result.
* This is the {@code long}-consuming primitive type specialization of
@@ -41,5 +43,26 @@ public interface LongConsumer {
*
* @param value the input value
*/
- public void accept(long value);
+ void accept(long value);
+
+ /**
+ * Returns a {@code LongConsumer} which performs, in sequence, the operation
+ * represented by this object followed by the operation represented by
+ * another {@code LongConsumer}.
+ *
+ *
Any exceptions thrown by either {@code accept} method are relayed
+ * to the caller; if performing this operation throws an exception, the
+ * other operation will not be performed.
+ *
+ * @param other a LongConsumer which will be chained after this
+ * LongConsumer
+ * @return a LongConsumer which performs in sequence the {@code accept} method
+ * of this LongConsumer and the {@code accept} method of the specified LongConsumer
+ * operation
+ * @throws NullPointerException if other is null
+ */
+ default LongConsumer chain(LongConsumer other) {
+ Objects.requireNonNull(other);
+ return (long t) -> { accept(t); other.accept(t); };
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/LongFunction.java b/jdk/src/share/classes/java/util/function/LongFunction.java
index 924eb43be17..d87f22ab7e9 100644
--- a/jdk/src/share/classes/java/util/function/LongFunction.java
+++ b/jdk/src/share/classes/java/util/function/LongFunction.java
@@ -43,5 +43,5 @@ public interface LongFunction {
* @param value the input value
* @return the function result
*/
- public R apply(long value);
+ R apply(long value);
}
diff --git a/jdk/src/share/classes/java/util/function/LongPredicate.java b/jdk/src/share/classes/java/util/function/LongPredicate.java
index 65f3e69525b..1a28708ea45 100644
--- a/jdk/src/share/classes/java/util/function/LongPredicate.java
+++ b/jdk/src/share/classes/java/util/function/LongPredicate.java
@@ -39,11 +39,11 @@ public interface LongPredicate {
/**
* Returns {@code true} if the input value matches some criteria.
*
- * @param value the value to be tested.
+ * @param value the value to be tested
* @return {@code true} if the input value matches some criteria, otherwise
- * {@code false}.
+ * {@code false}
*/
- public boolean test(long value);
+ boolean test(long value);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,15 @@ public interface LongPredicate {
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
*/
- public default LongPredicate and(LongPredicate p) {
+ default LongPredicate and(LongPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) && p.test(value);
}
@@ -64,9 +68,9 @@ public interface LongPredicate {
* Returns a predicate which negates the result of this predicate.
*
* @return a new predicate who's result is always the opposite of this
- * predicate.
+ * predicate
*/
- public default LongPredicate negate() {
+ default LongPredicate negate() {
return (value) -> !test(value);
}
@@ -76,25 +80,17 @@ public interface LongPredicate {
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default LongPredicate or(LongPredicate p) {
+ default LongPredicate or(LongPredicate p) {
Objects.requireNonNull(p);
return (value) -> test(value) || p.test(value);
}
-
- /**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- *
- * @param p a predicate which will be logically-XORed with this predicate.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
- */
- public default LongPredicate xor(LongPredicate p) {
- Objects.requireNonNull(p);
- return (value) -> test(value) ^ p.test(value);
- }
}
diff --git a/jdk/src/share/classes/java/util/function/LongSupplier.java b/jdk/src/share/classes/java/util/function/LongSupplier.java
index 2d5a3def105..d88c399a790 100644
--- a/jdk/src/share/classes/java/util/function/LongSupplier.java
+++ b/jdk/src/share/classes/java/util/function/LongSupplier.java
@@ -39,5 +39,5 @@ public interface LongSupplier {
*
* @return a {@code long} value
*/
- public long getAsLong();
+ long getAsLong();
}
diff --git a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java
index 3632e2a118a..a32918fc56b 100644
--- a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java
+++ b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java
@@ -24,6 +24,8 @@
*/
package java.util.function;
+import java.util.Objects;
+
/**
* An operation on a single {@code long} operand yielding a {@code long} result.
* This is the primitive type specialization of {@link UnaryOperator} for
@@ -42,5 +44,46 @@ public interface LongUnaryOperator {
* @param operand the operand value
* @return the operation result value
*/
- public long applyAsLong(long operand);
+ long applyAsLong(long operand);
+
+ /**
+ * Compose a new function which applies the provided function followed by
+ * this function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param before An additional function to be applied before this function
+ * is applied
+ * @return A function which performs the provided function followed by this
+ * function
+ * @throws NullPointerException if before is null
+ */
+ default LongUnaryOperator compose(LongUnaryOperator before) {
+ Objects.requireNonNull(before);
+ return (long v) -> applyAsLong(before.applyAsLong(v));
+ }
+
+ /**
+ * Compose a new function which applies this function followed by the
+ * provided function. If either function throws an exception, it is relayed
+ * to the caller.
+ *
+ * @param after An additional function to be applied after this function is
+ * applied
+ * @return A function which performs this function followed by the provided
+ * function followed
+ * @throws NullPointerException if after is null
+ */
+ default LongUnaryOperator andThen(LongUnaryOperator after) {
+ Objects.requireNonNull(after);
+ return (long t) -> after.applyAsLong(applyAsLong(t));
+ }
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static LongUnaryOperator identity() {
+ return t -> t;
+ }
}
diff --git a/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java b/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java
index 24e4c29327c..dd8c0c9cf99 100644
--- a/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java
+++ b/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java
@@ -44,5 +44,5 @@ public interface ObjDoubleConsumer {
* @param t an input object
* @param value an input value
*/
- public void accept(T t, double value);
+ void accept(T t, double value);
}
diff --git a/jdk/src/share/classes/java/util/function/ObjIntConsumer.java b/jdk/src/share/classes/java/util/function/ObjIntConsumer.java
index 33f900101ab..3ab4d5eef05 100644
--- a/jdk/src/share/classes/java/util/function/ObjIntConsumer.java
+++ b/jdk/src/share/classes/java/util/function/ObjIntConsumer.java
@@ -30,7 +30,7 @@ package java.util.function;
* {@link BiConsumer}. Unlike most other functional interfaces,
* {@code ObjIntConsumer} is expected to operate via side-effects.
*
- * @param Type of reference argument to {@code accept()}.
+ * @param Type of reference argument to {@code accept()}
*
* @see BiConsumer
* @since 1.8
@@ -44,5 +44,5 @@ public interface ObjIntConsumer {
* @param t an input object
* @param value an input value
*/
- public void accept(T t, int value);
+ void accept(T t, int value);
}
diff --git a/jdk/src/share/classes/java/util/function/ObjLongConsumer.java b/jdk/src/share/classes/java/util/function/ObjLongConsumer.java
index c2f19fba741..f90a4f84c77 100644
--- a/jdk/src/share/classes/java/util/function/ObjLongConsumer.java
+++ b/jdk/src/share/classes/java/util/function/ObjLongConsumer.java
@@ -30,7 +30,7 @@ package java.util.function;
* {@link BiConsumer}. Unlike most other functional interfaces,
* {@code ObjLongConsumer} is expected to operate via side-effects.
*
- * @param Type of reference argument to {@code accept()}.
+ * @param Type of reference argument to {@code accept()}
*
* @see BiConsumer
* @since 1.8
@@ -44,5 +44,5 @@ public interface ObjLongConsumer {
* @param t an input object
* @param value an input value
*/
- public void accept(T t, long value);
+ void accept(T t, long value);
}
diff --git a/jdk/src/share/classes/java/util/function/Predicate.java b/jdk/src/share/classes/java/util/function/Predicate.java
index 627771e26af..ac207a3d593 100644
--- a/jdk/src/share/classes/java/util/function/Predicate.java
+++ b/jdk/src/share/classes/java/util/function/Predicate.java
@@ -43,7 +43,7 @@ public interface Predicate {
* @return {@code true} if the input object matches some criteria, otherwise
* {@code false}
*/
- public boolean test(T t);
+ boolean test(T t);
/**
* Returns a predicate which evaluates to {@code true} only if this
@@ -51,11 +51,16 @@ public interface Predicate {
* this predicate returns {@code false} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ANDed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ANDed with this predicate
* @return a new predicate which returns {@code true} only if both
- * predicates return {@code true}.
+ * predicates return {@code true}
+ * @throws NullPointerException if p is null
*/
- public default Predicate and(Predicate super T> p) {
+ default Predicate and(Predicate super T> p) {
Objects.requireNonNull(p);
return (t) -> test(t) && p.test(t);
}
@@ -66,7 +71,7 @@ public interface Predicate {
* @return a new predicate who's result is always the opposite of this
* predicate.
*/
- public default Predicate negate() {
+ default Predicate negate() {
return (t) -> !test(t);
}
@@ -76,25 +81,32 @@ public interface Predicate {
* predicate returns {@code true} then the remaining predicate is not
* evaluated.
*
- * @param p a predicate which will be logically-ORed with this predicate.
+ *
Any exceptions thrown by either {@code test} method are relayed
+ * to the caller; if performing first operation throws an exception, the
+ * second operation will not be performed.
+ *
+ * @param p a predicate which will be logically-ORed with this predicate
* @return a new predicate which returns {@code true} if either predicate
- * returns {@code true}.
+ * returns {@code true}
+ * @throws NullPointerException if p is null
*/
- public default Predicate or(Predicate super T> p) {
+ default Predicate or(Predicate super T> p) {
Objects.requireNonNull(p);
return (t) -> test(t) || p.test(t);
}
/**
- * Returns a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
+ * Returns a predicate who's result matches
+ * {@code Objects.equals(target, t)}.
*
- * @param p a predicate which will be logically-XORed with this predicte.
- * @return a predicate that evaluates to {@code true} if both or neither of
- * the component predicates evaluate to {@code true}.
+ * @param the type of values evaluated by the predicate
+ * @param target the target value to be compared for equality
+ * @return a predicate who's result matches
+ * {@code Objects.equals(target, t)}
*/
- public default Predicate xor(Predicate super T> p) {
- Objects.requireNonNull(p);
- return (t) -> test(t) ^ p.test(t);
+ static Predicate isEqual(Object target) {
+ return (null == target)
+ ? Objects::isNull
+ : object -> target.equals(object);
}
}
diff --git a/jdk/src/share/classes/java/util/function/Supplier.java b/jdk/src/share/classes/java/util/function/Supplier.java
index 60bc801eb91..728994b17cf 100644
--- a/jdk/src/share/classes/java/util/function/Supplier.java
+++ b/jdk/src/share/classes/java/util/function/Supplier.java
@@ -40,5 +40,5 @@ public interface Supplier {
*
* @return an object
*/
- public T get();
+ T get();
}
diff --git a/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java b/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java
index a4a03e61b45..bd82422b9ab 100644
--- a/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java
+++ b/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java
@@ -46,5 +46,5 @@ public interface ToDoubleBiFunction {
* @param u an input object
* @return the function result value
*/
- public double applyAsDouble(T t, U u);
+ double applyAsDouble(T t, U u);
}
diff --git a/jdk/src/share/classes/java/util/function/ToDoubleFunction.java b/jdk/src/share/classes/java/util/function/ToDoubleFunction.java
index 87f19fce41e..c63d984a7ed 100644
--- a/jdk/src/share/classes/java/util/function/ToDoubleFunction.java
+++ b/jdk/src/share/classes/java/util/function/ToDoubleFunction.java
@@ -42,5 +42,5 @@ public interface ToDoubleFunction {
* @param t the input object
* @return the function result value
*/
- public double applyAsDouble(T t);
+ double applyAsDouble(T t);
}
diff --git a/jdk/src/share/classes/java/util/function/ToIntBiFunction.java b/jdk/src/share/classes/java/util/function/ToIntBiFunction.java
index d7c727fa31c..3fc6d560030 100644
--- a/jdk/src/share/classes/java/util/function/ToIntBiFunction.java
+++ b/jdk/src/share/classes/java/util/function/ToIntBiFunction.java
@@ -28,10 +28,10 @@ package java.util.function;
* Apply a function to the input arguments, yielding an appropriate result.
* This is the {@code int}-bearing specialization for {@link BiFunction}.
*
- * @param the type of the first argument to the {@code applyAsLong}
- * operation.
- * @param the type of the second argument to the {@code applyAsLong}
- * operation.
+ * @param the type of the first argument to the {@code applyAsInt}
+ * operation
+ * @param the type of the second argument to the {@code applyAsInt}
+ * operation
*
* @see BiFunction
* @since 1.8
@@ -46,5 +46,5 @@ public interface ToIntBiFunction {
* @param u an input object
* @return the function result value
*/
- public int applyAsInt(T t, U u);
+ int applyAsInt(T t, U u);
}
diff --git a/jdk/src/share/classes/java/util/function/ToIntFunction.java b/jdk/src/share/classes/java/util/function/ToIntFunction.java
index 848a7b4486c..c3fd2f7004f 100644
--- a/jdk/src/share/classes/java/util/function/ToIntFunction.java
+++ b/jdk/src/share/classes/java/util/function/ToIntFunction.java
@@ -42,5 +42,5 @@ public interface ToIntFunction {
* @param t the input object
* @return the function result value
*/
- public int applyAsInt(T t);
+ int applyAsInt(T t);
}
diff --git a/jdk/src/share/classes/java/util/function/ToLongBiFunction.java b/jdk/src/share/classes/java/util/function/ToLongBiFunction.java
index 994fa49a536..abf6f7851d1 100644
--- a/jdk/src/share/classes/java/util/function/ToLongBiFunction.java
+++ b/jdk/src/share/classes/java/util/function/ToLongBiFunction.java
@@ -46,5 +46,5 @@ public interface ToLongBiFunction {
* @param u an input object
* @return the function result value
*/
- public long applyAsLong(T t, U u);
+ long applyAsLong(T t, U u);
}
diff --git a/jdk/src/share/classes/java/util/function/ToLongFunction.java b/jdk/src/share/classes/java/util/function/ToLongFunction.java
index 6d5877b6814..4489c6fa655 100644
--- a/jdk/src/share/classes/java/util/function/ToLongFunction.java
+++ b/jdk/src/share/classes/java/util/function/ToLongFunction.java
@@ -42,5 +42,5 @@ public interface ToLongFunction {
* @param t the input object
* @return the function result value
*/
- public long applyAsLong(T t);
+ long applyAsLong(T t);
}
diff --git a/jdk/src/share/classes/java/util/function/UnaryOperator.java b/jdk/src/share/classes/java/util/function/UnaryOperator.java
index 8e92291887e..87fda16bbeb 100644
--- a/jdk/src/share/classes/java/util/function/UnaryOperator.java
+++ b/jdk/src/share/classes/java/util/function/UnaryOperator.java
@@ -36,4 +36,13 @@ package java.util.function;
*/
@FunctionalInterface
public interface UnaryOperator extends Function {
+
+ /**
+ * Returns a unary operator that provides its input value as the result.
+ *
+ * @return a unary operator that provides its input value as the result
+ */
+ static UnaryOperator identity() {
+ return t -> t;
+ }
}
From 862e2f6a7d03e9628f3813b64d28d60781b13d00 Mon Sep 17 00:00:00 2001
From: Henry Jen
Date: Thu, 9 May 2013 14:44:56 -0700
Subject: [PATCH 004/101] 8006884: (fs) Add Files.list, lines and find
Co-authored-by: Alan Bateman
Reviewed-by: briangoetz, mduigou
---
.../java/nio/file/FileTreeIterator.java | 124 ++++
.../classes/java/nio/file/FileTreeWalker.java | 16 +-
.../share/classes/java/nio/file/Files.java | 342 +++++++++-
.../java/nio/file/Files/FaultyFileSystem.java | 499 ++++++++++++++
.../nio/file/Files/PassThroughFileSystem.java | 4 +-
jdk/test/java/nio/file/Files/StreamTest.java | 621 ++++++++++++++++++
6 files changed, 1599 insertions(+), 7 deletions(-)
create mode 100644 jdk/src/share/classes/java/nio/file/FileTreeIterator.java
create mode 100644 jdk/test/java/nio/file/Files/FaultyFileSystem.java
create mode 100644 jdk/test/java/nio/file/Files/StreamTest.java
diff --git a/jdk/src/share/classes/java/nio/file/FileTreeIterator.java b/jdk/src/share/classes/java/nio/file/FileTreeIterator.java
new file mode 100644
index 00000000000..63b4dc767d8
--- /dev/null
+++ b/jdk/src/share/classes/java/nio/file/FileTreeIterator.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 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 java.nio.file;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.nio.file.FileTreeWalker.Event;
+
+/**
+ * An {@code Iterator to iterate over the nodes of a file tree.
+ *
+ *
+ */
+
+class FileTreeIterator implements Iterator, Closeable {
+ private final FileTreeWalker walker;
+ private Event next;
+
+ /**
+ * Creates a new iterator to walk the file tree starting at the given file.
+ *
+ * @throws IllegalArgumentException
+ * if {@code maxDepth} is negative
+ * @throws IOException
+ * if an I/O errors occurs opening the starting file
+ * @throws SecurityException
+ * if the security manager denies access to the starting file
+ * @throws NullPointerException
+ * if {@code start} or {@code options} is {@ocde null} or
+ * the options array contains a {@code null} element
+ */
+ FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
+ throws IOException
+ {
+ this.walker = new FileTreeWalker(Arrays.asList(options), maxDepth);
+ this.next = walker.walk(start);
+ assert next.type() == FileTreeWalker.EventType.ENTRY ||
+ next.type() == FileTreeWalker.EventType.START_DIRECTORY;
+
+ // IOException if there a problem accessing the starting file
+ IOException ioe = next.ioeException();
+ if (ioe != null)
+ throw ioe;
+ }
+
+ private void fetchNextIfNeeded() {
+ if (next == null) {
+ FileTreeWalker.Event ev = walker.next();
+ while (ev != null) {
+ IOException ioe = ev.ioeException();
+ if (ioe != null)
+ throw new UncheckedIOException(ioe);
+
+ // END_DIRECTORY events are ignored
+ if (ev.type() != FileTreeWalker.EventType.END_DIRECTORY) {
+ next = ev;
+ return;
+ }
+ ev = walker.next();
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (!walker.isOpen())
+ throw new IllegalStateException();
+ fetchNextIfNeeded();
+ return next != null;
+ }
+
+ @Override
+ public Event next() {
+ if (!walker.isOpen())
+ throw new IllegalStateException();
+ fetchNextIfNeeded();
+ if (next == null)
+ throw new NoSuchElementException();
+ Event result = next;
+ next = null;
+ return result;
+ }
+
+ @Override
+ public void close() {
+ walker.close();
+ }
+}
diff --git a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java
index 8ce95bc8240..85086e1e5a8 100644
--- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java
@@ -29,8 +29,8 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayDeque;
+import java.util.Collection;
import java.util.Iterator;
-import java.util.Set;
import sun.nio.fs.BasicFileAttributesHolder;
/**
@@ -164,8 +164,17 @@ class FileTreeWalker implements Closeable {
/**
* Creates a {@code FileTreeWalker}.
+ *
+ * @throws IllegalArgumentException
+ * if {@code maxDepth} is negative
+ * @throws ClassCastException
+ * if (@code options} contains an element that is not a
+ * {@code FileVisitOption}
+ * @throws NullPointerException
+ * if {@code options} is {@ocde null} or the options
+ * array contains a {@code null} element
*/
- FileTreeWalker(Set options, int maxDepth) {
+ FileTreeWalker(Collection options, int maxDepth) {
boolean fl = false;
for (FileVisitOption option: options) {
// will throw NPE if options contains null
@@ -175,6 +184,9 @@ class FileTreeWalker implements Closeable {
throw new AssertionError("Should not get here");
}
}
+ if (maxDepth < 0)
+ throw new IllegalArgumentException("'maxDepth' is negative");
+
this.followLinks = fl;
this.linkOptions = (fl) ? new LinkOption[0] :
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java
index a935a58001e..d816ad9fdf5 100644
--- a/jdk/src/share/classes/java/nio/file/Files.java
+++ b/jdk/src/share/classes/java/nio/file/Files.java
@@ -29,6 +29,7 @@ import java.nio.file.attribute.*;
import java.nio.file.spi.FileSystemProvider;
import java.nio.file.spi.FileTypeDetector;
import java.nio.channels.SeekableByteChannel;
+import java.io.Closeable;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
@@ -38,7 +39,13 @@ import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.util.*;
+import java.util.function.BiPredicate;
+import java.util.stream.CloseableStream;
+import java.util.stream.DelegatingStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.nio.charset.Charset;
@@ -2587,9 +2594,6 @@ public final class Files {
FileVisitor super Path> visitor)
throws IOException
{
- if (maxDepth < 0)
- throw new IllegalArgumentException("'maxDepth' is negative");
-
/**
* Create a FileTreeWalker to walk the file tree, invoking the visitor
* for each event.
@@ -3177,4 +3181,336 @@ public final class Files {
}
return path;
}
+
+ // -- Stream APIs --
+
+ /**
+ * Implementation of CloseableStream
+ */
+ private static class DelegatingCloseableStream extends DelegatingStream
+ implements CloseableStream
+ {
+ private final Closeable closeable;
+
+ DelegatingCloseableStream(Closeable c, Stream delegate) {
+ super(delegate);
+ this.closeable = c;
+ }
+
+ public void close() {
+ try {
+ closeable.close();
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+ }
+
+ /**
+ * Return a lazily populated {@code CloseableStream}, the elements of
+ * which are the entries in the directory. The listing is not recursive.
+ *
+ *
The elements of the stream are {@link Path} objects that are
+ * obtained as if by {@link Path#resolve(Path) resolving} the name of the
+ * directory entry against {@code dir}. Some file systems maintain special
+ * links to the directory itself and the directory's parent directory.
+ * Entries representing these links are not included.
+ *
+ *
The stream is weakly consistent. It is thread safe but does
+ * not freeze the directory while iterating, so it may (or may not)
+ * reflect updates to the directory that occur after returning from this
+ * method.
+ *
+ *
When not using the try-with-resources construct, then the stream's
+ * {@link CloseableStream#close close} method should be invoked after the
+ * operation is completed so as to free any resources held for the open
+ * directory. Operating on a closed stream behaves as if the end of stream
+ * has been reached. Due to read-ahead, one or more elements may be
+ * returned after the stream has been closed.
+ *
+ *
If an {@link IOException} is thrown when accessing the directory
+ * after this method has returned, it is wrapped in an {@link
+ * UncheckedIOException} which will be thrown from the method that caused
+ * the access to take place.
+ *
+ * @param dir The path to the directory
+ *
+ * @return The {@code CloseableStream} describing the content of the
+ * directory
+ *
+ * @throws NotDirectoryException
+ * if the file could not otherwise be opened because it is not
+ * a directory (optional specific exception)
+ * @throws IOException
+ * if an I/O error occurs when opening the directory
+ * @throws SecurityException
+ * In the case of the default provider, and a security manager is
+ * installed, the {@link SecurityManager#checkRead(String) checkRead}
+ * method is invoked to check read access to the directory.
+ *
+ * @see #newDirectoryStream(Path)
+ * @since 1.8
+ */
+ public static CloseableStream list(Path dir) throws IOException {
+ DirectoryStream ds = Files.newDirectoryStream(dir);
+ final Iterator delegate = ds.iterator();
+
+ // Re-wrap DirectoryIteratorException to UncheckedIOException
+ Iterator it = new Iterator() {
+ public boolean hasNext() {
+ try {
+ return delegate.hasNext();
+ } catch (DirectoryIteratorException e) {
+ throw new UncheckedIOException(e.getCause());
+ }
+ }
+ public Path next() {
+ try {
+ return delegate.next();
+ } catch (DirectoryIteratorException e) {
+ throw new UncheckedIOException(e.getCause());
+ }
+ }
+ };
+
+ return new DelegatingCloseableStream<>(ds,
+ StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
+ Spliterator.DISTINCT)));
+ }
+
+ /**
+ * Return a {@code CloseableStream} that is lazily populated with {@code
+ * Path} by walking the file tree rooted at a given starting file. The
+ * file tree is traversed depth-first, the elements in the stream
+ * are {@link Path} objects that are obtained as if by {@link
+ * Path#resolve(Path) resolving} the relative path against {@code start}.
+ *
+ *
The {@code stream} walks the file tree as elements are consumed.
+ * The {@code CloseableStream} returned is guaranteed to have at least one
+ * element, the starting file itself. For each file visited, the stream
+ * attempts to read its {@link BasicFileAttributes}. If the file is a
+ * directory and can be opened successfully, entries in the directory, and
+ * their descendants will follow the directory in the stream as
+ * they are encountered. When all entries have been visited, then the
+ * directory is closed. The file tree walk then continues at the next
+ * sibling of the directory.
+ *
+ *
The stream is weakly consistent. It does not freeze the
+ * file tree while iterating, so it may (or may not) reflect updates to
+ * the file tree that occur after returned from this method.
+ *
+ *
By default, symbolic links are not automatically followed by this
+ * method. If the {@code options} parameter contains the {@link
+ * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
+ * followed. When following links, and the attributes of the target cannot
+ * be read, then this method attempts to get the {@code BasicFileAttributes}
+ * of the link.
+ *
+ *
If the {@code options} parameter contains the {@link
+ * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
+ * track of directories visited so that cycles can be detected. A cycle
+ * arises when there is an entry in a directory that is an ancestor of the
+ * directory. Cycle detection is done by recording the {@link
+ * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
+ * or if file keys are not available, by invoking the {@link #isSameFile
+ * isSameFile} method to test if a directory is the same file as an
+ * ancestor. When a cycle is detected it is treated as an I/O error with
+ * an instance of {@link FileSystemLoopException}.
+ *
+ *
The {@code maxDepth} parameter is the maximum number of levels of
+ * directories to visit. A value of {@code 0} means that only the starting
+ * file is visited, unless denied by the security manager. A value of
+ * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
+ * levels should be visited.
+ *
+ *
When a security manager is installed and it denies access to a file
+ * (or directory), then it is ignored and not included in the stream.
+ *
+ *
When not using the try-with-resources construct, then the stream's
+ * {@link CloseableStream#close close} method should be invoked after the
+ * operation is completed so as to free any resources held for the open
+ * directory. Operate the stream after it is closed will throw an
+ * {@link java.lang.IllegalStateException}.
+ *
+ *
If an {@link IOException} is thrown when accessing the directory
+ * after this method has returned, it is wrapped in an {@link
+ * UncheckedIOException} which will be thrown from the method that caused
+ * the access to take place.
+ *
+ * @param start
+ * the starting file
+ * @param maxDepth
+ * the maximum number of directory levels to visit
+ * @param options
+ * options to configure the traversal
+ *
+ * @return the {@link CloseableStream} of {@link Path}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code maxDepth} parameter is negative
+ * @throws SecurityException
+ * If the security manager denies access to the starting file.
+ * In the case of the default provider, the {@link
+ * SecurityManager#checkRead(String) checkRead} method is invoked
+ * to check read access to the directory.
+ * @throws IOException
+ * if an I/O error is thrown when accessing the starting file.
+ * @since 1.8
+ */
+ public static CloseableStream walk(Path start, int maxDepth,
+ FileVisitOption... options)
+ throws IOException
+ {
+ FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+ return new DelegatingCloseableStream<>(iterator,
+ StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+ .map(entry -> entry.file()));
+ }
+
+ /**
+ * Return a {@code CloseableStream} that is lazily populated with {@code
+ * Path} by walking the file tree rooted at a given starting file. The
+ * file tree is traversed depth-first, the elements in the stream
+ * are {@link Path} objects that are obtained as if by {@link
+ * Path#resolve(Path) resolving} the relative path against {@code start}.
+ *
+ *
This method works as if invoking it were equivalent to evaluating the
+ * expression:
+ *
+ * walk(start, Integer.MAX_VALUE, options)
+ *
+ * In other words, it visits all levels of the file tree.
+ *
+ * @param start
+ * the starting file
+ * @param options
+ * options to configure the traversal
+ *
+ * @return the {@link CloseableStream} of {@link Path}
+ *
+ * @throws SecurityException
+ * If the security manager denies access to the starting file.
+ * In the case of the default provider, the {@link
+ * SecurityManager#checkRead(String) checkRead} method is invoked
+ * to check read access to the directory.
+ * @throws IOException
+ * if an I/O error is thrown when accessing the starting file.
+ *
+ * @see #walk(Path, int, FileVisitOption...)
+ * @since 1.8
+ */
+ public static CloseableStream walk(Path start,
+ FileVisitOption... options)
+ throws IOException
+ {
+ return walk(start, Integer.MAX_VALUE, options);
+ }
+
+ /**
+ * Return a {@code CloseableStream} that is lazily populated with {@code
+ * Path} by searching for files in a file tree rooted at a given starting
+ * file.
+ *
+ *
This method walks the file tree in exactly the manner specified by
+ * the {@link #walk walk} method. For each file encountered, the given
+ * {@link BiPredicate} is invoked with its {@link Path} and {@link
+ * BasicFileAttributes}. The {@code Path} object is obtained as if by
+ * {@link Path#resolve(Path) resolving} the relative path against {@code
+ * start} and is only included in the returned {@link CloseableStream} if
+ * the {@code BiPredicate} returns true. Compare to calling {@link
+ * java.util.stream.Stream#filter filter} on the {@code Stream}
+ * returned by {@code walk} method, this method may be more efficient by
+ * avoiding redundant retrieval of the {@code BasicFileAttributes}.
+ *
+ *
If an {@link IOException} is thrown when accessing the directory
+ * after returned from this method, it is wrapped in an {@link
+ * UncheckedIOException} which will be thrown from the method that caused
+ * the access to take place.
+ *
+ * @param start
+ * the starting file
+ * @param maxDepth
+ * the maximum number of directory levels to search
+ * @param matcher
+ * the function used to decide whether a file should be included
+ * in the returned stream
+ * @param options
+ * options to configure the traversal
+ *
+ * @return the {@link CloseableStream} of {@link Path}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code maxDepth} parameter is negative
+ * @throws SecurityException
+ * If the security manager denies access to the starting file.
+ * In the case of the default provider, the {@link
+ * SecurityManager#checkRead(String) checkRead} method is invoked
+ * to check read access to the directory.
+ * @throws IOException
+ * if an I/O error is thrown when accessing the starting file.
+ *
+ * @see #walk(Path, int, FileVisitOption...)
+ * @since 1.8
+ */
+ public static CloseableStream find(Path start,
+ int maxDepth,
+ BiPredicate matcher,
+ FileVisitOption... options)
+ throws IOException
+ {
+ FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
+ return new DelegatingCloseableStream<>(iterator,
+ StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
+ .filter(entry -> matcher.test(entry.file(), entry.attributes()))
+ .map(entry -> entry.file()));
+ }
+
+ /**
+ * Read all lines from a file as a {@code CloseableStream}. Unlike {@link
+ * #readAllLines(Path, Charset) readAllLines}, this method does not read
+ * all lines into a {@code List}, but instead populates lazily as the stream
+ * is consumed.
+ *
+ *
Bytes from the file are decoded into characters using the specified
+ * charset and the same line terminators as specified by {@code
+ * readAllLines} are supported.
+ *
+ *
After this method returns, then any subsequent I/O exception that
+ * occurs while reading from the file or when a malformed or unmappable byte
+ * sequence is read, is wrapped in an {@link UncheckedIOException} that will
+ * be thrown form the
+ * {@link java.util.stream.Stream} method that caused the read to take
+ * place. In case an {@code IOException} is thrown when closing the file,
+ * it is also wrapped as an {@code UncheckedIOException}.
+ *
+ *
-Note that the name of the type is always a string for a fully qualified name. You can use any of these types to create new instances, e.g.:
+Note that the name of the type is always a string for a fully qualified name. You can use any of these expressions to create new instances, e.g.:
- var anArrayList = new Java.type("java.util.ArrayList")
+ var anArrayList = new (Java.type("java.util.ArrayList"))
or
@@ -496,6 +507,37 @@ However, once you retrieved the outer class, you can access the inner class as a
You can access both static and non-static inner classes. If you want to create an instance of a non-static inner class, remember to pass an instance of its outer class as the first argument to the constructor.
+
+In addition to creating new instances, the type objects returned from Java.type calls can also be used to access the
+static fields and methods of the classes:
+
+ var File = Java.type("java.io.File")
+ File.createTempFile("nashorn", ".tmp")
+
+
+Methods with names of the form isXxx(), getXxx(), and setXxx() can also be used as properties, for both instances and statics.
+
+
+A type object returned from Java.type is distinct from a java.lang.Class object. You can obtain one from the other using properties class and static on them.
+
+ var ArrayList = Java.type("java.util.ArrayList")
+ var a = new ArrayList
+
+ // All of the following print true:
+ print("Type acts as target of instanceof: " + (a instanceof ArrayList))
+ print("Class doesn't act as target of instanceof: " + !(a instanceof a.getClass()))
+ print("Type is not same as instance's getClass(): " + (a.getClass() !== ArrayList))
+ print("Type's `class` property is same as instance getClass(): " + (a.getClass() === ArrayList.class))
+ print("Type is same as instance getClass()'s `static` property: " + (a.getClass().static === ArrayList))
+
+
+You can think of the type object as similar to the class names as used in Java source code: you use them as the
+arguments to the new and instanceof operators and as the namespace for the static fields
+and methods, but they are different than the runtime Class objects returned by getClass() calls.
+Syntactically and semantically, this separation produces code that is most similar to Java code, where a distinction
+between compile-time class expressions and runtime class objects also exists. (Also, Java can't have the equivalent of static
+property on a Class object since compile-time class expressions are never reified as objects).
+
Importing Java Packages, Classes
@@ -558,10 +600,7 @@ with (SwingGui) {
Creating, Converting and Using Java Arrays
-Array element access or length access is
-the same as in Java. Also, a script array can be used when a Java
-method expects a Java array (auto conversion). So in most cases we
-don't have to create Java arrays explicitly.
+Array element access or length access is the same as in Java.
// javaarray.js
@@ -587,7 +626,11 @@ Given a JavaScript array and a Java type, Java.toJavaArray returns
print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
-Given a Java array or Collection, Java.toJavaScriptArray returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method.i
+You can use either a string or a type object returned from Java.type() to specify the component type of the array.
+You can also omit the array type, in which case a Object[] will be created.
+
+
+Given a Java array or Collection, Java.toJavaScriptArray returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method.
var File = Java.type("java.io.File");
@@ -597,7 +640,7 @@ print(jsList);
-
Implementing Java Interfaces
+
Implementing Java interfaces
A Java interface can be implemented in JavaScript by using a
Java anonymous class-like syntax:
@@ -631,8 +674,8 @@ th.join();
-
-
Extending Java classes
+
+
Extending Abstract Java Classes
If a Java class is abstract, you can instantiate an anonymous subclass of it using an argument list that is applicable to any of its public or protected constructors, but inserting a JavaScript object with functions properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the JavaScript function will provide implementation for all overloads. E.g.:
@@ -671,6 +714,9 @@ The use of functions can be taken even further; if you are invoking a Java metho
Here, Timer.schedule() expects a TimerTask as its argument, so Nashorn creates an instance of a TimerTask subclass and uses the passed function to implement its only abstract method, run(). In this usage though, you can't use non-default constructors; the type must be either an interface, or must have a protected or public no-arg constructor.
+
+
+
Extending Concrete Java Classes
To extend a concrete Java class, you have to use Java.extend function.
Java.extend returns a type object for a subclass of the specified Java class (or implementation of the specified interface) that acts as a script-to-Java adapter for it.
@@ -695,26 +741,178 @@ var printAddInvokedArrayList = new ArrayListExtender() {
printSizeInvokedArrayList.size();
printAddInvokedArrayList.add(33, 33);
+
+The reason you must use Java.extend() with concrete classes is that with concrete classes, there can be a
+syntactic ambiguity if you just invoke their constructor. Consider this example:
+
+
+var t = new java.lang.Thread({ run: function() { print("Hello!") } })
+
+
+If we allowed subclassing of concrete classes with constructor syntax, Nashorn couldn't tell if you're creating a new
+Thread and passing it a Runnable at this point, or you are subclassing Thread and
+passing it a new implementation for its own run() method.
+
+
+
+
Implementing Multiple Interfaces
+
+Java.extend can in fact take a list of multiple types. At most one of the types can be a class, and the rest must
+be interfaces (the class doesn't have to be the first in the list). You will get back an object that extends the class and
+implements all the interfaces. (Obviously, if you only specify interfaces and no class, the object will extend java.lang.Object).
+
+
+
Class-Bound Implementations
+
+The methods shown so far for extending Java classes and implementing interfaces – passing an implementation JavaScript object
+or function to a constructor, or using Java.extend with new – all produce classes that take an
+extra JavaScript object parameter in their constructors that specifies the implementation. The implementation is therefore always bound
+to the actual instance being created with new, and not to the whole class. This has some advantages, for example in the
+memory footprint of the runtime, as Nashorn can just create a single "universal adapter" for every combination of types being implemented.
+In reality, the below code shows that different instantiations of, say, Runnable have the same class regardless of them having
+different JavaScript implementation objects:
+
+
+var Runnable = java.lang.Runnable;
+var r1 = new Runnable(function() { print("I'm runnable 1!") })
+var r2 = new Runnable(function() { print("I'm runnable 2!") })
+r1.run()
+r2.run()
+print("We share the same class: " + (r1.class === r2.class))
+
+
+prints:
+
+
+I'm runnable 1!
+I'm runnable 2!
+We share the same class: true
+
+
+Sometimes, however, you'll want to extend a Java class or implement an interface with implementation bound to the class, not to
+its instances. Such a need arises, for example, when you need to pass the class for instantiation to an external API; prime example
+of this is the JavaFX framework where you need to pass an Application class to the FX API and let it instantiate it.
+
+
+Fortunately, there's a solution for that: Java.extend() – aside from being able to take any number of type parameters
+denoting a class to extend and interfaces to implement – can also take one last argument that has to be a JavaScript object
+that serves as the implementation for the methods. In this case, Java.extend() will create a class that has the same
+constructors as the original class had, as they don't need to take an an extra implementation object parameter. The example below
+shows how you can create class-bound implementations, and shows that in this case, the implementation classes for different invocations
+are indeed different:
+
+I'm runnable 1!
+I'm runnable 2!
+We share the same class: false
+
+
+As you can see, the major difference here is that we moved the implementation object into the invocation of Java.extend
+from the constructor invocations – indeed the constructor invocations now don't even need to take an extra parameter! Since
+the implementations are bound to a class, the two classes obviously can't be the same, and we indeed see that the two runnables no
+longer share the same class – every invocation of Java.extend() with a class-specific implementation object triggers
+the creation of a new Java adapter class.
+
+
+Finally, the adapter classes with class-bound implementations can still take an additional constructor parameter to further
+override the behavior on a per-instance basis. Thus, you can even combine the two approaches: you can provide part of the implementation
+in a class-based JavaScript implementation object passed to Java.extend, and part in another object passed to the constructor.
+Whatever functions are provided by the constructor-passed object will override the functions in the class-bound object.
+
+
+var RunnableImpl = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
+var r1 = new RunnableImpl()
+var r2 = new RunnableImpl(function() { print("I'm runnable 2!") })
+r1.run()
+r2.run()
+print("We share the same class: " + (r1.class === r2.class))
+
+
+prints:
+
+
+I'm runnable 1!
+I'm runnable 2!
+We share the same class: true
+
Overload Resolution
Java methods can be overloaded by argument types. In Java,
overload resolution occurs at compile time (performed by javac).
-When calling Java methods from a script, the script
-interpreter/compiler needs to select the appropriate method. With
-the JavaScript engine, you do not need to do anything special - the
-correct Java method overload variant is selected based on the
-argument types. But, sometimes you may want (or have) to explicitly
-select a particular overload variant.
+When calling Java methods from Nashorn, the appropriate method will be
+selected based on the argument types at invocation time. You do not need
+to do anything special – the correct Java method overload variant
+is selected based automatically. You still have the option of explicitly
+specifying a particular overload variant. Reasons for this include
+either running into a genuine ambiguity with actual argument types, or
+rarely reasons of performance – if you specify the actual overload
+then the engine doesn't have to perform resolution during invocation.
+Individual overloads of a Java methods are exposed as special properties
+with the name of the method followed with its signature in parentheses.
+You can invoke them like this:
// overload.js
var out = java.lang.System.out;
// select a particular print function
-out["println(java.lang.Object)"]("hello");
+out["println(Object)"]("hello");
+
+Note that you normally don't even have to use qualified class names in
+the signatures as long as the unqualified name of the type is sufficient
+for uniquely identifying the signature. In practice this means that only
+in the extremely unlikely case that two overloads only differ in
+parameter types that have identical unqualified names but come from
+different packages would you need to use the fully qualified name of the
+class.
+
+
+
+
Mapping of Data Types Between Java and JavaScript
+
+We have previously shown some of the data type mappings between Java and JavaScript.
+We saw that arrays need to be explicitly converted. We have also shown that JavaScript functions
+are automatically converted to SAM types when passed as parameters to Java methods. Most other
+conversions work as you would expect.
+
+
+Every JavaScript object is also a java.util.Map so APIs receiving maps will receive them directly.
+
+
+When numbers are passed to a Java API, they will be converted to the expected target numeric type, either boxed or
+primitive, but if the target type is less specific, say Number or Object, you can only
+count on them being a Number, and have to test specifically for whether it's a boxed Double,
+Integer, Long, etc. – it can be any of these due to internal optimizations. Also, you
+can pass any JavaScript value to a Java API expecting either a boxed or primitive number; the JavaScript specification's
+ToNumber conversion algorithm will be applied to the value.
+
+
+In a similar vein, if a Java method expects a String or a Boolean, the values will be
+converted using all conversions allowed by the JavaScript specification's ToString and ToBoolean
+conversions.
+
+
+Finally, a word of caution about strings. Due to internal performance optimizations of string operations, JavaScript strings are
+not always necessarily of type java.lang.String, but they will always be of type java.lang.CharSequence.
+If you pass them to a Java method that expects a java.lang.String parameter, then you will naturally receive a Java
+String, but if the signature of your method is more generic, i.e. it receives a java.lang.Object parameter, you can
+end up with an object of private engine implementation class that implements CharSequence but is not a Java String.
+
Implementing Your Own Script Engine
From 8bbf3e9b524c0bd260da5294218e7623f24229e7 Mon Sep 17 00:00:00 2001
From: Athijegannathan Sundararajan
Date: Wed, 15 May 2013 19:45:16 +0530
Subject: [PATCH 010/101] 8012305: Function.bind can't be called on prototype
function inside constructor
Reviewed-by: lagergren, attila
---
nashorn/test/script/basic/JDK-8012305.js | 39 +++++++++++++++++++
.../test/script/basic/JDK-8012305.js.EXPECTED | 1 +
2 files changed, 40 insertions(+)
create mode 100644 nashorn/test/script/basic/JDK-8012305.js
create mode 100644 nashorn/test/script/basic/JDK-8012305.js.EXPECTED
diff --git a/nashorn/test/script/basic/JDK-8012305.js b/nashorn/test/script/basic/JDK-8012305.js
new file mode 100644
index 00000000000..d08502defb1
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8012305.js
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8012305: Function.bind can't be called on prototype function inside constructor
+ *
+ * @test
+ * @run
+ */
+
+function MyObject() {
+ // If the call to bind is removed, then the function is properly printed.
+ print("function " + this._process);
+ this._process = this._process.bind(this);
+}
+
+MyObject.prototype._process = function() { print("Message "); }
+
+var s = new MyObject();
diff --git a/nashorn/test/script/basic/JDK-8012305.js.EXPECTED b/nashorn/test/script/basic/JDK-8012305.js.EXPECTED
new file mode 100644
index 00000000000..b509e0c1051
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8012305.js.EXPECTED
@@ -0,0 +1 @@
+function function() { print("Message "); }
From e5be7a02eaf8f90d5c7f84338af5854c2e164e7f Mon Sep 17 00:00:00 2001
From: James Laskey
Date: Wed, 15 May 2013 12:09:38 -0300
Subject: [PATCH 011/101] 8014648: Exclude testing and infrastructure packages
from code coverage, round two
Reviewed-by: sundar
---
nashorn/make/code_coverage.xml | 12 ++++
.../internal/runtime/options/Option.java | 4 --
.../internal/runtime/options/Options.java | 2 -
.../internal/runtime/options/ValueOption.java | 59 -------------------
nashorn/test/script/basic/allgettersetters.js | 3 +
5 files changed, 15 insertions(+), 65 deletions(-)
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/options/ValueOption.java
diff --git a/nashorn/make/code_coverage.xml b/nashorn/make/code_coverage.xml
index 457f6308154..3e2860f8d9d 100644
--- a/nashorn/make/code_coverage.xml
+++ b/nashorn/make/code_coverage.xml
@@ -153,6 +153,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java b/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java
index ddbeba184d4..feaff1f1805 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java
@@ -42,10 +42,6 @@ public class Option {
this.value = value;
}
- void setValue(final T value) {
- this.value = value;
- }
-
/**
* Return the value of an option
* @return the option value
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
index 286feec907b..52864a6652a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
@@ -501,8 +501,6 @@ public final class Options {
return new Option<>(TimeZone.getTimeZone(value));
case "keyvalues":
return new KeyValueOption(value);
- case "values":
- return new ValueOption(value);
case "log":
final KeyValueOption kv = new KeyValueOption(value);
Logging.initialize(kv.getValues());
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/options/ValueOption.java b/nashorn/src/jdk/nashorn/internal/runtime/options/ValueOption.java
deleted file mode 100644
index 2f4461f44ca..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/ValueOption.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.runtime.options;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.StringTokenizer;
-
-/**
- * This option represents a collection of comma separated values
- */
-public class ValueOption extends Option {
-
- private Collection values;
-
- ValueOption(final String value) {
- super(value);
- if (value != null) {
- values = new LinkedHashSet<>();
- final StringTokenizer st = new StringTokenizer(getValue(), ",");
- while (st.hasMoreElements()) {
- values.add(st.nextToken());
- }
- }
- }
-
- /**
- * Get the values in the option
- * @return collection of strings
- */
- public Collection getValues() {
- return Collections.unmodifiableCollection(values);
- }
-
-}
diff --git a/nashorn/test/script/basic/allgettersetters.js b/nashorn/test/script/basic/allgettersetters.js
index 0f6753c23a4..1cb956239e5 100644
--- a/nashorn/test/script/basic/allgettersetters.js
+++ b/nashorn/test/script/basic/allgettersetters.js
@@ -34,6 +34,9 @@ function checkGetterSetter(obj, expectError) {
for (var i in properties) {
var prop = properties[i];
try {
+ if (!/\d.*/.test(prop)) {
+ eval("obj." + prop + " = " + "obj." + prop + ";");
+ }
obj[prop] = obj[prop];
} catch (e) {
if (!expectError || !(e instanceof TypeError)) {
From 18bdc5fd42353d59f803b64377033e4d76af90af Mon Sep 17 00:00:00 2001
From: Attila Szegedi
Date: Wed, 15 May 2013 20:21:59 +0200
Subject: [PATCH 012/101] 8014647: Allow class-based overrides to be
initialized with a ScriptFunction
Reviewed-by: hannesw, jlaskey, sundar
---
.../linker/JavaAdapterBytecodeGenerator.java | 32 ++++++++++++++-
nashorn/test/script/basic/JDK-8014647.js | 40 +++++++++++++++++++
.../test/script/basic/JDK-8014647.js.EXPECTED | 5 +++
3 files changed, 76 insertions(+), 1 deletion(-)
create mode 100644 nashorn/test/script/basic/JDK-8014647.js
create mode 100644 nashorn/test/script/basic/JDK-8014647.js.EXPECTED
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index 37786b1e685..1fe76954391 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -310,7 +310,34 @@ final class JavaAdapterBytecodeGenerator extends JavaAdapterGeneratorBase {
Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR);
- // Assign MethodHandle fields through invoking getHandle()
+ final Label initGlobal;
+ if(samName != null) {
+ // If the class is a SAM, allow having a ScriptFunction passed as class overrides
+ final Label notAFunction = new Label();
+ mv.dup();
+ mv.instanceOf(SCRIPT_FUNCTION_TYPE);
+ mv.ifeq(notAFunction);
+ mv.checkcast(SCRIPT_FUNCTION_TYPE);
+
+ // Assign MethodHandle fields through invoking getHandle() for a ScriptFunction, only assigning the SAM
+ // method(s).
+ for (final MethodInfo mi : methodInfos) {
+ if(mi.getName().equals(samName)) {
+ mv.dup();
+ mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR);
+ } else {
+ mv.visitInsn(ACONST_NULL);
+ }
+ mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
+ }
+ initGlobal = new Label();
+ mv.goTo(initGlobal);
+ mv.visitLabel(notAFunction);
+ } else {
+ initGlobal = null;
+ }
+ // Assign MethodHandle fields through invoking getHandle() for a ScriptObject
for (final MethodInfo mi : methodInfos) {
mv.dup();
mv.aconst(mi.getName());
@@ -319,6 +346,9 @@ final class JavaAdapterBytecodeGenerator extends JavaAdapterGeneratorBase {
mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
+ if(initGlobal != null) {
+ mv.visitLabel(initGlobal);
+ }
// Assign "staticGlobal = Context.getGlobal()"
invokeGetGlobalWithNullCheck(mv);
mv.putstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
diff --git a/nashorn/test/script/basic/JDK-8014647.js b/nashorn/test/script/basic/JDK-8014647.js
new file mode 100644
index 00000000000..8ecc21101d5
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8014647.js
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8014647: Allow class-based overrides to be initialized with a ScriptFunction
+ *
+ * @test
+ * @run
+ */
+
+var RunnableImpl1 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
+var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") })
+var r1 = new RunnableImpl1()
+var r2 = new RunnableImpl2()
+var r3 = new RunnableImpl2(function() { print("I'm runnable 3!") })
+r1.run()
+r2.run()
+r3.run()
+print("r1.class === r2.class: " + (r1.class === r2.class))
+print("r2.class === r3.class: " + (r2.class === r3.class))
diff --git a/nashorn/test/script/basic/JDK-8014647.js.EXPECTED b/nashorn/test/script/basic/JDK-8014647.js.EXPECTED
new file mode 100644
index 00000000000..641a13b1d45
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8014647.js.EXPECTED
@@ -0,0 +1,5 @@
+I'm runnable 1!
+I'm runnable 2!
+I'm runnable 3!
+r1.class === r2.class: false
+r2.class === r3.class: true
From 6e9157648062e24fa6a84bb0d06f32e5674c88bd Mon Sep 17 00:00:00 2001
From: Athijegannathan Sundararajan
Date: Thu, 16 May 2013 14:52:48 +0530
Subject: [PATCH 013/101] 8009141: Avoid netscape.javascript.JSObject in
nashorn code
Reviewed-by: lagergren, hannesw
---
.../nashorn/api/scripting}/JSObject.java | 18 ++----------------
.../api/scripting/ScriptObjectMirror.java | 1 -
.../runtime/linker/JSObjectLinker.java | 2 +-
.../api/scripting/ScriptEngineTest.java | 1 -
4 files changed, 3 insertions(+), 19 deletions(-)
rename nashorn/src/{netscape/javascript => jdk/nashorn/api/scripting}/JSObject.java (87%)
diff --git a/nashorn/src/netscape/javascript/JSObject.java b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java
similarity index 87%
rename from nashorn/src/netscape/javascript/JSObject.java
rename to nashorn/src/jdk/nashorn/api/scripting/JSObject.java
index 23054c6321d..583e8f7a199 100644
--- a/nashorn/src/netscape/javascript/JSObject.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java
@@ -23,26 +23,12 @@
* questions.
*/
-package netscape.javascript;
-
-import java.applet.Applet;
+package jdk.nashorn.api.scripting;
/**
- * Stub for JSObject to get compilation going.
+ * netscape.javascript.JSObject-like interface for nashorn script objects.
*/
public abstract class JSObject {
-
- /**
- * Get the window for an {@link Applet}. Not supported
- * by Nashorn
- *
- * @param a applet
- * @return the window instance
- */
- public static JSObject getWindow(final Applet a) {
- throw new UnsupportedOperationException("getWindow");
- }
-
/**
* Call a JavaScript method
*
diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
index 266ce87f48d..e53903d3c3f 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@@ -42,7 +42,6 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
-import netscape.javascript.JSObject;
/**
* Mirror object that wraps a given ScriptObject instance. User can
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
index df9c47ff623..edd75e4dafd 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
@@ -38,7 +38,7 @@ import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.nashorn.internal.runtime.JSType;
-import netscape.javascript.JSObject;
+import jdk.nashorn.api.scripting.JSObject;
/**
* A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
index d12c9057246..a6c015a1e54 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
@@ -47,7 +47,6 @@ import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;
-import netscape.javascript.JSObject;
import org.testng.Assert;
import org.testng.annotations.Test;
From aeda283b752d5e8b74cf849bdaf151540ce503a0 Mon Sep 17 00:00:00 2001
From: Marcus Lagergren
Date: Thu, 16 May 2013 13:44:25 +0200
Subject: [PATCH 014/101] 8013919: Original exception no longer thrown away
when a finally rethrows
Reviewed-by: jlaskey, sundar
---
.../jdk/nashorn/internal/codegen/Lower.java | 32 ++++++++-------
.../jdk/nashorn/internal/ir/FunctionNode.java | 38 ++++++++++++------
nashorn/test/script/basic/JDK-8013919.js | 39 +++++++++++++++++++
.../test/script/basic/JDK-8013919.js.EXPECTED | 2 +
4 files changed, 87 insertions(+), 24 deletions(-)
create mode 100644 nashorn/test/script/basic/JDK-8013919.js
create mode 100644 nashorn/test/script/basic/JDK-8013919.js.EXPECTED
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java
index a602ddf512c..a7089674d82 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java
@@ -261,19 +261,25 @@ final class Lower extends NodeOperatorVisitor {
return throwNode;
}
- private static Node ensureUniqueLabelsIn(final Node node) {
+ private static Node ensureUniqueNamesIn(final LexicalContext lc, final Node node) {
return node.accept(new NodeVisitor() {
- @Override
- public Node leaveDefault(final Node labelledNode) {
- return labelledNode.ensureUniqueLabels(getLexicalContext());
- }
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ final String name = functionNode.getName();
+ return functionNode.setName(getLexicalContext(), lc.getCurrentFunction().uniqueName(name));
+ }
+
+ @Override
+ public Node leaveDefault(final Node labelledNode) {
+ return labelledNode.ensureUniqueLabels(getLexicalContext());
+ }
});
}
- private static List copyFinally(final Block finallyBody) {
+ private static List copyFinally(final LexicalContext lc, final Block finallyBody) {
final List newStatements = new ArrayList<>();
for (final Statement statement : finallyBody.getStatements()) {
- newStatements.add((Statement)ensureUniqueLabelsIn(statement));
+ newStatements.add((Statement)ensureUniqueNamesIn(lc, statement));
if (statement.hasTerminalFlags()) {
return newStatements;
}
@@ -316,9 +322,9 @@ final class Lower extends NodeOperatorVisitor {
* @return new try node after splicing finally code (same if nop)
*/
private Node spliceFinally(final TryNode tryNode, final List rethrows, final Block finallyBody) {
- final int finish = tryNode.getFinish();
-
assert tryNode.getFinallyBody() == null;
+ final int finish = tryNode.getFinish();
+ final LexicalContext lc = getLexicalContext();
final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() {
final List insideTry = new ArrayList<>();
@@ -338,7 +344,7 @@ final class Lower extends NodeOperatorVisitor {
@Override
public Node leaveThrowNode(final ThrowNode throwNode) {
if (rethrows.contains(throwNode)) {
- final List newStatements = copyFinally(finallyBody);
+ final List newStatements = copyFinally(lc, finallyBody);
if (!isTerminal(newStatements)) {
newStatements.add(throwNode);
}
@@ -372,7 +378,7 @@ final class Lower extends NodeOperatorVisitor {
resultNode = null;
}
- newStatements.addAll(copyFinally(finallyBody));
+ newStatements.addAll(copyFinally(lc, finallyBody));
if (!isTerminal(newStatements)) {
newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
}
@@ -382,7 +388,7 @@ final class Lower extends NodeOperatorVisitor {
private Node copy(final Statement endpoint, final Node targetNode) {
if (!insideTry.contains(targetNode)) {
- final List newStatements = copyFinally(finallyBody);
+ final List newStatements = copyFinally(lc, finallyBody);
if (!isTerminal(newStatements)) {
newStatements.add(endpoint);
}
@@ -548,7 +554,7 @@ final class Lower extends NodeOperatorVisitor {
final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
return callNode.setEvalArgs(
new CallNode.EvalArgs(
- ensureUniqueLabelsIn(args.get(0)).accept(this),
+ ensureUniqueNamesIn(getLexicalContext(), args.get(0)).accept(this),
compilerConstant(THIS),
evalLocation(callee),
currentFunction.isStrict()));
diff --git a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
index 2b6d19bf501..715d4507ac3 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
@@ -250,6 +250,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags compilationState,
@@ -260,6 +261,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags newState = EnumSet.copyOf(this.compilationState);
newState.add(state);
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, newState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
}
/**
@@ -410,7 +411,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags
Date: Thu, 16 May 2013 19:52:39 +0200
Subject: [PATCH 015/101] 8012359: Increase code coverage in Joni
Reviewed-by: jlaskey, lagergren
---
nashorn/make/build.xml | 2 +
.../{DefaultRegExp.java => JdkRegExp.java} | 4 +-
.../internal/runtime/regexp/JoniRegExp.java | 2 +-
.../runtime/regexp/RegExpFactory.java | 6 +-
.../runtime/regexp/joni/Analyser.java | 837 +-----------------
.../runtime/regexp/joni/ArrayCompiler.java | 410 ++-------
.../runtime/regexp/joni/AsmCompiler.java | 109 ---
.../regexp/joni/AsmCompilerSupport.java | 267 ------
.../internal/runtime/regexp/joni/BitSet.java | 8 -
.../runtime/regexp/joni/BitStatus.java | 7 +-
.../runtime/regexp/joni/ByteCodeMachine.java | 263 ------
.../runtime/regexp/joni/ByteCodePrinter.java | 237 ++++-
.../runtime/regexp/joni/CaptureTreeNode.java | 74 --
.../runtime/regexp/joni/Compiler.java | 28 +-
.../internal/runtime/regexp/joni/Config.java | 17 +-
.../runtime/regexp/joni/EncodingHelper.java | 14 -
.../internal/runtime/regexp/joni/Lexer.java | 376 +-------
.../internal/runtime/regexp/joni/Matcher.java | 18 -
.../runtime/regexp/joni/NameEntry.java | 97 --
.../runtime/regexp/joni/NativeMachine.java | 27 -
.../internal/runtime/regexp/joni/Parser.java | 195 +---
.../internal/runtime/regexp/joni/Regex.java | 139 +--
.../internal/runtime/regexp/joni/Region.java | 19 -
.../runtime/regexp/joni/ScanEnvironment.java | 10 -
.../runtime/regexp/joni/ScannerSupport.java | 4 +-
.../runtime/regexp/joni/StackMachine.java | 104 ---
.../internal/runtime/regexp/joni/Syntax.java | 2 +-
.../runtime/regexp/joni/UnsetAddrList.java | 69 --
.../runtime/regexp/joni/ast/CClassNode.java | 40 +-
.../runtime/regexp/joni/ast/CTypeNode.java | 50 --
.../runtime/regexp/joni/ast/CallNode.java | 86 --
.../runtime/regexp/joni/ast/EncloseNode.java | 38 +-
.../regexp/joni/ast/QuantifierNode.java | 44 +-
.../runtime/regexp/joni/ast/StateNode.java | 65 --
.../regexp/joni/bench/AbstractBench.java | 49 -
.../joni/bench/BenchGreedyBacktrack.java | 7 -
.../regexp/joni/bench/BenchRailsRegs.java | 31 -
.../joni/bench/BenchSeveralRegexps.java | 17 -
.../runtime/regexp/joni/constants/OPCode.java | 235 -----
.../runtime/regexp/joni/constants/Reduce.java | 61 --
.../regexp/joni/encoding/AsciiTables.java | 157 ----
.../runtime/regexp/joni/encoding/ObjPtr.java | 1 -
.../regexp/joni/encoding/PosixBracket.java | 77 --
.../runtime/regexp/joni/encoding/Ptr.java | 35 -
.../regexp/joni/exception/ErrorMessages.java | 29 +-
.../regexp/joni/exception/ValueException.java | 4 -
.../runtime/regexp/JdkRegExpTest.java | 61 ++
.../runtime/regexp/joni/JoniTest.java | 52 ++
48 files changed, 531 insertions(+), 3953 deletions(-)
rename nashorn/src/jdk/nashorn/internal/runtime/regexp/{DefaultRegExp.java => JdkRegExp.java} (97%)
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompiler.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompilerSupport.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CaptureTreeNode.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NameEntry.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NativeMachine.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/UnsetAddrList.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CTypeNode.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CallNode.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/AbstractBench.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchGreedyBacktrack.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchRailsRegs.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/BenchSeveralRegexps.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/constants/Reduce.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/AsciiTables.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/PosixBracket.java
delete mode 100644 nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/Ptr.java
create mode 100644 nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
create mode 100644 nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml
index d884b2fe009..c647ba4b922 100644
--- a/nashorn/make/build.xml
+++ b/nashorn/make/build.xml
@@ -305,6 +305,8 @@
+
+
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
similarity index 97%
rename from nashorn/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java
rename to nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
index e3157ba5cb8..9250331deda 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/DefaultRegExp.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
@@ -41,7 +41,7 @@ import java.util.regex.PatternSyntaxException;
* Note that this class is not thread-safe as it stores the current match result
* and the string being matched in instance fields.
*/
-public class DefaultRegExp extends RegExp {
+public class JdkRegExp extends RegExp {
/** Java regexp pattern to use for match. We compile to one of these */
private Pattern pattern;
@@ -56,7 +56,7 @@ public class DefaultRegExp extends RegExp {
* @param flags RegExp flag string
* @throws ParserException if flags is invalid or source string has syntax error.
*/
- public DefaultRegExp(final String source, final String flags) throws ParserException {
+ public JdkRegExp(final String source, final String flags) throws ParserException {
super(source, flags);
int intFlags = 0;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
index 1047221af69..f797b051adc 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
@@ -113,7 +113,7 @@ public class JoniRegExp extends RegExp {
public static class Factory extends RegExpFactory {
@Override
- protected RegExp compile(final String pattern, final String flags) throws ParserException {
+ public RegExp compile(final String pattern, final String flags) throws ParserException {
return new JoniRegExp(pattern, flags);
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
index 4a7ac11bc99..08168b63779 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
@@ -29,7 +29,7 @@ import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.options.Options;
/**
- * Factory class for regular expressions. This class creates instances of {@link DefaultRegExp}.
+ * Factory class for regular expressions. This class creates instances of {@link JdkRegExp}.
* An alternative factory can be installed using the {@code nashorn.regexp.impl} system property.
*/
public class RegExpFactory {
@@ -62,8 +62,8 @@ public class RegExpFactory {
* @return new RegExp
* @throws ParserException if flags is invalid or pattern string has syntax error.
*/
- protected RegExp compile(final String pattern, final String flags) throws ParserException {
- return new DefaultRegExp(pattern, flags);
+ public RegExp compile(final String pattern, final String flags) throws ParserException {
+ return new JdkRegExp(pattern, flags);
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
index 49a2a925ec8..c0dbf0d8740 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
@@ -21,10 +21,7 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAll;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
-import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsClear;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAt;
-import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
-import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline;
@@ -36,8 +33,6 @@ import java.util.HashSet;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
@@ -49,9 +44,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.ObjPtr;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
final class Analyser extends Parser {
@@ -74,38 +67,9 @@ final class Analyser extends Parser {
//regex.repeatRangeAlloc = 0;
regex.repeatRangeLo = null;
regex.repeatRangeHi = null;
- regex.numCombExpCheck = 0;
-
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) regex.numCombExpCheck = 0;
parse();
- if (Config.USE_NAMED_GROUP) {
- /* mixed use named group and no-named group */
- if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(regex.options)) {
- if (env.numNamed != env.numMem) {
- root = disableNoNameGroupCapture(root);
- } else {
- numberedRefCheck(root);
- }
- }
- } // USE_NAMED_GROUP
-
- if (Config.USE_NAMED_GROUP) {
- if (env.numCall > 0) {
- env.unsetAddrList = new UnsetAddrList(env.numCall);
- setupSubExpCall(root);
- // r != 0 ???
- subexpRecursiveCheckTrav(root);
- // r < 0 -< err, FOUND_CALLED_NODE = 1
- subexpInfRecursiveCheckTrav(root);
- // r != 0 recursion infinite ???
- regex.numCall = env.numCall;
- } else {
- regex.numCall = 0;
- }
- } // USE_NAMED_GROUP
-
if (Config.DEBUG_PARSE_TREE_RAW && Config.DEBUG_PARSE_TREE) {
Config.log.println("");
Config.log.println(root + "\n");
@@ -129,27 +93,6 @@ final class Analyser extends Parser {
regex.btMemEnd |= regex.captureHistory;
}
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- if (env.backrefedMem == 0 || (Config.USE_SUBEXP_CALL && env.numCall == 0)) {
- setupCombExpCheck(root, 0);
-
- if (Config.USE_SUBEXP_CALL && env.hasRecursion) {
- env.numCombExpCheck = 0;
- } else { // USE_SUBEXP_CALL
- if (env.combExpMaxRegNum > 0) {
- for (int i=1; ic)/
- node = noNameDisableMap(node, map, counter);
- }
- } else {
- //en.target = noNameDisableMap(en.target, map, counter);
- en.setTarget(noNameDisableMap(en.target, map, counter)); // ???
- }
- return node;
- }
-
- private void noNameDisableMapFor_anchor(Node node, int[]map, Ptr counter) {
- AnchorNode an = (AnchorNode)node;
- switch (an.type) {
- case AnchorNode.PREC_READ:
- case AnchorNode.PREC_READ_NOT:
- case AnchorNode.LOOK_BEHIND:
- case AnchorNode.LOOK_BEHIND_NOT:
- an.setTarget(noNameDisableMap(an.target, map, counter));
- }
- }
-
- private Node noNameDisableMap(Node node, int[]map, Ptr counter) {
- switch (node.getType()) {
- case NodeType.LIST:
- case NodeType.ALT:
- noNameDisableMapFor_cosAlt(node, map, counter);
- break;
- case NodeType.QTFR:
- noNameDisableMapFor_quantifier(node, map, counter);
- break;
- case NodeType.ENCLOSE:
- node = noNameDisableMapFor_enclose(node, map, counter);
- break;
- case NodeType.ANCHOR:
- noNameDisableMapFor_anchor(node, map, counter);
- break;
- } // switch
- return node;
- }
-
- private void renumberByMap(Node node, int[]map) {
- switch (node.getType()) {
- case NodeType.LIST:
- case NodeType.ALT:
- ConsAltNode can = (ConsAltNode)node;
- do {
- renumberByMap(can.car, map);
- } while ((can = can.cdr) != null);
- break;
-
- case NodeType.QTFR:
- renumberByMap(((QuantifierNode)node).target, map);
- break;
-
- case NodeType.ENCLOSE:
- renumberByMap(((EncloseNode)node).target, map);
- break;
-
- case NodeType.BREF:
- ((BackRefNode)node).renumber(map);
- break;
- } // switch
- }
-
- protected final void numberedRefCheck(Node node) {
- switch (node.getType()) {
- case NodeType.LIST:
- case NodeType.ALT:
- ConsAltNode can = (ConsAltNode)node;
- do {
- numberedRefCheck(can.car);
- } while ((can = can.cdr) != null);
- break;
-
- case NodeType.QTFR:
- numberedRefCheck(((QuantifierNode)node).target);
- break;
-
- case NodeType.ENCLOSE:
- numberedRefCheck(((EncloseNode)node).target);
- break;
-
- case NodeType.BREF:
- BackRefNode br = (BackRefNode)node;
- if (!br.isNameRef()) newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
- break;
- } // switch
- }
-
- protected final Node disableNoNameGroupCapture(Node root) {
- int[]map = new int[env.numMem + 1];
-
- for (int i=1; i<=env.numMem; i++) map[i] = 0;
-
- root = noNameDisableMap(root, map, new Ptr(0));
- renumberByMap(root, map);
-
- for (int i=1, pos=1; i<=env.numMem; i++) {
- if (map[i] > 0) {
- env.memNodes[pos] = env.memNodes[i];
- pos++;
- }
- }
-
- int loc = env.captureHistory;
- env.captureHistory = bsClear();
-
- for (int i=1; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
- if (bsAt(loc, i)) {
- env.captureHistory = bsOnAtSimple(env.captureHistory, map[i]);
- }
- }
-
- env.numMem = env.numNamed;
- regex.numMem = env.numNamed;
-
- regex.renumberNameTable(map);
-
- return root;
- }
-
private void swap(Node a, Node b) {
a.swap(b);
@@ -352,17 +143,6 @@ final class Analyser extends Parser {
} while ((can = can.cdr) != null);
break;
- case NodeType.CALL:
- if (Config.USE_SUBEXP_CALL) {
- CallNode cn = (CallNode)node;
- if (cn.isRecursion()) {
- return TargetInfo.IS_EMPTY_REC; /* tiny version */
- } else {
- info = quantifiersMemoryInfo(cn.target);
- }
- } // USE_SUBEXP_CALL
- break;
-
case NodeType.QTFR:
QuantifierNode qn = (QuantifierNode)node;
if (qn.upper != 0) {
@@ -417,18 +197,6 @@ final class Analyser extends Parser {
}
break;
- case NodeType.CALL:
- if (Config.USE_SUBEXP_CALL) {
- CallNode cn = (CallNode)node;
- if (cn.isRecursion()) {
- EncloseNode en = (EncloseNode)cn.target;
- if (en.isMinFixed()) min = en.minLength;
- } else {
- min = getMinMatchLength(cn.target);
- }
- } // USE_SUBEXP_CALL
- break;
-
case NodeType.LIST:
ConsAltNode can = (ConsAltNode)node;
do {
@@ -474,15 +242,13 @@ final class Analyser extends Parser {
EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.MEMORY:
- if (Config.USE_SUBEXP_CALL) {
- if (en.isMinFixed()) {
- min = en.minLength;
- } else {
- min = getMinMatchLength(en.target);
- en.minLength = min;
- en.setMinFixed();
- }
- } // USE_SUBEXP_CALL
+ if (en.isMinFixed()) {
+ min = en.minLength;
+ } else {
+ min = getMinMatchLength(en.target);
+ en.minLength = min;
+ en.setMinFixed();
+ }
break;
case EncloseType.OPTION:
@@ -547,17 +313,6 @@ final class Analyser extends Parser {
}
break;
- case NodeType.CALL:
- if (Config.USE_SUBEXP_CALL) {
- CallNode cn = (CallNode)node;
- if (!cn.isRecursion()) {
- max = getMaxMatchLength(cn.target);
- } else {
- max = MinMaxLen.INFINITE_DISTANCE;
- }
- } // USE_SUBEXP_CALL
- break;
-
case NodeType.QTFR:
QuantifierNode qn = (QuantifierNode)node;
if (qn.upper != 0) {
@@ -576,15 +331,13 @@ final class Analyser extends Parser {
EncloseNode en = (EncloseNode)node;
switch (en.type) {
case EncloseType.MEMORY:
- if (Config.USE_SUBEXP_CALL) {
- if (en.isMaxFixed()) {
- max = en.maxLength;
- } else {
- max = getMaxMatchLength(en.target);
- en.maxLength = max;
- en.setMaxFixed();
- }
- } // USE_SUBEXP_CALL
+ if (en.isMaxFixed()) {
+ max = en.maxLength;
+ } else {
+ max = getMaxMatchLength(en.target);
+ en.maxLength = max;
+ en.setMaxFixed();
+ }
break;
case EncloseType.OPTION:
@@ -663,17 +416,6 @@ final class Analyser extends Parser {
}
break;
- case NodeType.CALL:
- if (Config.USE_SUBEXP_CALL) {
- CallNode cn = (CallNode)node;
- if (!cn.isRecursion()) {
- len = getCharLengthTree(cn.target, level);
- } else {
- returnCode = GET_CHAR_LEN_VARLEN;
- }
- } // USE_SUBEXP_CALL
- break;
-
case NodeType.CTYPE:
len = 1;
@@ -686,17 +428,15 @@ final class Analyser extends Parser {
EncloseNode en = (EncloseNode)node;
switch(en.type) {
case EncloseType.MEMORY:
- if (Config.USE_SUBEXP_CALL) {
- if (en.isCLenFixed()) {
- len = en.charLength;
- } else {
- len = getCharLengthTree(en.target, level);
- if (returnCode == 0) {
- en.charLength = len;
- en.setCLenFixed();
- }
+ if (en.isCLenFixed()) {
+ len = en.charLength;
+ } else {
+ len = getCharLengthTree(en.target, level);
+ if (returnCode == 0) {
+ en.charLength = len;
+ en.setCLenFixed();
}
- } // USE_SUBEXP_CALL
+ }
break;
case EncloseType.OPTION:
@@ -727,10 +467,6 @@ final class Analyser extends Parser {
switch(x.getType()) {
case NodeType.CTYPE:
switch(yType) {
- case NodeType.CTYPE:
- CTypeNode cny = (CTypeNode)y;
- CTypeNode cnx = (CTypeNode)x;
- return cny.ctype == cnx.ctype && cny.not != cnx.not;
case NodeType.CCLASS:
// !swap:!
@@ -756,37 +492,6 @@ final class Analyser extends Parser {
CClassNode xc = (CClassNode)x;
switch(yType) {
- case NodeType.CTYPE:
- switch(((CTypeNode)y).ctype) {
- case CharacterType.WORD:
- if (!((CTypeNode)y).not) {
- if (xc.mbuf == null && !xc.isNot()) {
- for (int i=0; i 0) newValueException(ERR_NEVER_ENDING_RECURSION);
- en.clearMark1();
- }
- r = subexpInfRecursiveCheckTrav(en.target);
- break;
-
- default:
- break;
- } // switch
-
- return r;
- }
-
- private int subexpRecursiveCheck(Node node) {
- int r = 0;
-
- switch (node.getType()) {
- case NodeType.LIST:
- case NodeType.ALT:
- ConsAltNode can = (ConsAltNode)node;
- do {
- r |= subexpRecursiveCheck(can.car);
- } while ((can = can.cdr) != null);
- break;
-
- case NodeType.QTFR:
- r = subexpRecursiveCheck(((QuantifierNode)node).target);
- break;
-
- case NodeType.ANCHOR:
- AnchorNode an = (AnchorNode)node;
- switch (an.type) {
- case AnchorType.PREC_READ:
- case AnchorType.PREC_READ_NOT:
- case AnchorType.LOOK_BEHIND:
- case AnchorType.LOOK_BEHIND_NOT:
- r = subexpRecursiveCheck(an.target);
- break;
- } // inner switch
- break;
-
- case NodeType.CALL:
- CallNode cn = (CallNode)node;
- r = subexpRecursiveCheck(cn.target);
- if (r != 0) cn.setRecursion();
- break;
-
- case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
- if (en.isMark2()) {
- return 0;
- } else if (en.isMark1()) {
- return 1; /* recursion */
- } else {
- en.setMark2();
- r = subexpRecursiveCheck(en.target);
- en.clearMark2();
- }
- break;
-
- default:
- break;
- } // switch
-
- return r;
- }
-
- private static final int FOUND_CALLED_NODE = 1;
- protected final int subexpRecursiveCheckTrav(Node node) {
- int r = 0;
-
- switch (node.getType()) {
- case NodeType.LIST:
- case NodeType.ALT:
- ConsAltNode can = (ConsAltNode)node;
- do {
- int ret = subexpRecursiveCheckTrav(can.car);
- if (ret == FOUND_CALLED_NODE) {
- r = FOUND_CALLED_NODE;
- }
- // else if (ret < 0) return ret; ???
- } while ((can = can.cdr) != null);
- break;
-
- case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
- r = subexpRecursiveCheckTrav(qn.target);
- if (qn.upper == 0) {
- if (r == FOUND_CALLED_NODE) qn.isRefered = true;
- }
- break;
-
- case NodeType.ANCHOR:
- AnchorNode an = (AnchorNode)node;
- switch (an.type) {
- case AnchorType.PREC_READ:
- case AnchorType.PREC_READ_NOT:
- case AnchorType.LOOK_BEHIND:
- case AnchorType.LOOK_BEHIND_NOT:
- r = subexpRecursiveCheckTrav(an.target);
- break;
- } // inner switch
- break;
-
- case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
- if (!en.isRecursion()) {
- if (en.isCalled()) {
- en.setMark1();
- r = subexpRecursiveCheck(en.target);
- if (r != 0) en.setRecursion();
- en.clearMark1();
- }
- }
- r = subexpRecursiveCheckTrav(en.target);
- if (en.isCalled()) r |= FOUND_CALLED_NODE;
- break;
-
- default:
- break;
- } // switch
-
- return r;
- }
-
- private void setCallAttr(CallNode cn) {
- cn.target = env.memNodes[cn.groupNum]; // no setTarget in call nodes!
- if (cn.target == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
-
- ((EncloseNode)cn.target).setCalled();
- env.btMemStart = BitStatus.bsOnAt(env.btMemStart, cn.groupNum);
- cn.unsetAddrList = env.unsetAddrList;
- }
-
- protected final void setupSubExpCall(Node node) {
-
- switch(node.getType()) {
- case NodeType.LIST:
- ConsAltNode ln = (ConsAltNode)node;
- do {
- setupSubExpCall(ln.car);
- } while ((ln = ln.cdr) != null);
- break;
-
- case NodeType.ALT:
- ConsAltNode can = (ConsAltNode)node;
- do {
- setupSubExpCall(can.car);
- } while ((can = can.cdr) != null);
- break;
-
- case NodeType.QTFR:
- setupSubExpCall(((QuantifierNode)node).target);
- break;
-
- case NodeType.ENCLOSE:
- setupSubExpCall(((EncloseNode)node).target);
- break;
-
- case NodeType.CALL:
- CallNode cn = (CallNode)node;
-
- if (cn.groupNum != 0) {
- int gNum = cn.groupNum;
-
- if (Config.USE_NAMED_GROUP) {
- if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(env.option)) {
- newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
- }
- } // USE_NAMED_GROUP
- if (gNum > env.numMem) newValueException(ERR_UNDEFINED_GROUP_REFERENCE, cn.nameP, cn.nameEnd);
- setCallAttr(cn);
- } else {
- if (Config.USE_NAMED_GROUP) {
- NameEntry ne = regex.nameToGroupNumbers(cn.name, cn.nameP, cn.nameEnd);
-
- if (ne == null) {
- newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
- } else if (ne.backNum > 1) {
- newValueException(ERR_MULTIPLEX_DEFINITION_NAME_CALL, cn.nameP, cn.nameEnd);
- } else {
- cn.groupNum = ne.backRef1; // ne.backNum == 1 ? ne.backRef1 : ne.backRefs[0]; // ??? need to check ?
- setCallAttr(cn);
- }
- }
- }
- break;
-
- case NodeType.ANCHOR:
- AnchorNode an = (AnchorNode)node;
- switch (an.type) {
- case AnchorType.PREC_READ:
- case AnchorType.PREC_READ_NOT:
- case AnchorType.LOOK_BEHIND:
- case AnchorType.LOOK_BEHIND_NOT:
- setupSubExpCall(an.target);
- break;
- }
- break;
-
- } // switch
- }
-
/* divide different length alternatives in look-behind.
(?<=A|B) ==> (?<=A)|(?<=B)
(? (?= 0 && (ln = ln.cdr) != null);
- break;
-
- case NodeType.ALT:
- ConsAltNode an = (ConsAltNode)node;
- do {
- ret = setupCombExpCheck(an.car, state);
- r |= ret;
- } while (ret >= 0 && (an = an.cdr) != null);
- break;
-
- case NodeType.QTFR:
- QuantifierNode qn = (QuantifierNode)node;
- int childState = state;
- int addState = 0;
- int varNum;
-
- if (!isRepeatInfinite(qn.upper)) {
- if (qn.upper > 1) {
- /* {0,1}, {1,1} are allowed */
- childState |= CEC_IN_FINITE_REPEAT;
-
- /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
- if (env.backrefedMem == 0) {
- if (qn.target.getType() == NodeType.ENCLOSE) {
- EncloseNode en = (EncloseNode)qn.target;
- if (en.type == EncloseType.MEMORY) {
- if (en.target.getType() == NodeType.QTFR) {
- QuantifierNode q = (QuantifierNode)en.target;
- if (isRepeatInfinite(q.upper) && q.greedy == qn.greedy) {
- qn.upper = qn.lower == 0 ? 1 : qn.lower;
- if (qn.upper == 1) childState = state;
- }
- }
- }
- }
- }
- }
- }
-
- if ((state & CEC_IN_FINITE_REPEAT) != 0) {
- qn.combExpCheckNum = -1;
- } else {
- if (isRepeatInfinite(qn.upper)) {
- varNum = CEC_INFINITE_NUM;
- childState |= CEC_IN_INFINITE_REPEAT;
- } else {
- varNum = qn.upper - qn.lower;
- }
-
- if (varNum >= CEC_THRES_NUM_BIG_REPEAT) addState |= CEC_CONT_BIG_REPEAT;
-
- if (((state & CEC_IN_INFINITE_REPEAT) != 0 && varNum != 0) ||
- ((state & CEC_CONT_BIG_REPEAT) != 0 && varNum >= CEC_THRES_NUM_BIG_REPEAT)) {
- if (qn.combExpCheckNum == 0) {
- env.numCombExpCheck++;
- qn.combExpCheckNum = env.numCombExpCheck;
- if (env.currMaxRegNum > env.combExpMaxRegNum) {
- env.combExpMaxRegNum = env.currMaxRegNum;
- }
- }
- }
- }
- r = setupCombExpCheck(qn.target, childState);
- r |= addState;
- break;
-
- case NodeType.ENCLOSE:
- EncloseNode en = (EncloseNode)node;
- switch( en.type) {
- case EncloseNode.MEMORY:
- if (env.currMaxRegNum < en.regNum) {
- env.currMaxRegNum = en.regNum;
- }
- r = setupCombExpCheck(en.target, state);
- break;
-
- default:
- r = setupCombExpCheck(en.target, state);
- } // inner switch
- break;
-
- case NodeType.CALL:
- if (Config.USE_SUBEXP_CALL) {
- CallNode cn = (CallNode)node;
- if (cn.isRecursion()) {
- env.hasRecursion = true;
- } else {
- r = setupCombExpCheck(cn.target, state);
- }
- } // USE_SUBEXP_CALL
- break;
-
- default:
- break;
-
- } // switch
-
- return r;
- }
-
private static final int IN_ALT = (1<<0);
private static final int IN_NOT = (1<<1);
private static final int IN_REPEAT = (1<<2);
@@ -1691,20 +953,12 @@ final class Analyser extends Parser {
case NodeType.CANY:
break;
- case NodeType.CALL: // if (Config.USE_SUBEXP_CALL) ?
- break;
-
case NodeType.BREF:
BackRefNode br = (BackRefNode)node;
for (int i=0; i env.numMem) newValueException(ERR_INVALID_BACKREF);
env.backrefedMem = bsOnAt(env.backrefedMem, br.back[i]);
env.btMemStart = bsOnAt(env.btMemStart, br.back[i]);
- if (Config.USE_BACKREF_WITH_LEVEL) {
- if (br.isNestLevel()) {
- env.btMemEnd = bsOnAt(env.btMemEnd, br.back[i]);
- }
- } // USE_BACKREF_AT_LEVEL
((EncloseNode)env.memNodes[br.back[i]]).setMemBackrefed();
}
break;
@@ -1916,37 +1170,6 @@ final class Analyser extends Parser {
break;
}
- case NodeType.CTYPE: {
- int min;
- int max = 1;
- if (max == 1) {
- min = 1;
- CTypeNode cn = (CTypeNode)node;
-
- switch (cn.ctype) {
- case CharacterType.WORD:
- if (cn.not) {
- for (int i=0; i MAX_NODE_OPT_INFO_REF_COUNT) {
+ if (++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
int min = 0;
int max = MinMaxLen.INFINITE_DISTANCE;
if (en.isMinFixed()) min = en.minLength;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
index b55991698b6..f348a205289 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
@@ -28,8 +28,6 @@ import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepe
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
@@ -71,11 +69,6 @@ final class ArrayCompiler extends Compiler {
regex.templates = templates;
regex.templateNum = templateNum;
regex.factory = MatcherFactory.DEFAULT;
-
- if (Config.USE_SUBEXP_CALL && analyser.env.unsetAddrList != null) {
- analyser.env.unsetAddrList.fix(regex);
- analyser.env.unsetAddrList = null;
- }
}
@Override
@@ -119,7 +112,7 @@ final class ArrayCompiler extends Compiler {
return isNeedStrLenOpExact(op);
}
- private int selectStrOpcode(int mbLength, int strLength, boolean ignoreCase) {
+ private int selectStrOpcode(int strLength, boolean ignoreCase) {
int op;
if (ignoreCase) {
@@ -128,31 +121,14 @@ final class ArrayCompiler extends Compiler {
default:op = OPCode.EXACTN_IC; break;
} // switch
} else {
- switch (mbLength) {
- case 1:
- switch (strLength) {
- case 1: op = OPCode.EXACT1; break;
- case 2: op = OPCode.EXACT2; break;
- case 3: op = OPCode.EXACT3; break;
- case 4: op = OPCode.EXACT4; break;
- case 5: op = OPCode.EXACT5; break;
- default:op = OPCode.EXACTN; break;
- } // inner switch
- break;
- case 2:
- switch (strLength) {
- case 1: op = OPCode.EXACTMB2N1; break;
- case 2: op = OPCode.EXACTMB2N2; break;
- case 3: op = OPCode.EXACTMB2N3; break;
- default:op = OPCode.EXACTMB2N; break;
- } // inner switch
- break;
- case 3:
- op = OPCode.EXACTMB3N;
- break;
- default:
- op = OPCode.EXACTMBN;
- } // switch
+ switch (strLength) {
+ case 1: op = OPCode.EXACT1; break;
+ case 2: op = OPCode.EXACT2; break;
+ case 3: op = OPCode.EXACT3; break;
+ case 4: op = OPCode.EXACT4; break;
+ case 5: op = OPCode.EXACT5; break;
+ default:op = OPCode.EXACTN; break;
+ } // inner switch
}
return op;
}
@@ -185,8 +161,8 @@ final class ArrayCompiler extends Compiler {
}
}
- private int addCompileStringlength(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
- int op = selectStrOpcode(mbLength, strLength, ignoreCase);
+ private int addCompileStringlength(char[] chars, int p, int strLength, boolean ignoreCase) {
+ int op = selectStrOpcode(strLength, ignoreCase);
int len = OPSize.OPCODE;
if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
@@ -194,25 +170,21 @@ final class ArrayCompiler extends Compiler {
len += OPSize.LENGTH + OPSize.INDEX + OPSize.INDEX;
} else {
if (isNeedStrLenOpExact(op)) len += OPSize.LENGTH;
- len += mbLength * strLength;
+ len += strLength;
}
if (op == OPCode.EXACTMBN) len += OPSize.LENGTH;
return len;
}
@Override
- protected final void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
- int op = selectStrOpcode(mbLength, strLength, ignoreCase);
+ protected final void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase) {
+ int op = selectStrOpcode(strLength, ignoreCase);
addOpcode(op);
- if (op == OPCode.EXACTMBN) addLength(mbLength);
+ if (op == OPCode.EXACTMBN) addLength(1);
if (isNeedStrLenOpExact(op)) {
- if (op == OPCode.EXACTN_IC || op == OPCode.EXACTN_IC_SB) {
- addLength(mbLength * strLength);
- } else {
- addLength(strLength);
- }
+ addLength(strLength);
}
if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
@@ -220,7 +192,7 @@ final class ArrayCompiler extends Compiler {
addInt(p);
addTemplate(chars);
} else {
- addChars(chars, p, mbLength * strLength);
+ addChars(chars, p, strLength);
}
}
@@ -242,14 +214,14 @@ final class ArrayCompiler extends Compiler {
slen++;
p++;
}
- int r = addCompileStringlength(chars, prev, 1, slen, ambig);
+ int r = addCompileStringlength(chars, prev, slen, ambig);
rlen += r;
return rlen;
}
private int compileLengthStringRawNode(StringNode sn) {
if (sn.length() <= 0) return 0;
- return addCompileStringlength(sn.chars, sn.p, 1 /*sb*/, sn.length(), false);
+ return addCompileStringlength(sn.chars, sn.p, sn.length(), false);
}
private void addMultiByteCClass(CodeRangeBuffer mbuf) {
@@ -311,26 +283,6 @@ final class ArrayCompiler extends Compiler {
}
}
- @Override
- protected void compileCTypeNode(CTypeNode node) {
- CTypeNode cn = node;
- int op;
- switch (cn.ctype) {
- case CharacterType.WORD:
- if (cn.not) {
- op = OPCode.NOT_WORD;
- } else {
- op = OPCode.WORD;
- }
- break;
-
- default:
- newInternalException(ERR_PARSER_BUG);
- return; // not reached
- } // inner switch
- addOpcode(op);
- }
-
@Override
protected void compileAnyCharNode() {
if (isMultiline(regex.options)) {
@@ -340,31 +292,16 @@ final class ArrayCompiler extends Compiler {
}
}
- @Override
- protected void compileCallNode(CallNode node) {
- addOpcode(OPCode.CALL);
- node.unsetAddrList.add(codeLength, node.target);
- addAbsAddr(0); /*dummy addr.*/
- }
-
@Override
protected void compileBackrefNode(BackRefNode node) {
BackRefNode br = node;
- if (Config.USE_BACKREF_WITH_LEVEL && br.isNestLevel()) {
- addOpcode(OPCode.BACKREF_WITH_LEVEL);
- addOption(regex.options & Option.IGNORECASE);
- addLength(br.nestLevel);
- // !goto add_bacref_mems;!
- addLength(br.backNum);
- for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
- return;
- } else { // USE_BACKREF_AT_LEVEL
- if (br.backNum == 1) {
- if (isIgnoreCase(regex.options)) {
- addOpcode(OPCode.BACKREFN_IC);
- addMemNum(br.back[0]);
- } else {
- switch (br.back[0]) {
+ // USE_BACKREF_AT_LEVEL
+ if (br.backNum == 1) {
+ if (isIgnoreCase(regex.options)) {
+ addOpcode(OPCode.BACKREFN_IC);
+ addMemNum(br.back[0]);
+ } else {
+ switch (br.back[0]) {
case 1:
addOpcode(OPCode.BACKREF1);
break;
@@ -375,18 +312,17 @@ final class ArrayCompiler extends Compiler {
addOpcode(OPCode.BACKREFN);
addOpcode(br.back[0]);
break;
- } // switch
- }
- } else {
- if (isIgnoreCase(regex.options)) {
- addOpcode(OPCode.BACKREF_MULTI_IC);
- } else {
- addOpcode(OPCode.BACKREF_MULTI);
- }
- // !add_bacref_mems:!
- addLength(br.backNum);
- for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
+ } // switch
}
+ } else {
+ if (isIgnoreCase(regex.options)) {
+ addOpcode(OPCode.BACKREF_MULTI_IC);
+ } else {
+ addOpcode(OPCode.BACKREF_MULTI);
+ }
+ // !add_bacref_mems:!
+ addLength(br.backNum);
+ for (int i=br.backNum-1; i>=0; i--) addMemNum(br.back[i]);
}
}
@@ -419,7 +355,7 @@ final class ArrayCompiler extends Compiler {
compileTreeEmptyCheck(qn.target, emptyInfo);
- if ((Config.USE_SUBEXP_CALL && regex.numCall > 0) || qn.isInRepeat()) {
+ if (qn.isInRepeat()) {
addOpcode(qn.greedy ? OPCode.REPEAT_INC_SG : OPCode.REPEAT_INC_NG_SG);
} else {
addOpcode(qn.greedy ? OPCode.REPEAT_INC : OPCode.REPEAT_INC_NG);
@@ -434,193 +370,6 @@ final class ArrayCompiler extends Compiler {
return ckn > 0;
}
- private int compileCECLengthQuantifierNode(QuantifierNode qn) {
- boolean infinite = isRepeatInfinite(qn.upper);
- int emptyInfo = qn.targetEmptyInfo;
-
- int tlen = compileLengthTree(qn.target);
- int ckn = regex.numCombExpCheck > 0 ? qn.combExpCheckNum : 0;
- int cklen = cknOn(ckn) ? OPSize.STATE_CHECK_NUM : 0;
-
- /* anychar repeat */
- if (qn.target.getType() == NodeType.CANY) {
- if (qn.greedy && infinite) {
- if (qn.nextHeadExact != null && !cknOn(ckn)) {
- return OPSize.ANYCHAR_STAR_PEEK_NEXT + tlen * qn.lower + cklen;
- } else {
- return OPSize.ANYCHAR_STAR + tlen * qn.lower + cklen;
- }
- }
- }
-
- int modTLen;
- if (emptyInfo != 0) {
- modTLen = tlen + (OPSize.NULL_CHECK_START + OPSize.NULL_CHECK_END);
- } else {
- modTLen = tlen;
- }
-
- int len;
- if (infinite && qn.lower <= 1) {
- if (qn.greedy) {
- if (qn.lower == 1) {
- len = OPSize.JUMP;
- } else {
- len = 0;
- }
- len += OPSize.PUSH + cklen + modTLen + OPSize.JUMP;
- } else {
- if (qn.lower == 0) {
- len = OPSize.JUMP;
- } else {
- len = 0;
- }
- len += modTLen + OPSize.PUSH + cklen;
- }
- } else if (qn.upper == 0) {
- if (qn.isRefered) { /* /(?..){0}/ */
- len = OPSize.JUMP + tlen;
- } else {
- len = 0;
- }
- } else if (qn.upper == 1 && qn.greedy) {
- if (qn.lower == 0) {
- if (cknOn(ckn)) {
- len = OPSize.STATE_CHECK_PUSH + tlen;
- } else {
- len = OPSize.PUSH + tlen;
- }
- } else {
- len = tlen;
- }
- } else if (!qn.greedy && qn.upper == 1 && qn.lower == 0) { /* '??' */
- len = OPSize.PUSH + cklen + OPSize.JUMP + tlen;
- } else {
- len = OPSize.REPEAT_INC + modTLen + OPSize.OPCODE + OPSize.RELADDR + OPSize.MEMNUM;
-
- if (cknOn(ckn)) {
- len += OPSize.STATE_CHECK;
- }
- }
- return len;
- }
-
- @Override
- protected void compileCECQuantifierNode(QuantifierNode qn) {
- boolean infinite = isRepeatInfinite(qn.upper);
- int emptyInfo = qn.targetEmptyInfo;
-
- int tlen = compileLengthTree(qn.target);
-
- int ckn = regex.numCombExpCheck > 0 ? qn.combExpCheckNum : 0;
-
- if (qn.isAnyCharStar()) {
- compileTreeNTimes(qn.target, qn.lower);
- if (qn.nextHeadExact != null && !cknOn(ckn)) {
- if (isMultiline(regex.options)) {
- addOpcode(OPCode.ANYCHAR_ML_STAR_PEEK_NEXT);
- } else {
- addOpcode(OPCode.ANYCHAR_STAR_PEEK_NEXT);
- }
- if (cknOn(ckn)) {
- addStateCheckNum(ckn);
- }
- StringNode sn = (StringNode)qn.nextHeadExact;
- addChars(sn.chars, sn.p, 1);
- return;
- } else {
- if (isMultiline(regex.options)) {
- if (cknOn(ckn)) {
- addOpcode(OPCode.STATE_CHECK_ANYCHAR_ML_STAR);
- } else {
- addOpcode(OPCode.ANYCHAR_ML_STAR);
- }
- } else {
- if (cknOn(ckn)) {
- addOpcode(OPCode.STATE_CHECK_ANYCHAR_STAR);
- } else {
- addOpcode(OPCode.ANYCHAR_STAR);
- }
- }
- if (cknOn(ckn)) {
- addStateCheckNum(ckn);
- }
- return;
- }
- }
-
- int modTLen;
- if (emptyInfo != 0) {
- modTLen = tlen + (OPSize.NULL_CHECK_START + OPSize.NULL_CHECK_END);
- } else {
- modTLen = tlen;
- }
- if (infinite && qn.lower <= 1) {
- if (qn.greedy) {
- if (qn.lower == 1) {
- addOpcodeRelAddr(OPCode.JUMP, cknOn(ckn) ? OPSize.STATE_CHECK_PUSH :
- OPSize.PUSH);
- }
- if (cknOn(ckn)) {
- addOpcode(OPCode.STATE_CHECK_PUSH);
- addStateCheckNum(ckn);
- addRelAddr(modTLen + OPSize.JUMP);
- } else {
- addOpcodeRelAddr(OPCode.PUSH, modTLen + OPSize.JUMP);
- }
- compileTreeEmptyCheck(qn.target, emptyInfo);
- addOpcodeRelAddr(OPCode.JUMP, -(modTLen + OPSize.JUMP + (cknOn(ckn) ?
- OPSize.STATE_CHECK_PUSH :
- OPSize.PUSH)));
- } else {
- if (qn.lower == 0) {
- addOpcodeRelAddr(OPCode.JUMP, modTLen);
- }
- compileTreeEmptyCheck(qn.target, emptyInfo);
- if (cknOn(ckn)) {
- addOpcode(OPCode.STATE_CHECK_PUSH_OR_JUMP);
- addStateCheckNum(ckn);
- addRelAddr(-(modTLen + OPSize.STATE_CHECK_PUSH_OR_JUMP));
- } else {
- addOpcodeRelAddr(OPCode.PUSH, -(modTLen + OPSize.PUSH));
- }
- }
- } else if (qn.upper == 0) {
- if (qn.isRefered) { /* /(?..){0}/ */
- addOpcodeRelAddr(OPCode.JUMP, tlen);
- compileTree(qn.target);
- } // else r=0 ???
- } else if (qn.upper == 1 && qn.greedy) {
- if (qn.lower == 0) {
- if (cknOn(ckn)) {
- addOpcode(OPCode.STATE_CHECK_PUSH);
- addStateCheckNum(ckn);
- addRelAddr(tlen);
- } else {
- addOpcodeRelAddr(OPCode.PUSH, tlen);
- }
- }
- compileTree(qn.target);
- } else if (!qn.greedy && qn.upper == 1 && qn.lower == 0){ /* '??' */
- if (cknOn(ckn)) {
- addOpcode(OPCode.STATE_CHECK_PUSH);
- addStateCheckNum(ckn);
- addRelAddr(OPSize.JUMP);
- } else {
- addOpcodeRelAddr(OPCode.PUSH, OPSize.JUMP);
- }
-
- addOpcodeRelAddr(OPCode.JUMP, tlen);
- compileTree(qn.target);
- } else {
- compileRangeRepeatNode(qn, modTLen, emptyInfo);
- if (cknOn(ckn)) {
- addOpcode(OPCode.STATE_CHECK);
- addStateCheckNum(ckn);
- }
- }
- }
-
private int compileNonCECLengthQuantifierNode(QuantifierNode qn) {
boolean infinite = isRepeatInfinite(qn.upper);
int emptyInfo = qn.targetEmptyInfo;
@@ -821,21 +570,12 @@ final class ArrayCompiler extends Compiler {
int len;
switch (node.type) {
case EncloseType.MEMORY:
- if (Config.USE_SUBEXP_CALL && node.isCalled()) {
- len = OPSize.MEMORY_START_PUSH + tlen + OPSize.CALL + OPSize.JUMP + OPSize.RETURN;
- if (bsAt(regex.btMemEnd, node.regNum)) {
- len += node.isRecursion() ? OPSize.MEMORY_END_PUSH_REC : OPSize.MEMORY_END_PUSH;
- } else {
- len += node.isRecursion() ? OPSize.MEMORY_END_REC : OPSize.MEMORY_END;
- }
- } else { // USE_SUBEXP_CALL
- if (bsAt(regex.btMemStart, node.regNum)) {
- len = OPSize.MEMORY_START_PUSH;
- } else {
- len = OPSize.MEMORY_START;
- }
- len += tlen + (bsAt(regex.btMemEnd, node.regNum) ? OPSize.MEMORY_END_PUSH : OPSize.MEMORY_END);
+ if (bsAt(regex.btMemStart, node.regNum)) {
+ len = OPSize.MEMORY_START_PUSH;
+ } else {
+ len = OPSize.MEMORY_START;
}
+ len += tlen + (bsAt(regex.btMemEnd, node.regNum) ? OPSize.MEMORY_END_PUSH : OPSize.MEMORY_END);
break;
case EncloseType.STOP_BACKTRACK:
@@ -860,23 +600,6 @@ final class ArrayCompiler extends Compiler {
int len;
switch (node.type) {
case EncloseType.MEMORY:
- if (Config.USE_SUBEXP_CALL) {
- if (node.isCalled()) {
- addOpcode(OPCode.CALL);
- node.callAddr = codeLength + OPSize.ABSADDR + OPSize.JUMP;
- node.setAddrFixed();
- addAbsAddr(node.callAddr);
- len = compileLengthTree(node.target);
- len += OPSize.MEMORY_START_PUSH + OPSize.RETURN;
- if (bsAt(regex.btMemEnd, node.regNum)) {
- len += node.isRecursion() ? OPSize.MEMORY_END_PUSH_REC : OPSize.MEMORY_END_PUSH;
- } else {
- len += node.isRecursion() ? OPSize.MEMORY_END_REC : OPSize.MEMORY_END;
- }
- addOpcodeRelAddr(OPCode.JUMP, len);
- }
- } // USE_SUBEXP_CALL
-
if (bsAt(regex.btMemStart, node.regNum)) {
addOpcode(OPCode.MEMORY_START_PUSH);
} else {
@@ -886,22 +609,12 @@ final class ArrayCompiler extends Compiler {
addMemNum(node.regNum);
compileTree(node.target);
- if (Config.USE_SUBEXP_CALL && node.isCalled()) {
- if (bsAt(regex.btMemEnd, node.regNum)) {
- addOpcode(node.isRecursion() ? OPCode.MEMORY_END_PUSH_REC : OPCode.MEMORY_END_PUSH);
- } else {
- addOpcode(node.isRecursion() ? OPCode.MEMORY_END_REC : OPCode.MEMORY_END);
- }
- addMemNum(node.regNum);
- addOpcode(OPCode.RETURN);
- } else { // USE_SUBEXP_CALL
- if (bsAt(regex.btMemEnd, node.regNum)) {
- addOpcode(OPCode.MEMORY_END_PUSH);
- } else {
- addOpcode(OPCode.MEMORY_END);
- }
- addMemNum(node.regNum);
+ if (bsAt(regex.btMemEnd, node.regNum)) {
+ addOpcode(OPCode.MEMORY_END_PUSH);
+ } else {
+ addOpcode(OPCode.MEMORY_END);
}
+ addMemNum(node.regNum);
break;
case EncloseType.STOP_BACKTRACK:
@@ -1078,32 +791,17 @@ final class ArrayCompiler extends Compiler {
case NodeType.BREF:
BackRefNode br = (BackRefNode)node;
- if (Config.USE_BACKREF_WITH_LEVEL && br.isNestLevel()) {
- len = OPSize.OPCODE + OPSize.OPTION + OPSize.LENGTH +
- OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
- } else { // USE_BACKREF_AT_LEVEL
- if (br.backNum == 1) {
- len = ((!isIgnoreCase(regex.options) && br.back[0] <= 2)
- ? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
- } else {
- len = OPSize.OPCODE + OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
- }
+ // USE_BACKREF_AT_LEVEL
+ if (br.backNum == 1) {
+ len = ((!isIgnoreCase(regex.options) && br.back[0] <= 2)
+ ? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
+ } else {
+ len = OPSize.OPCODE + OPSize.LENGTH + (OPSize.MEMNUM * br.backNum);
}
break;
- case NodeType.CALL:
- if (Config.USE_SUBEXP_CALL) {
- len = OPSize.CALL;
- break;
- } // USE_SUBEXP_CALL
- break;
-
case NodeType.QTFR:
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- len = compileCECLengthQuantifierNode((QuantifierNode)node);
- } else {
- len = compileNonCECLengthQuantifierNode((QuantifierNode)node);
- }
+ len = compileNonCECLengthQuantifierNode((QuantifierNode)node);
break;
case NodeType.ENCLOSE:
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompiler.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompiler.java
deleted file mode 100644
index 475d6595bcd..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompiler.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
-
-final class AsmCompiler extends AsmCompilerSupport {
-
- public AsmCompiler(Analyser analyser) {
- super(analyser);
- }
-
- @Override
- protected void prepare() {
- REG_NUM++;
- prepareMachine();
- prepareMachineInit();
- prepareMachineMatch();
-
- prepareFactory();
- prepareFactoryInit();
- }
-
- @Override
- protected void finish() {
- setupFactoryInit();
-
- setupMachineInit();
- setupMachineMatch();
-
- setupClasses();
- }
-
- @Override
- protected void compileAltNode(ConsAltNode node) {
- }
-
- @Override
- protected void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
- String template = installTemplate(chars, p, strLength);
- }
-
- @Override
- protected void compileCClassNode(CClassNode node) {
- if (node.bs != null) {
- String bitsetName = installBitSet(node.bs.bits);
- }
- }
-
- @Override
- protected void compileCTypeNode(CTypeNode node) {
- }
-
- @Override
- protected void compileAnyCharNode() {
- }
-
- @Override
- protected void compileBackrefNode(BackRefNode node) {
- }
-
- @Override
- protected void compileCallNode(CallNode node) {
- }
-
- @Override
- protected void compileCECQuantifierNode(QuantifierNode node) {
- }
-
- @Override
- protected void compileNonCECQuantifierNode(QuantifierNode node) {
- }
-
- @Override
- protected void compileOptionNode(EncloseNode node) {
- }
-
- @Override
- protected void compileEncloseNode(EncloseNode node) {
- }
-
- @Override
- protected void compileAnchorNode(AnchorNode node) {
- }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompilerSupport.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompilerSupport.java
deleted file mode 100644
index 06ca21a9b06..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompilerSupport.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import jdk.nashorn.internal.runtime.regexp.joni.constants.AsmConstants;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-
-abstract class AsmCompilerSupport extends Compiler implements Opcodes, AsmConstants {
- protected ClassWriter factory; // matcher allocator, also bit set, code rage and string template container
- protected MethodVisitor factoryInit;// factory constructor
- protected String factoryName;
-
- protected ClassWriter machine; // matcher
- protected MethodVisitor machineInit;// matcher constructor
- protected MethodVisitor match; // actual matcher implementation (the matchAt method)
- protected String machineName;
-
- // we will? try to manage visitMaxs ourselves for efficiency
- protected int maxStack = 1;
- protected int maxVars = LAST_INDEX;
-
- // for field generation
- protected int bitsets, ranges, templates;
-
- // simple class name postfix scheme for now
- static int REG_NUM = 0;
-
- // dummy class loader for now
- private static final class DummyClassLoader extends ClassLoader {
- public Class> defineClass(String name, byte[] bytes) {
- return super.defineClass(name, bytes, 0, bytes.length);
- }
- };
-
- private static final DummyClassLoader loader = new DummyClassLoader();
-
- AsmCompilerSupport(Analyser analyser) {
- super(analyser);
- }
-
- protected final void prepareFactory() {
- factory = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- factoryName = "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory" + REG_NUM;
-
- factory.visit(V1_4, ACC_PUBLIC + ACC_FINAL, factoryName, null, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", null);
-
- MethodVisitor create = factory.visitMethod(ACC_SYNTHETIC, "create", "(Lorg/joni/Regex;[BII)Lorg/joni/Matcher;", null, null);
- create.visitTypeInsn(NEW, machineName);
- create.visitInsn(DUP); // instance
- create.visitVarInsn(ALOAD, 1); // Regex
- create.visitVarInsn(ALOAD, 2); // bytes[]
- create.visitVarInsn(ILOAD, 3); // p
- create.visitVarInsn(ILOAD, 4); // end
- create.visitMethodInsn(INVOKESPECIAL, machineName, "", "(Lorg/joni/Regex;[BII)V");
- create.visitInsn(ARETURN);
- create.visitMaxs(0, 0);
- //create.visitMaxs(6, 5);
- create.visitEnd();
- }
-
- protected final void prepareFactoryInit() {
- factoryInit = factory.visitMethod(ACC_PUBLIC, "", "()V", null, null);
- factoryInit.visitVarInsn(ALOAD, 0);
- factoryInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", "", "()V");
- }
-
- protected final void setupFactoryInit() {
- factoryInit.visitInsn(RETURN);
- factoryInit.visitMaxs(0, 0);
- //init.visitMaxs(1, 1);
- factoryInit.visitEnd();
- }
-
- protected final void prepareMachine() {
- machine = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- machineName = "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine" + REG_NUM;
- }
-
- protected final void prepareMachineInit() {
- machine.visit(V1_4, ACC_PUBLIC + ACC_FINAL, machineName, null, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", null);
- machineInit = machine.visitMethod(ACC_PROTECTED, "", "(Lorg/joni/Regex;[BII)V", null, null);
- machineInit.visitVarInsn(ALOAD, THIS); // this
- machineInit.visitVarInsn(ALOAD, 1); // Regex
- machineInit.visitVarInsn(ALOAD, 2); // bytes[]
- machineInit.visitVarInsn(ILOAD, 3); // p
- machineInit.visitVarInsn(ILOAD, 4); // end
- machineInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", "", "(Lorg/joni/Regex;[BII)V");
- }
-
- protected final void setupMachineInit() {
- if (bitsets + ranges + templates > 0) { // ok, some of these are in use, we'd like to cache the factory
- machine.visitField(ACC_PRIVATE + ACC_FINAL, "factory", "L" + factoryName + ";", null, null);
- machineInit.visitVarInsn(ALOAD, THIS); // this
- machineInit.visitVarInsn(ALOAD, 1); // this, Regex
- machineInit.visitFieldInsn(GETFIELD, "jdk/nashorn/internal/runtime/regexp/joni/Regex", "factory", "Lorg/joni/MatcherFactory;"); // this, factory
- machineInit.visitTypeInsn(CHECKCAST, factoryName);
- machineInit.visitFieldInsn(PUTFIELD, machineName, "factory", "L" + factoryName + ";"); // []
- }
-
- machineInit.visitInsn(RETURN);
- machineInit.visitMaxs(0, 0);
- //init.visitMaxs(5, 5);
- machineInit.visitEnd();
- }
-
- protected final void prepareMachineMatch() {
- match = machine.visitMethod(ACC_SYNTHETIC, "matchAt", "(III)I", null, null);
- move(S, SSTART); // s = sstart
- load("bytes", "[B"); //
- astore(BYTES); // byte[]bytes = this.bytes
- }
-
- protected final void setupMachineMatch() {
- match.visitInsn(ICONST_M1);
- match.visitInsn(IRETURN);
-
- match.visitMaxs(maxStack, maxVars);
- match.visitEnd();
- }
-
- protected final void setupClasses() {
- byte[]factoryCode = factory.toByteArray();
- byte[]machineCode = machine.toByteArray();
-
- if (Config.DEBUG_ASM) {
- try {
- FileOutputStream fos;
- fos = new FileOutputStream(factoryName.substring(factoryName.lastIndexOf('/') + 1) + ".class");
- fos.write(factoryCode);
- fos.close();
- fos = new FileOutputStream(machineName.substring(machineName.lastIndexOf('/') + 1) + ".class");
- fos.write(machineCode);
- fos.close();
- } catch (IOException ioe) {
- ioe.printStackTrace(Config.err);
- }
- }
-
- loader.defineClass(machineName.replace('/', '.'), machineCode);
- Class> cls = loader.defineClass(factoryName.replace('/', '.'), factoryCode);
- try {
- regex.factory = (MatcherFactory)cls.newInstance();
- } catch(Exception e) {
- e.printStackTrace(Config.err);
- }
- }
-
- protected final void aload(int var) {
- match.visitVarInsn(ALOAD, var);
- }
-
- protected final void astore(int var) {
- match.visitVarInsn(ASTORE, var);
- }
-
- protected final void loadThis() {
- match.visitVarInsn(ALOAD, THIS);
- }
-
- protected final void load(int var) {
- match.visitVarInsn(ILOAD, var);
- }
-
- protected final void store(int var) {
- match.visitVarInsn(ISTORE, var);
- }
-
- protected final void move(int to, int from) {
- load(from);
- store(to);
- }
-
- protected final void load(String field, String singature) {
- loadThis();
- match.visitFieldInsn(GETFIELD, machineName, field, singature);
- }
-
- protected final void load(String field) {
- load(field, "I");
- }
-
- protected final void store(String field, String singature) {
- loadThis();
- match.visitFieldInsn(PUTFIELD, machineName, field, singature);
- }
-
- protected final void store(String field) {
- store(field, "I");
- }
-
- protected final String installTemplate(char[] arr, int p, int length) {
- String templateName = TEMPLATE + ++templates;
- installArray(templateName, arr, p, length);
- return templateName;
- }
-
- protected final String installCodeRange(int[]arr) {
- String coreRangeName = CODERANGE + ++ranges;
- installArray(coreRangeName, arr);
- return coreRangeName;
- }
-
- protected final String installBitSet(int[]arr) {
- String bitsetName = BITSET + ++bitsets;
- installArray(bitsetName, arr);
- return bitsetName;
- }
-
- private void installArray(String name, int[]arr) {
- factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[I", null, null);
- factoryInit.visitVarInsn(ALOAD, THIS); // this;
- loadInt(factoryInit, arr.length); // this, length
- factoryInit.visitIntInsn(NEWARRAY, T_INT); // this, arr
- for (int i=0;i < arr.length; i++) buildArray(i, arr[i], IASTORE);
- factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[I");
- }
-
- private void installArray(String name, char[]arr, int p, int length) {
- factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[B", null, null);
- factoryInit.visitVarInsn(ALOAD, THIS); // this;
- loadInt(factoryInit, arr.length); // this, length
- factoryInit.visitIntInsn(NEWARRAY, T_BYTE); // this, arr
- for (int i=p, j=0; i < p + length; i++, j++) buildArray(j, arr[i] & 0xff, BASTORE);
- factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[B");
- }
-
- private void buildArray(int index, int value, int type) {
- factoryInit.visitInsn(DUP); // ... arr, arr
- loadInt(factoryInit, index); // ... arr, arr, index
- loadInt(factoryInit, value); // ... arr, arr, index, value
- factoryInit.visitInsn(type); // ... arr
- }
-
- private void loadInt(MethodVisitor mv, int value) {
- if (value >= -1 && value <= 5) {
- mv.visitInsn(value + ICONST_0); // ICONST_0 == 3
- } else if (value >= 6 && value <= 127 || value >= -128 && value <= -2) {
- mv.visitIntInsn(BIPUSH, value);
- } else if (value >= 128 && value <= 32767 || value >= -32768 && value <= -129) {
- mv.visitIntInsn(SIPUSH, value);
- } else {
- mv.visitLdcInsn(new Integer(value));
- }
- }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
index bf715987428..5f98fe6411b 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
@@ -51,10 +51,6 @@ public final class BitSet {
bits[pos >>> ROOM_SHIFT] &= ~bit(pos);
}
- public void invert(int pos) {
- bits[pos >>> ROOM_SHIFT] ^= bit(pos);
- }
-
public void clear() {
for (int i=0; i range) {opFail(); return;}
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- sprev = sbegin; // break;
- }
-
- private void opExactMB2N2() {
- if (s + 4 > range) {opFail(); return;}
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- sprev = s;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- }
-
- private void opExactMB2N3() {
- if (s + 6 > range) {opFail(); return;}
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- sprev = s;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- }
-
- private void opExactMB2N() {
- int tlen = code[ip++];
- if (s + tlen * 2 > range) {opFail(); return;}
-
- if (Config.USE_STRING_TEMPLATES) {
- char[] bs = regex.templates[code[ip++]];
- int ps = code[ip++];
-
- while(tlen-- > 0) {
- if (bs[ps] != chars[s]) {opFail(); return;}
- ps++; s++;
- if (bs[ps] != chars[s]) {opFail(); return;}
- ps++; s++;
- }
- } else {
- while(tlen-- > 0) {
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- }
- }
- sprev = s - 2;
- }
-
- private void opExactMB3N() {
- int tlen = code[ip++];
- if (s + tlen * 3 > range) {opFail(); return;}
-
- if (Config.USE_STRING_TEMPLATES) {
- char[] bs = regex.templates[code[ip++]];
- int ps = code[ip++];
-
- while (tlen-- > 0) {
- if (bs[ps] != chars[s]) {opFail(); return;}
- ps++; s++;
- if (bs[ps] != chars[s]) {opFail(); return;}
- ps++; s++;
- if (bs[ps] != chars[s]) {opFail(); return;}
- ps++; s++;
- }
- } else {
- while (tlen-- > 0) {
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- }
- }
-
- sprev = s - 3;
- }
-
- private void opExactMBN() {
- int tlen = code[ip++]; /* mb-len */
- int tlen2= code[ip++]; /* string len */
-
- tlen2 *= tlen;
- if (s + tlen2 > range) {opFail(); return;}
-
- if (Config.USE_STRING_TEMPLATES) {
- char[] bs = regex.templates[code[ip++]];
- int ps = code[ip++];
-
- while (tlen2-- > 0) {
- if (bs[ps] != chars[s]) {opFail(); return;}
- ps++; s++;
- }
- } else {
- while (tlen2-- > 0) {
- if (code[ip] != chars[s]) {opFail(); return;}
- ip++; s++;
- }
- }
-
- sprev = s - tlen;
- }
-
private void opExact1IC() {
if (s >= range || code[ip] != Character.toLowerCase(chars[s++])) {opFail(); return;}
ip++;
@@ -748,34 +558,6 @@ class ByteCodeMachine extends StackMachine {
sprev = sbegin; // break;
}
- // CEC
- private void opStateCheckAnyCharStar() {
- int mem = code[ip++];
- final char[] chars = this.chars;
-
- while (s < range) {
- if (stateCheckVal(s, mem)) {opFail(); return;}
- pushAltWithStateCheck(ip, s, sprev, mem);
- if (chars[s] == EncodingHelper.NEW_LINE) {opFail(); return;}
- sprev = s;
- s++;
- }
- sprev = sbegin; // break;
- }
-
- // CEC
- private void opStateCheckAnyCharMLStar() {
- int mem = code[ip++];
-
- while (s < range) {
- if (stateCheckVal(s, mem)) {opFail(); return;}
- pushAltWithStateCheck(ip, s, sprev, mem);
- sprev = s;
- s++;
- }
- sprev = sbegin; // break;
- }
-
private void opWord() {
if (s >= range || !EncodingHelper.isWord(chars[s])) {opFail(); return;}
s++;
@@ -1223,33 +1005,6 @@ class ByteCodeMachine extends StackMachine {
pushAlt(ip + addr, s, sprev);
}
- // CEC
- private void opStateCheckPush() {
- int mem = code[ip++];
- if (stateCheckVal(s, mem)) {opFail(); return;}
- int addr = code[ip++];
- pushAltWithStateCheck(ip + addr, s, sprev, mem);
- }
-
- // CEC
- private void opStateCheckPushOrJump() {
- int mem = code[ip++];
- int addr= code[ip++];
-
- if (stateCheckVal(s, mem)) {
- ip += addr;
- } else {
- pushAltWithStateCheck(ip + addr, s, sprev, mem);
- }
- }
-
- // CEC
- private void opStateCheck() {
- int mem = code[ip++];
- if (stateCheckVal(s, mem)) {opFail(); return;}
- pushStateCheck(s, mem);
- }
-
private void opPop() {
popOne();
}
@@ -1425,17 +1180,6 @@ class ByteCodeMachine extends StackMachine {
opFail();
}
- private void opCall() {
- int addr = code[ip++];
- pushCallFrame(ip);
- ip = addr; // absolute address
- }
-
- private void opReturn() {
- ip = sreturn();
- pushReturn();
- }
-
private void opFail() {
if (stack == null) {
ip = regex.codeLength - 1;
@@ -1447,13 +1191,6 @@ class ByteCodeMachine extends StackMachine {
ip = e.getStatePCode();
s = e.getStatePStr();
sprev = e.getStatePStrPrev();
-
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- if (e.getStateCheck() != 0) {
- e.type = STATE_CHECK_MARK;
- stk++;
- }
- }
}
private int finish() {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
index 86a558b0e0c..d56164d116f 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
@@ -34,6 +34,239 @@ class ByteCodePrinter {
int operantCount;
WarnCallback warnings;
+ private final static String OpCodeNames[] = new String[] {
+ "finish", /*OP_FINISH*/
+ "end", /*OP_END*/
+ "exact1", /*OP_EXACT1*/
+ "exact2", /*OP_EXACT2*/
+ "exact3", /*OP_EXACT3*/
+ "exact4", /*OP_EXACT4*/
+ "exact5", /*OP_EXACT5*/
+ "exactn", /*OP_EXACTN*/
+ "exactmb2-n1", /*OP_EXACTMB2N1*/
+ "exactmb2-n2", /*OP_EXACTMB2N2*/
+ "exactmb2-n3", /*OP_EXACTMB2N3*/
+ "exactmb2-n", /*OP_EXACTMB2N*/
+ "exactmb3n", /*OP_EXACTMB3N*/
+ "exactmbn", /*OP_EXACTMBN*/
+ "exact1-ic", /*OP_EXACT1_IC*/
+ "exactn-ic", /*OP_EXACTN_IC*/
+ "cclass", /*OP_CCLASS*/
+ "cclass-mb", /*OP_CCLASS_MB*/
+ "cclass-mix", /*OP_CCLASS_MIX*/
+ "cclass-not", /*OP_CCLASS_NOT*/
+ "cclass-mb-not", /*OP_CCLASS_MB_NOT*/
+ "cclass-mix-not", /*OP_CCLASS_MIX_NOT*/
+ "cclass-node", /*OP_CCLASS_NODE*/
+ "anychar", /*OP_ANYCHAR*/
+ "anychar-ml", /*OP_ANYCHAR_ML*/
+ "anychar*", /*OP_ANYCHAR_STAR*/
+ "anychar-ml*", /*OP_ANYCHAR_ML_STAR*/
+ "anychar*-peek-next", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+ "anychar-ml*-peek-next", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+ "word", /*OP_WORD*/
+ "not-word", /*OP_NOT_WORD*/
+ "word-bound", /*OP_WORD_BOUND*/
+ "not-word-bound", /*OP_NOT_WORD_BOUND*/
+ "word-begin", /*OP_WORD_BEGIN*/
+ "word-end", /*OP_WORD_END*/
+ "begin-buf", /*OP_BEGIN_BUF*/
+ "end-buf", /*OP_END_BUF*/
+ "begin-line", /*OP_BEGIN_LINE*/
+ "end-line", /*OP_END_LINE*/
+ "semi-end-buf", /*OP_SEMI_END_BUF*/
+ "begin-position", /*OP_BEGIN_POSITION*/
+ "backref1", /*OP_BACKREF1*/
+ "backref2", /*OP_BACKREF2*/
+ "backrefn", /*OP_BACKREFN*/
+ "backrefn-ic", /*OP_BACKREFN_IC*/
+ "backref_multi", /*OP_BACKREF_MULTI*/
+ "backref_multi-ic", /*OP_BACKREF_MULTI_IC*/
+ "backref_at_level", /*OP_BACKREF_AT_LEVEL*/
+ "mem-start", /*OP_MEMORY_START*/
+ "mem-start-push", /*OP_MEMORY_START_PUSH*/
+ "mem-end-push", /*OP_MEMORY_END_PUSH*/
+ "mem-end-push-rec", /*OP_MEMORY_END_PUSH_REC*/
+ "mem-end", /*OP_MEMORY_END*/
+ "mem-end-rec", /*OP_MEMORY_END_REC*/
+ "fail", /*OP_FAIL*/
+ "jump", /*OP_JUMP*/
+ "push", /*OP_PUSH*/
+ "pop", /*OP_POP*/
+ "push-or-jump-e1", /*OP_PUSH_OR_JUMP_EXACT1*/
+ "push-if-peek-next", /*OP_PUSH_IF_PEEK_NEXT*/
+ "repeat", /*OP_REPEAT*/
+ "repeat-ng", /*OP_REPEAT_NG*/
+ "repeat-inc", /*OP_REPEAT_INC*/
+ "repeat-inc-ng", /*OP_REPEAT_INC_NG*/
+ "repeat-inc-sg", /*OP_REPEAT_INC_SG*/
+ "repeat-inc-ng-sg", /*OP_REPEAT_INC_NG_SG*/
+ "null-check-start", /*OP_NULL_CHECK_START*/
+ "null-check-end", /*OP_NULL_CHECK_END*/
+ "null-check-end-memst", /*OP_NULL_CHECK_END_MEMST*/
+ "null-check-end-memst-push", /*OP_NULL_CHECK_END_MEMST_PUSH*/
+ "push-pos", /*OP_PUSH_POS*/
+ "pop-pos", /*OP_POP_POS*/
+ "push-pos-not", /*OP_PUSH_POS_NOT*/
+ "fail-pos", /*OP_FAIL_POS*/
+ "push-stop-bt", /*OP_PUSH_STOP_BT*/
+ "pop-stop-bt", /*OP_POP_STOP_BT*/
+ "look-behind", /*OP_LOOK_BEHIND*/
+ "push-look-behind-not", /*OP_PUSH_LOOK_BEHIND_NOT*/
+ "fail-look-behind-not", /*OP_FAIL_LOOK_BEHIND_NOT*/
+ "call", /*OP_CALL*/
+ "return", /*OP_RETURN*/
+ "state-check-push", /*OP_STATE_CHECK_PUSH*/
+ "state-check-push-or-jump", /*OP_STATE_CHECK_PUSH_OR_JUMP*/
+ "state-check", /*OP_STATE_CHECK*/
+ "state-check-anychar*", /*OP_STATE_CHECK_ANYCHAR_STAR*/
+ "state-check-anychar-ml*", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+ "set-option-push", /*OP_SET_OPTION_PUSH*/
+ "set-option", /*OP_SET_OPTION*/
+
+ // single byte versions
+ "anychar-sb", /*OP_ANYCHAR*/
+ "anychar-ml-sb", /*OP_ANYCHAR_ML*/
+ "anychar*-sb", /*OP_ANYCHAR_STAR*/
+ "anychar-ml*-sb", /*OP_ANYCHAR_ML_STAR*/
+ "anychar*-peek-next-sb", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+ "anychar-ml*-peek-next-sb", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+ "state-check-anychar*-sb", /*OP_STATE_CHECK_ANYCHAR_STAR*/
+ "state-check-anychar-ml*-sb", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+
+ "cclass-sb", /*OP_CCLASS*/
+ "cclass-not-sb", /*OP_CCLASS_NOT*/
+
+ "word-sb", /*OP_WORD*/
+ "not-word-sb", /*OP_NOT_WORD*/
+ "word-bound-sb", /*OP_WORD_BOUND*/
+ "not-word-bound-sb", /*OP_NOT_WORD_BOUND*/
+ "word-begin-sb", /*OP_WORD_BEGIN*/
+ "word-end-sb", /*OP_WORD_END*/
+
+ "look-behind-sb", /*OP_LOOK_BEHIND*/
+
+ "exact1-ic-sb", /*OP_EXACT1_IC*/
+ "exactn-ic-sb", /*OP_EXACTN_IC*/
+
+ };
+
+ private final static int OpCodeArgTypes[] = new int[] {
+ Arguments.NON, /*OP_FINISH*/
+ Arguments.NON, /*OP_END*/
+ Arguments.SPECIAL, /*OP_EXACT1*/
+ Arguments.SPECIAL, /*OP_EXACT2*/
+ Arguments.SPECIAL, /*OP_EXACT3*/
+ Arguments.SPECIAL, /*OP_EXACT4*/
+ Arguments.SPECIAL, /*OP_EXACT5*/
+ Arguments.SPECIAL, /*OP_EXACTN*/
+ Arguments.SPECIAL, /*OP_EXACTMB2N1*/
+ Arguments.SPECIAL, /*OP_EXACTMB2N2*/
+ Arguments.SPECIAL, /*OP_EXACTMB2N3*/
+ Arguments.SPECIAL, /*OP_EXACTMB2N*/
+ Arguments.SPECIAL, /*OP_EXACTMB3N*/
+ Arguments.SPECIAL, /*OP_EXACTMBN*/
+ Arguments.SPECIAL, /*OP_EXACT1_IC*/
+ Arguments.SPECIAL, /*OP_EXACTN_IC*/
+ Arguments.SPECIAL, /*OP_CCLASS*/
+ Arguments.SPECIAL, /*OP_CCLASS_MB*/
+ Arguments.SPECIAL, /*OP_CCLASS_MIX*/
+ Arguments.SPECIAL, /*OP_CCLASS_NOT*/
+ Arguments.SPECIAL, /*OP_CCLASS_MB_NOT*/
+ Arguments.SPECIAL, /*OP_CCLASS_MIX_NOT*/
+ Arguments.SPECIAL, /*OP_CCLASS_NODE*/
+ Arguments.NON, /*OP_ANYCHAR*/
+ Arguments.NON, /*OP_ANYCHAR_ML*/
+ Arguments.NON, /*OP_ANYCHAR_STAR*/
+ Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
+ Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+ Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+ Arguments.NON, /*OP_WORD*/
+ Arguments.NON, /*OP_NOT_WORD*/
+ Arguments.NON, /*OP_WORD_BOUND*/
+ Arguments.NON, /*OP_NOT_WORD_BOUND*/
+ Arguments.NON, /*OP_WORD_BEGIN*/
+ Arguments.NON, /*OP_WORD_END*/
+ Arguments.NON, /*OP_BEGIN_BUF*/
+ Arguments.NON, /*OP_END_BUF*/
+ Arguments.NON, /*OP_BEGIN_LINE*/
+ Arguments.NON, /*OP_END_LINE*/
+ Arguments.NON, /*OP_SEMI_END_BUF*/
+ Arguments.NON, /*OP_BEGIN_POSITION*/
+ Arguments.NON, /*OP_BACKREF1*/
+ Arguments.NON, /*OP_BACKREF2*/
+ Arguments.MEMNUM, /*OP_BACKREFN*/
+ Arguments.SPECIAL, /*OP_BACKREFN_IC*/
+ Arguments.SPECIAL, /*OP_BACKREF_MULTI*/
+ Arguments.SPECIAL, /*OP_BACKREF_MULTI_IC*/
+ Arguments.SPECIAL, /*OP_BACKREF_AT_LEVEL*/
+ Arguments.MEMNUM, /*OP_MEMORY_START*/
+ Arguments.MEMNUM, /*OP_MEMORY_START_PUSH*/
+ Arguments.MEMNUM, /*OP_MEMORY_END_PUSH*/
+ Arguments.MEMNUM, /*OP_MEMORY_END_PUSH_REC*/
+ Arguments.MEMNUM, /*OP_MEMORY_END*/
+ Arguments.MEMNUM, /*OP_MEMORY_END_REC*/
+ Arguments.NON, /*OP_FAIL*/
+ Arguments.RELADDR, /*OP_JUMP*/
+ Arguments.RELADDR, /*OP_PUSH*/
+ Arguments.NON, /*OP_POP*/
+ Arguments.SPECIAL, /*OP_PUSH_OR_JUMP_EXACT1*/
+ Arguments.SPECIAL, /*OP_PUSH_IF_PEEK_NEXT*/
+ Arguments.SPECIAL, /*OP_REPEAT*/
+ Arguments.SPECIAL, /*OP_REPEAT_NG*/
+ Arguments.MEMNUM, /*OP_REPEAT_INC*/
+ Arguments.MEMNUM, /*OP_REPEAT_INC_NG*/
+ Arguments.MEMNUM, /*OP_REPEAT_INC_SG*/
+ Arguments.MEMNUM, /*OP_REPEAT_INC_NG_SG*/
+ Arguments.MEMNUM, /*OP_NULL_CHECK_START*/
+ Arguments.MEMNUM, /*OP_NULL_CHECK_END*/
+ Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST*/
+ Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST_PUSH*/
+ Arguments.NON, /*OP_PUSH_POS*/
+ Arguments.NON, /*OP_POP_POS*/
+ Arguments.RELADDR, /*OP_PUSH_POS_NOT*/
+ Arguments.NON, /*OP_FAIL_POS*/
+ Arguments.NON, /*OP_PUSH_STOP_BT*/
+ Arguments.NON, /*OP_POP_STOP_BT*/
+ Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
+ Arguments.SPECIAL, /*OP_PUSH_LOOK_BEHIND_NOT*/
+ Arguments.NON, /*OP_FAIL_LOOK_BEHIND_NOT*/
+ Arguments.ABSADDR, /*OP_CALL*/
+ Arguments.NON, /*OP_RETURN*/
+ Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH*/
+ Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH_OR_JUMP*/
+ Arguments.STATE_CHECK, /*OP_STATE_CHECK*/
+ Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
+ Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+ Arguments.OPTION, /*OP_SET_OPTION_PUSH*/
+ Arguments.OPTION, /*OP_SET_OPTION*/
+
+ // single byte versions
+ Arguments.NON, /*OP_ANYCHAR*/
+ Arguments.NON, /*OP_ANYCHAR_ML*/
+ Arguments.NON, /*OP_ANYCHAR_STAR*/
+ Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
+ Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
+ Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
+ Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
+ Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
+
+ Arguments.SPECIAL, /*OP_CCLASS*/
+ Arguments.SPECIAL, /*OP_CCLASS_NOT*/
+
+ Arguments.NON, /*OP_WORD*/
+ Arguments.NON, /*OP_NOT_WORD*/
+ Arguments.NON, /*OP_WORD_BOUND*/
+ Arguments.NON, /*OP_NOT_WORD_BOUND*/
+ Arguments.NON, /*OP_WORD_BEGIN*/
+ Arguments.NON, /*OP_WORD_END*/
+
+ Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
+
+ Arguments.SPECIAL, /*OP_EXACT1_IC*/
+ Arguments.SPECIAL, /*OP_EXACTN_IC*/
+ };
+
public ByteCodePrinter(Regex regex) {
code = regex.code;
codeLength = regex.codeLength;
@@ -76,8 +309,8 @@ class ByteCodePrinter {
CClassNode cc;
int tm, idx;
- sb.append("[" + OPCode.OpCodeNames[code[bp]]);
- int argType = OPCode.OpCodeArgTypes[code[bp]];
+ sb.append("[" + OpCodeNames[code[bp]]);
+ int argType = OpCodeArgTypes[code[bp]];
int ip = bp;
if (argType != Arguments.SPECIAL) {
bp++;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CaptureTreeNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CaptureTreeNode.java
deleted file mode 100644
index 268f682c92e..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CaptureTreeNode.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-public class CaptureTreeNode {
-
-
- int group;
- int beg;
- int end;
- // int allocated;
- int numChildren;
- CaptureTreeNode[]children;
-
- CaptureTreeNode() {
- beg = Region.REGION_NOTPOS;
- end = Region.REGION_NOTPOS;
- group = -1;
- }
-
- static final int HISTORY_TREE_INIT_ALLOC_SIZE = 8;
- void addChild(CaptureTreeNode child) {
- if (children == null) {
- children = new CaptureTreeNode[HISTORY_TREE_INIT_ALLOC_SIZE];
- } else if (numChildren >= children.length) {
- CaptureTreeNode[]tmp = new CaptureTreeNode[children.length << 1];
- System.arraycopy(children, 0, tmp, 0, children.length);
- children = tmp;
- }
-
- children[numChildren] = child;
- numChildren++;
- }
-
- void clear() {
- for (int i=0; i, \k */
-
final boolean USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT = true; /* /(?:()|())*\2/ */
final boolean USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE = true; /* /\n$/ =~ "\n" */
final boolean USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR = false;
@@ -42,12 +38,10 @@ public interface Config {
final boolean CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS = true;
final boolean USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE = false;
- final boolean USE_CAPTURE_HISTORY = false;
final boolean USE_VARIABLE_META_CHARS = true;
final boolean USE_WORD_BEGIN_END = true; /* "\<": word-begin, "\>": word-end */
- final boolean USE_POSIX_API_REGION_OPTION = true; /* needed for POSIX API support */
+ final boolean USE_POSIX_API_REGION_OPTION = false; /* needed for POSIX API support */
final boolean USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE = true;
- final boolean USE_COMBINATION_EXPLOSION_CHECK = false;
final int NREGION = 10;
final int MAX_BACKREF_NUM = 1000;
@@ -73,13 +67,6 @@ public interface Config {
final boolean USE_STRING_TEMPLATES = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
-
- final int MAX_CAPTURE_HISTORY_GROUP = 31;
-
-
- final int CHECK_STRING_THRESHOLD_LEN = 7;
- final int CHECK_BUFF_MAX_SIZE = 0x4000;
-
final boolean NON_UNICODE_SDW = true;
@@ -95,6 +82,4 @@ public interface Config {
final boolean DEBUG_COMPILE_BYTE_CODE_INFO = DEBUG_ALL;
final boolean DEBUG_SEARCH = DEBUG_ALL;
final boolean DEBUG_MATCH = DEBUG_ALL;
- final boolean DEBUG_ASM = true;
- final boolean DEBUG_ASM_EXEC = true;
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
index d3e54947aea..8c274fe0365 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
@@ -95,20 +95,6 @@ public class EncodingHelper {
return s;
}
- /* onigenc_with_ascii_strncmp */
- public static int strNCmp(char[] chars1, int p1, int end, char[] chars2, int p2, int n) {
- while (n-- > 0) {
- if (p1 >= end) return chars2[p2];
- int c = chars1[p1];
- int x = chars2[p2] - c;
- if (x != 0) return x;
-
- p2++;
- p1++;
- }
- return 0;
- }
-
public static int mbcToCode(byte[] bytes, int p, int end) {
int code = 0;
for (int i = p; i < end; i++) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
index c289f33d34d..53ab3ec066b 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
@@ -27,10 +27,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
import jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar;
import jdk.nashorn.internal.runtime.regexp.joni.constants.TokenType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
class Lexer extends ScannerSupport {
protected final ScanEnvironment env;
@@ -215,198 +212,6 @@ class Lexer extends ScannerSupport {
\k<-num+n>, \k<-num-n>
*/
- // value implicit (rnameEnd)
- private boolean fetchNameWithLevel(int startCode, Ptr rbackNum, Ptr rlevel) {
- int src = p;
- boolean existLevel = false;
- int isNum = 0;
- int sign = 1;
-
- int endCode = nameEndCodePoint(startCode);
- int pnumHead = p;
- int nameEnd = stop;
-
- String err = null;
- if (!left()) {
- newValueException(ERR_EMPTY_GROUP_NAME);
- } else {
- fetch();
- if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
- if (Character.isDigit(c)) {
- isNum = 1;
- } else if (c == '-') {
- isNum = 2;
- sign = -1;
- pnumHead = p;
- } else if (!EncodingHelper.isWord(c)) {
- err = ERR_INVALID_GROUP_NAME;
- }
- }
-
- while (left()) {
- nameEnd = p;
- fetch();
- if (c == endCode || c == ')' || c == '+' || c == '-') {
- if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
- break;
- }
-
- if (isNum != 0) {
- if (EncodingHelper.isDigit(c)) {
- isNum = 1;
- } else {
- err = ERR_INVALID_GROUP_NAME;
- // isNum = 0;
- }
- } else if (!EncodingHelper.isWord(c)) {
- err = ERR_INVALID_CHAR_IN_GROUP_NAME;
- }
- }
-
- boolean isEndCode = false;
- if (err == null && c != endCode) {
- if (c == '+' || c == '-') {
- int flag = c == '-' ? -1 : 1;
-
- fetch();
- if (!EncodingHelper.isDigit(c)) newValueException(ERR_INVALID_GROUP_NAME, src, stop);
- unfetch();
- int level = scanUnsignedNumber();
- if (level < 0) newValueException(ERR_TOO_BIG_NUMBER);
- rlevel.p = level * flag;
- existLevel = true;
-
- fetch();
- isEndCode = c == endCode;
- }
-
- if (!isEndCode) {
- err = ERR_INVALID_GROUP_NAME;
- nameEnd = stop;
- }
- }
-
- if (err == null) {
- if (isNum != 0) {
- mark();
- p = pnumHead;
- int backNum = scanUnsignedNumber();
- restore();
- if (backNum < 0) {
- newValueException(ERR_TOO_BIG_NUMBER);
- } else if (backNum == 0) {
- newValueException(ERR_INVALID_GROUP_NAME, src, stop);
- }
- rbackNum.p = backNum * sign;
- }
- value = nameEnd;
- return existLevel;
- } else {
- newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
- return false; // not reached
- }
- }
-
- // USE_NAMED_GROUP
- // ref: 0 -> define name (don't allow number name)
- // 1 -> reference name (allow number name)
- private int fetchNameForNamedGroup(int startCode, boolean ref) {
- int src = p;
- value = 0;
-
- int isNum = 0;
- int sign = 1;
-
- int endCode = nameEndCodePoint(startCode);
- int pnumHead = p;
- int nameEnd = stop;
-
- String err = null;
- if (!left()) {
- newValueException(ERR_EMPTY_GROUP_NAME);
- } else {
- fetch();
- if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
- if (EncodingHelper.isDigit(c)) {
- if (ref) {
- isNum = 1;
- } else {
- err = ERR_INVALID_GROUP_NAME;
- // isNum = 0;
- }
- } else if (c == '-') {
- if (ref) {
- isNum = 2;
- sign = -1;
- pnumHead = p;
- } else {
- err = ERR_INVALID_GROUP_NAME;
- // isNum = 0;
- }
- } else if (!EncodingHelper.isWord(c)) {
- err = ERR_INVALID_CHAR_IN_GROUP_NAME;
- }
- }
-
- if (err == null) {
- while (left()) {
- nameEnd = p;
- fetch();
- if (c == endCode || c == ')') {
- if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
- break;
- }
-
- if (isNum != 0) {
- if (EncodingHelper.isDigit(c)) {
- isNum = 1;
- } else {
- if (!EncodingHelper.isWord(c)) {
- err = ERR_INVALID_CHAR_IN_GROUP_NAME;
- } else {
- err = ERR_INVALID_GROUP_NAME;
- }
- // isNum = 0;
- }
- } else {
- if (!EncodingHelper.isWord(c)) {
- err = ERR_INVALID_CHAR_IN_GROUP_NAME;
- }
- }
- }
-
- if (c != endCode) {
- err = ERR_INVALID_GROUP_NAME;
- nameEnd = stop;
- }
-
- int backNum = 0;
- if (isNum != 0) {
- mark();
- p = pnumHead;
- backNum = scanUnsignedNumber();
- restore();
- if (backNum < 0) {
- newValueException(ERR_TOO_BIG_NUMBER);
- } else if (backNum == 0) {
- newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
- }
- backNum *= sign;
- }
- value = nameEnd;
- return backNum;
- } else {
- while (left()) {
- nameEnd = p;
- fetch();
- if (c == endCode || c == ')') break;
- }
- if (!left()) nameEnd = stop;
- newValueException(err, src, nameEnd);
- return 0; // not reached
- }
- }
-
// #else USE_NAMED_GROUP
// make it return nameEnd!
private final int fetchNameForNoNamedGroup(int startCode, boolean ref) {
@@ -472,11 +277,7 @@ class Lexer extends ScannerSupport {
}
protected final int fetchName(int startCode, boolean ref) {
- if (Config.USE_NAMED_GROUP) {
- return fetchNameForNamedGroup(startCode, ref);
- } else {
- return fetchNameForNoNamedGroup(startCode, ref);
- }
+ return fetchNameForNoNamedGroup(startCode, ref);
}
private boolean strExistCheckWithEsc(int[]s, int n, int bad) {
@@ -519,26 +320,6 @@ class Lexer extends ScannerSupport {
token.setPropNot(flag);
}
- private void fetchTokenInCCFor_p() {
- int c2 = peek(); // !!! migrate to peekIs
- if (c2 == '{' && syntax.op2EscPBraceCharProperty()) {
- inc();
- token.type = TokenType.CHAR_PROPERTY;
- token.setPropNot(c == 'P');
-
- if (syntax.op2EscPBraceCircumflexNot()) {
- c2 = fetchTo();
- if (c2 == '^') {
- token.setPropNot(!token.getPropNot());
- } else {
- unfetch();
- }
- }
- } else {
- syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
- }
- }
-
private void fetchTokenInCCFor_x() {
if (!left()) return;
int last = p;
@@ -604,30 +385,6 @@ class Lexer extends ScannerSupport {
}
}
- private void fetchTokenInCCFor_posixBracket() {
- if (syntax.opPosixBracket() && peekIs(':')) {
- token.backP = p; /* point at '[' is readed */
- inc();
- if (strExistCheckWithEsc(send, send.length, ']')) {
- token.type = TokenType.POSIX_BRACKET_OPEN;
- } else {
- unfetch();
- // remove duplication, goto cc_in_cc;
- if (syntax.op2CClassSetOp()) {
- token.type = TokenType.CC_CC_OPEN;
- } else {
- env.ccEscWarn("[");
- }
- }
- } else { // cc_in_cc:
- if (syntax.op2CClassSetOp()) {
- token.type = TokenType.CC_CC_OPEN;
- } else {
- env.ccEscWarn("[");
- }
- }
- }
-
private void fetchTokenInCCFor_and() {
if (syntax.op2CClassSetOp() && left() && peekIs('&')) {
inc();
@@ -683,10 +440,6 @@ class Lexer extends ScannerSupport {
case 'H':
if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
break;
- case 'p':
- case 'P':
- fetchTokenInCCFor_p();
- break;
case 'x':
fetchTokenInCCFor_x();
break;
@@ -714,18 +467,12 @@ class Lexer extends ScannerSupport {
break;
} // switch
- } else if (c == '[') {
- fetchTokenInCCFor_posixBracket();
} else if (c == '&') {
fetchTokenInCCFor_and();
}
return token.type;
}
- protected final int backrefRelToAbs(int relNo) {
- return env.numMem + 1 + relNo;
- }
-
private void fetchTokenFor_repeat(int lower, int upper) {
token.type = TokenType.OP_REPEAT;
token.setRepeatLower(lower);
@@ -815,7 +562,6 @@ class Lexer extends ScannerSupport {
token.setBackrefNum(1);
token.setBackrefRef1(num);
token.setBackrefByName(false);
- if (Config.USE_BACKREF_WITH_LEVEL) token.setBackrefExistLevel(false);
return;
}
@@ -845,76 +591,6 @@ class Lexer extends ScannerSupport {
}
}
- private void fetchTokenFor_namedBackref() {
- if (syntax.op2EscKNamedBackref()) {
- if (left()) {
- fetch();
- if (c =='<' || c == '\'') {
- int last = p;
- int backNum;
- if (Config.USE_BACKREF_WITH_LEVEL) {
- Ptr rbackNum = new Ptr();
- Ptr rlevel = new Ptr();
- token.setBackrefExistLevel(fetchNameWithLevel(c, rbackNum, rlevel));
- token.setBackrefLevel(rlevel.p);
- backNum = rbackNum.p;
- } else {
- backNum = fetchName(c, true);
- } // USE_BACKREF_AT_LEVEL
- int nameEnd = value; // set by fetchNameWithLevel/fetchName
-
- if (backNum != 0) {
- if (backNum < 0) {
- backNum = backrefRelToAbs(backNum);
- if (backNum <= 0) newValueException(ERR_INVALID_BACKREF);
- }
-
- if (syntax.strictCheckBackref() && (backNum > env.numMem || env.memNodes == null)) {
- newValueException(ERR_INVALID_BACKREF);
- }
- token.type = TokenType.BACKREF;
- token.setBackrefByName(false);
- token.setBackrefNum(1);
- token.setBackrefRef1(backNum);
- } else {
- NameEntry e = env.reg.nameToGroupNumbers(chars, last, nameEnd);
- if (e == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, last, nameEnd);
-
- if (syntax.strictCheckBackref()) {
- if (e.backNum == 1) {
- if (e.backRef1 > env.numMem ||
- env.memNodes == null ||
- env.memNodes[e.backRef1] == null) newValueException(ERR_INVALID_BACKREF);
- } else {
- for (int i=0; i env.numMem ||
- env.memNodes == null ||
- env.memNodes[e.backRefs[i]] == null) newValueException(ERR_INVALID_BACKREF);
- }
- }
- }
-
- token.type = TokenType.BACKREF;
- token.setBackrefByName(true);
-
- if (e.backNum == 1) {
- token.setBackrefNum(1);
- token.setBackrefRef1(e.backRef1);
- } else {
- token.setBackrefNum(e.backNum);
- token.setBackrefRefs(e.backRefs);
- }
- }
- } else {
- unfetch();
- syntaxWarn(Warnings.INVALID_BACKREFERENCE);
- }
- } else {
- syntaxWarn(Warnings.INVALID_BACKREFERENCE);
- }
- }
- }
-
private void fetchTokenFor_subexpCall() {
if (syntax.op2EscGSubexpCall()) {
if (left()) {
@@ -937,25 +613,6 @@ class Lexer extends ScannerSupport {
}
}
- private void fetchTokenFor_charProperty() {
- if (peekIs('{') && syntax.op2EscPBraceCharProperty()) {
- inc();
- token.type = TokenType.CHAR_PROPERTY;
- token.setPropNot(c == 'P');
-
- if (syntax.op2EscPBraceCircumflexNot()) {
- fetch();
- if (c == '^') {
- token.setPropNot(!token.getPropNot());
- } else {
- unfetch();
- }
- }
- } else {
- syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
- }
- }
-
private void fetchTokenFor_metaChars() {
if (c == syntax.metaCharTable.anyChar) {
token.type = TokenType.ANYCHAR;
@@ -1091,19 +748,6 @@ class Lexer extends ScannerSupport {
case '0':
fetchTokenFor_zero();
break;
- case 'k':
- if (Config.USE_NAMED_GROUP) fetchTokenFor_namedBackref();
- break;
- case 'g':
- if (Config.USE_SUBEXP_CALL) fetchTokenFor_subexpCall();
- break;
- case 'Q':
- if (syntax.op2EscCapitalQQuote()) token.type = TokenType.QUOTE_OPEN;
- break;
- case 'p':
- case 'P':
- fetchTokenFor_charProperty();
- break;
default:
unfetch();
@@ -1244,24 +888,6 @@ class Lexer extends ScannerSupport {
}
}
- protected final int fetchCharPropertyToCType() {
- mark();
-
- while (left()) {
- int last = p;
- fetch();
- if (c == '}') {
- String name = new String(chars, _p, last - _p);
- return PosixBracket.propertyNameToCType(name);
- } else if (c == '(' || c == ')' || c == '{' || c == '|') {
- String name = new String(chars, _p, last - _p);
- throw new JOniException(ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
- }
- }
- newInternalException(ERR_PARSER_BUG);
- return 0; // not reached
- }
-
protected final void syntaxWarn(String message, char c) {
syntaxWarn(message.replace("<%n>", Character.toString(c)));
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
index 4aea4acb787..911b23b391e 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
@@ -58,17 +58,10 @@ public abstract class Matcher extends IntHolder {
// main matching method
protected abstract int matchAt(int range, int sstart, int sprev);
- protected abstract void stateCheckBuffInit(int strLength, int offset, int stateNum);
- protected abstract void stateCheckBuffClear();
-
public final Region getRegion() {
return msaRegion;
}
- public final Region getEagerRegion() {
- return msaRegion != null ? msaRegion : new Region(msaBegin, msaEnd);
- }
-
public final int getBegin() {
return msaBegin;
}
@@ -86,11 +79,6 @@ public abstract class Matcher extends IntHolder {
public final int match(int at, int range, int option) {
msaInit(option, at);
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- int offset = at = str;
- stateCheckBuffInit(end - str, offset, regex.numCombExpCheck); // move it to construction?
- } // USE_COMBINATION_EXPLOSION_CHECK
-
int prev = EncodingHelper.prevCharHead(str, at);
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
@@ -377,8 +365,6 @@ public abstract class Matcher extends IntHolder {
prev = -1;
msaInit(option, start);
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) stateCheckBuffClear();
-
if (matchCheck(end, s, prev)) return match(s);
return mismatch();
}
@@ -393,10 +379,6 @@ public abstract class Matcher extends IntHolder {
}
msaInit(option, origStart);
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- int offset = Math.min(start, range) - str;
- stateCheckBuffInit(end - str, offset, regex.numCombExpCheck);
- }
s = start;
if (range > start) { /* forward search */
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NameEntry.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NameEntry.java
deleted file mode 100644
index d35f725155e..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NameEntry.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-public final class NameEntry {
- static final int INIT_NAME_BACKREFS_ALLOC_NUM = 8;
-
- public final char[] name;
- public final int nameP;
- public final int nameEnd;
-
- int backNum;
- int backRef1;
- int backRefs[];
-
- public NameEntry(char[] chars, int p, int end) {
- name = chars;
- nameP = p;
- nameEnd = end;
- }
-
- public int[] getBackRefs() {
- switch (backNum) {
- case 0:
- return new int[]{};
- case 1:
- return new int[]{backRef1};
- default:
- int[]result = new int[backNum];
- System.arraycopy(backRefs, 0, result, 0, backNum);
- return result;
- }
- }
-
- private void alloc() {
- backRefs = new int[INIT_NAME_BACKREFS_ALLOC_NUM];
- }
-
- private void ensureSize() {
- if (backNum > backRefs.length) {
- int[]tmp = new int[backRefs.length << 1];
- System.arraycopy(backRefs, 0, tmp, 0, backRefs.length);
- backRefs = tmp;
- }
- }
-
- public void addBackref(int backRef) {
- backNum++;
-
- switch (backNum) {
- case 1:
- backRef1 = backRef;
- break;
- case 2:
- alloc();
- backRefs[0] = backRef1;
- backRefs[1] = backRef;
- break;
- default:
- ensureSize();
- backRefs[backNum - 1] = backRef;
- }
- }
-
- public String toString() {
- StringBuilder buff = new StringBuilder(new String(name, nameP, nameEnd - nameP) + " ");
- if (backNum == 0) {
- buff.append("-");
- } else if (backNum == 1){
- buff.append(backRef1);
- } else {
- for (int i=0; i 0) buff.append(", ");
- buff.append(backRefs[i]);
- }
- }
- return buff.toString();
- }
-
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NativeMachine.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NativeMachine.java
deleted file mode 100644
index 2a3f2a13144..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NativeMachine.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-public abstract class NativeMachine extends Matcher {
-
- protected NativeMachine(Regex regex, char[] chars, int p, int end) {
- super(regex, chars, p, end);
- }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
index 13d569b7b08..749b1d4196d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
@@ -19,20 +19,15 @@
*/
package jdk.nashorn.internal.runtime.regexp.joni;
-import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnOff;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
-import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnyCharNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
@@ -66,65 +61,6 @@ class Parser extends Lexer {
return root;
}
- private static final int POSIX_BRACKET_NAME_MIN_LEN = 4;
- private static final int POSIX_BRACKET_CHECK_LIMIT_LENGTH = 20;
- private static final char BRACKET_END[] = ":]".toCharArray();
- private boolean parsePosixBracket(CClassNode cc) {
- mark();
-
- boolean not;
- if (peekIs('^')) {
- inc();
- not = true;
- } else {
- not = false;
- }
- if (stop - p >= POSIX_BRACKET_NAME_MIN_LEN + 3) { // else goto not_posix_bracket
- char[][] pbs = PosixBracket.PBSNamesLower;
- for (int i=0; i POSIX_BRACKET_CHECK_LIMIT_LENGTH) break;
- }
-
- if (c == ':' && left()) {
- inc();
- if (left()) {
- fetch();
- if (c == ']') newSyntaxException(ERR_INVALID_POSIX_BRACKET_TYPE);
- }
- }
- restore();
- return true; /* 1: is not POSIX bracket, but no error. */
- }
-
- private CClassNode parseCharProperty() {
- int ctype = fetchCharPropertyToCType();
- CClassNode n = new CClassNode();
- n.addCType(ctype, false, env, this);
- if (token.getPropNot()) n.setNot();
- return n;
- }
-
private boolean codeExistCheck(int code, boolean ignoreEscaped) {
mark();
@@ -225,29 +161,11 @@ class Parser extends Lexer {
parseCharClassValEntry(cc, arg); // val_entry:, val_entry2
break;
- case POSIX_BRACKET_OPEN:
- if (parsePosixBracket(cc)) { /* true: is not POSIX bracket */
- env.ccEscWarn("[");
- p = token.backP;
- arg.v = token.getC();
- arg.vIsRaw = false;
- parseCharClassValEntry(cc, arg); // goto val_entry
- break;
- }
- cc.nextStateClass(arg, env); // goto next_class
- break;
-
case CHAR_TYPE:
cc.addCType(token.getPropCType(), token.getPropNot(), env, this);
cc.nextStateClass(arg, env); // next_class:
break;
- case CHAR_PROPERTY:
- int ctype = fetchCharPropertyToCType();
- cc.addCType(ctype, token.getPropNot(), env, this);
- cc.nextStateClass(arg, env); // goto next_class
- break;
-
case CC_RANGE:
if (arg.state == CCSTATE.VALUE) {
fetchTokenInCC();
@@ -413,15 +331,6 @@ class Parser extends Lexer {
node = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
break;
case '\'':
- if (Config.USE_NAMED_GROUP) {
- if (syntax.op2QMarkLtNamedGroup()) {
- listCapture = false; // goto named_group1
- node = parseEncloseNamedGroup2(listCapture);
- break;
- } else {
- newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
- }
- } // USE_NAMED_GROUP
break;
case '<': /* look behind (?<=...), (?...) */
- }
- unfetch();
- }
- } // USE_NAMED_GROUP
- EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory
+ EncloseNode en = new EncloseNode(); // node_new_enclose_memory
int num = env.addMemEntry();
if (num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
en.regNum = num;
@@ -546,7 +431,7 @@ class Parser extends Lexer {
returnCode = 1; /* group */
return node;
}
- EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory
+ EncloseNode en = new EncloseNode(); // node_new_enclose_memory
int num = env.addMemEntry();
en.regNum = num;
node = en;
@@ -570,48 +455,6 @@ class Parser extends Lexer {
return node; // ??
}
- private Node parseEncloseNamedGroup2(boolean listCapture) {
- int nm = p;
- int num = fetchName(c, false);
- int nameEnd = value;
- num = env.addMemEntry();
- if (listCapture && num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
-
- regex.nameAdd(chars, nm, nameEnd, num, syntax);
- EncloseNode en = new EncloseNode(env.option, true); // node_new_enclose_memory
- en.regNum = num;
-
- Node node = en;
-
- if (listCapture) env.captureHistory = bsOnAtSimple(env.captureHistory, num);
- env.numNamed++;
- return node;
- }
-
- private int findStrPosition(int[]s, int n, int from, int to, Ptr nextChar) {
- int x;
- int q;
- int p = from;
- int i = 0;
- while (p < to) {
- x = chars[p];
- q = p + 1;
- if (x == s[0]) {
- for (i=1; i= n) {
- if (chars[nextChar.p] != 0) nextChar.p = q; // we may need zero term semantics...
- return p;
- }
- }
- p = q;
- }
- return -1;
- }
-
private Node parseExp(TokenType term) {
if (token.type == term) return StringNode.EMPTY; // goto end_of_token
@@ -656,16 +499,6 @@ class Parser extends Lexer {
node = new StringNode(buf, 0, 1);
break;
- case QUOTE_OPEN:
- int[] endOp = new int[] {syntax.metaCharTable.esc, 'E'};
- int qstart = p;
- Ptr nextChar = new Ptr();
- int qend = findStrPosition(endOp, endOp.length, qstart, stop, nextChar);
- if (qend == -1) nextChar.p = qend = stop;
- node = new StringNode(chars, qstart, qend);
- p = nextChar.p;
- break;
-
case CHAR_TYPE:
switch(token.getPropCType()) {
case CharacterType.D:
@@ -679,10 +512,6 @@ class Parser extends Lexer {
}
break;
- case CharacterType.WORD:
- node = new CTypeNode(token.getPropCType(), token.getPropNot());
- break;
-
case CharacterType.SPACE:
case CharacterType.DIGIT:
case CharacterType.XDIGIT:
@@ -699,10 +528,6 @@ class Parser extends Lexer {
} // inner switch
break;
- case CHAR_PROPERTY:
- node = parseCharProperty();
- break;
-
case CC_CC_OPEN:
CClassNode cc = parseCharClass();
node = cc;
@@ -735,20 +560,6 @@ class Parser extends Lexer {
token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL
token.getBackrefLevel(), // ...
env);
-
- break;
-
- case CALL:
- if (Config.USE_SUBEXP_CALL) {
- int gNum = token.getCallGNum();
-
- if (gNum < 0) {
- gNum = backrefRelToAbs(gNum);
- if (gNum <= 0) newValueException(ERR_INVALID_BACKREF);
- }
- node = new CallNode(chars, token.getCallNameP(), token.getCallNameEnd(), gNum);
- env.numCall++;
- } // USE_SUBEXP_CALL
break;
case ANCHOR:
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
index da5b98271b7..b27814a71ce 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
@@ -23,9 +23,11 @@ import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
+import java.nio.file.Files;
import java.util.HashMap;
import java.util.Iterator;
+import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
@@ -44,7 +46,6 @@ public final class Regex implements RegexState {
int numMem; /* used memory(...) num counted from 1 */
int numRepeat; /* OP_REPEAT/OP_REPEAT_NG id-counter */
int numNullCheck; /* OP_NULL_CHECK_START/END id counter */
- int numCombExpCheck; /* combination explosion check */
int numCall; /* number of subexp call */
int captureHistory; /* (?@...) flag (1-31) */
int btMemStart; /* need backtrack flag */
@@ -57,7 +58,7 @@ public final class Regex implements RegexState {
WarnCallback warnings;
MatcherFactory factory;
- private Analyser analyser;
+ protected Analyser analyser;
int options;
int userOptions;
@@ -65,8 +66,6 @@ public final class Regex implements RegexState {
//final Syntax syntax;
final int caseFoldFlag;
- HashMap nameTable; // named entries
-
/* optimization info (string search, char-map and anchors) */
SearchAlgorithm searchAlgorithm; /* optimize flag */
int thresholdLength; /* search str-length for apply optimize */
@@ -172,112 +171,6 @@ public final class Regex implements RegexState {
return numMem;
}
- public int numberOfCaptureHistories() {
- if (Config.USE_CAPTURE_HISTORY) {
- int n = 0;
- for (int i=0; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
- if (bsAt(captureHistory, i)) n++;
- }
- return n;
- } else {
- return 0;
- }
- }
-
- String nameTableToString() {
- StringBuilder sb = new StringBuilder();
-
- if (nameTable != null) {
- sb.append("name table\n");
- for (NameEntry ne : nameTable.values()) {
- sb.append(" " + ne + "\n");
- }
- sb.append("\n");
- }
- return sb.toString();
- }
-
- NameEntry nameFind(char[] name, int nameP, int nameEnd) {
- if (nameTable != null) return nameTable.get(new String(name, nameP, nameEnd - nameP));
- return null;
- }
-
- void renumberNameTable(int[]map) {
- if (nameTable != null) {
- for (NameEntry e : nameTable.values()) {
- if (e.backNum > 1) {
- for (int i=0; i(); // 13, oni defaults to 5
- } else {
- e = nameFind(name, nameP, nameEnd);
- }
-
- if (e == null) {
- // dup the name here as oni does ?, what for ? (it has to manage it, we don't)
- e = new NameEntry(name, nameP, nameEnd);
- nameTable.put(new String(name, nameP, nameEnd - nameP), e);
- } else if (e.backNum >= 1 && !syntax.allowMultiplexDefinitionName()) {
- throw new ValueException(ErrorMessages.ERR_MULTIPLEX_DEFINED_NAME, new String(name, nameP, nameEnd - nameP));
- }
-
- e.addBackref(backRef);
- }
-
- NameEntry nameToGroupNumbers(char[] name, int nameP, int nameEnd) {
- return nameFind(name, nameP, nameEnd);
- }
-
- public int nameToBackrefNumber(char[] name, int nameP, int nameEnd, Region region) {
- NameEntry e = nameToGroupNumbers(name, nameP, nameEnd);
- if (e == null) throw new ValueException(ErrorMessages.ERR_UNDEFINED_NAME_REFERENCE,
- new String(name, nameP, nameEnd - nameP));
-
- switch(e.backNum) {
- case 0:
- throw new InternalException(ErrorMessages.ERR_PARSER_BUG);
- case 1:
- return e.backRef1;
- default:
- if (region != null) {
- for (int i = e.backNum - 1; i >= 0; i--) {
- if (region.beg[e.backRefs[i]] != Region.REGION_NOTPOS) return e.backRefs[i];
- }
- }
- return e.backRefs[e.backNum - 1];
- }
- }
-
- public Iterator namedBackrefIterator() {
- return nameTable.values().iterator();
- }
-
- public boolean noNameGroupIsActive(Syntax syntax) {
- if (isDontCaptureGroup(options)) return false;
-
- if (Config.USE_NAMED_GROUP) {
- if (numberOfNames() > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(options)) return false;
- }
- return true;
- }
-
/* set skip map for Boyer-Moor search */
void setupBMSkipMap() {
char[] chars = exact;
@@ -353,16 +246,6 @@ public final class Regex implements RegexState {
exactP = exactEnd = 0;
}
- public String encStringToString(byte[]bytes, int p, int end) {
- StringBuilder sb = new StringBuilder("\nPATTERN: /");
-
- while (p < end) {
- sb.append(new String(new byte[]{bytes[p]}));
- p++;
- }
- return sb.append("/").toString();
- }
-
public String optimizeInfoToString() {
String s = "";
s += "optimize: " + searchAlgorithm.getName() + "\n";
@@ -410,19 +293,13 @@ public final class Regex implements RegexState {
return options;
}
- public void setUserOptions(int options) {
- this.userOptions = options;
+ public String dumpTree() {
+ return analyser == null ? null : analyser.root.toString();
}
- public int getUserOptions() {
- return userOptions;
+ public String dumpByteCode() {
+ compile();
+ return new ByteCodePrinter(this).byteCodeListToString();
}
- public void setUserObject(Object object) {
- this.userObject = object;
- }
-
- public Object getUserObject() {
- return userObject;
- }
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
index d685a249593..ee9eb16810b 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
@@ -25,7 +25,6 @@ public final class Region {
public final int numRegs;
public final int[]beg;
public final int[]end;
- public CaptureTreeNode historyRoot;
public Region(int num) {
this.numRegs = num;
@@ -33,20 +32,6 @@ public final class Region {
this.end = new int[num];
}
- public Region(int begin, int end) {
- this.numRegs = 1;
- this.beg = new int[]{begin};
- this.end = new int[]{end};
- }
-
- public Region clone() {
- Region region = new Region(numRegs);
- System.arraycopy(beg, 0, region.beg, 0, beg.length);
- System.arraycopy(end, 0, region.end, 0, end.length);
- if (historyRoot != null) region.historyRoot = historyRoot.cloneTree();
- return region;
- }
-
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Region: \n");
@@ -54,10 +39,6 @@ public final class Region {
return sb.toString();
}
- CaptureTreeNode getCaptureTree() {
- return historyRoot;
- }
-
void clear() {
for (int i=0; i 0 && strLength >= Config.CHECK_STRING_THRESHOLD_LEN) {
- int size = ((strLength + 1) * stateNum + 7) >>> 3;
- offset = (offset * stateNum) >>> 3;
-
- if (size > 0 && offset < size && size < Config.CHECK_BUFF_MAX_SIZE) {
- if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) {
- stateCheckBuff = new byte[size];
- } else {
- // same impl, reduce...
- stateCheckBuff = new byte[size];
- }
- Arrays.fill(stateCheckBuff, offset, (size - offset), (byte)0);
- stateCheckBuffSize = size;
- } else {
- stateCheckBuff = null; // reduce
- stateCheckBuffSize = 0;
- }
- } else {
- stateCheckBuff = null; // reduce
- stateCheckBuffSize = 0;
- }
- }
-
- protected final void stateCheckBuffClear() {
- stateCheckBuff = null;
- stateCheckBuffSize = 0;
- }
-
private void push(int type, int pat, int s, int prev) {
StackEntry e = ensure1();
e.type = type;
e.setStatePCode(pat);
e.setStatePStr(s);
e.setStatePStrPrev(prev);
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
stk++;
}
@@ -172,30 +112,9 @@ abstract class StackMachine extends Matcher implements StackType {
StackEntry e = stack[stk];
e.type = type;
e.setStatePCode(pat);
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
stk++;
}
- protected final void pushAltWithStateCheck(int pat, int s, int sprev, int snum) {
- StackEntry e = ensure1();
- e.type = ALT;
- e.setStatePCode(pat);
- e.setStatePStr(s);
- e.setStatePStrPrev(sprev);
- if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(stateCheckBuff != null ? snum : 0);
- stk++;
- }
-
- protected final void pushStateCheck(int s, int snum) {
- if (stateCheckBuff != null) {
- StackEntry e = ensure1();
- e.type = STATE_CHECK_MARK;
- e.setStatePStr(s);
- e.setStateCheck(snum);
- stk++;
- }
- }
-
protected final void pushAlt(int pat, int s, int prev) {
push(ALT, pat, s, prev);
}
@@ -294,19 +213,6 @@ abstract class StackMachine extends Matcher implements StackType {
stk++;
}
- protected final void pushCallFrame(int pat) {
- StackEntry e = ensure1();
- e.type = CALL_FRAME;
- e.setCallFrameRetAddr(pat);
- stk++;
- }
-
- protected final void pushReturn() {
- StackEntry e = ensure1();
- e.type = RETURN;
- stk++;
- }
-
// stack debug routines here
// ...
@@ -331,8 +237,6 @@ abstract class StackMachine extends Matcher implements StackType {
if ((e.type & MASK_POP_USED) != 0) {
return e;
- } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- if (e.type == STATE_CHECK_MARK) stateCheckMark();
}
}
}
@@ -346,8 +250,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_START) {
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
- } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- if (e.type == STATE_CHECK_MARK) stateCheckMark();
}
}
}
@@ -368,8 +270,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_END) {
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
- } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- if (e.type == STATE_CHECK_MARK) stateCheckMark();
}
}
}
@@ -391,8 +291,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_END){
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemStart();
- } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- if (e.type == STATE_CHECK_MARK) stateCheckMark();
}
}
}
@@ -414,8 +312,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_END) {
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
- } else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
- if (e.type == STATE_CHECK_MARK) stateCheckMark();
}
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
index 07b52626eda..518a416e7fb 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
@@ -609,7 +609,7 @@ public final class Syntax implements SyntaxProperties{
OP_ESC_CONTROL_CHARS | OP_ESC_C_CONTROL | OP_ESC_X_HEX2)
& ~OP_ESC_LTGT_WORD_BEGIN_END ),
- ( OP2_QMARK_GROUP_EFFECT | OP2_CCLASS_SET_OP |
+ ( OP2_QMARK_GROUP_EFFECT |
OP2_ESC_V_VTAB | OP2_ESC_U_HEX4 ),
( GNU_REGEX_BV | DIFFERENT_LEN_ALT_LOOK_BEHIND ),
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/UnsetAddrList.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/UnsetAddrList.java
deleted file mode 100644
index ca72e16742f..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/UnsetAddrList.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni;
-
-import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
-import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
-
-public final class UnsetAddrList {
- int num;
- Node[]targets;
- int[]offsets;
-
- public UnsetAddrList(int size) {
- targets = new Node[size];
- offsets = new int[size];
- }
-
- public void add(int offset, Node node) {
- if (num >= offsets.length) {
- Node []ttmp = new Node[targets.length << 1];
- System.arraycopy(targets, 0, ttmp, 0, num);
- targets = ttmp;
- int[]otmp = new int[offsets.length << 1];
- System.arraycopy(offsets, 0, otmp, 0, num);
- offsets = otmp;
- }
- targets[num] = node;
- offsets[num] = offset;
-
- num++;
- }
-
- public void fix(Regex regex) {
- for (int i=0; i 0) {
- for (int i=0; i set, WarnCallback warnings) {
- if (target == null || target.parent == this)
- warnings.warn(this.getAddressName() + " doesn't point to a target or the target has been stolen");
- // do not recurse here
- }
-
- @Override
- public String toString(int level) {
- StringBuilder value = new StringBuilder(super.toString(level));
- value.append("\n name: " + new String(name, nameP, nameEnd - nameP));
- value.append("\n groupNum: " + groupNum);
- value.append("\n target: " + pad(target.getAddressName(), level + 1));
- value.append("\n unsetAddrList: " + pad(unsetAddrList, level + 1));
-
- return value.toString();
- }
-
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
index a60afb1d1d6..1c5bfe7d89d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
@@ -25,7 +25,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType;
public final class EncloseNode extends StateNode implements EncloseType {
- public int type; // enclose type
+ public final int type; // enclose type
public int regNum;
public int option;
public Node target; /* EncloseNode : ENCLOSE_MEMORY */
@@ -42,10 +42,8 @@ public final class EncloseNode extends StateNode implements EncloseType {
}
// node_new_enclose_memory
- public EncloseNode(int option, boolean isNamed) {
+ public EncloseNode() {
this(MEMORY);
- if (isNamed) setNamedGroup();
- if (Config.USE_SUBEXP_CALL) this.option = option;
}
// node_new_option
@@ -104,46 +102,14 @@ public final class EncloseNode extends StateNode implements EncloseType {
return types.toString();
}
- public void setEncloseStatus(int flag) {
- state |= flag;
- }
-
- public void clearEncloseStatus(int flag) {
- state &= ~flag;
- }
-
- public void clearMemory() {
- type &= ~MEMORY;
- }
-
- public void setMemory() {
- type |= MEMORY;
- }
-
public boolean isMemory() {
return (type & MEMORY) != 0;
}
- public void clearOption() {
- type &= ~OPTION;
- }
-
- public void setOption() {
- type |= OPTION;
- }
-
public boolean isOption() {
return (type & OPTION) != 0;
}
- public void clearStopBacktrack() {
- type &= ~STOP_BACKTRACK;
- }
-
- public void setStopBacktrack() {
- type |= STOP_BACKTRACK;
- }
-
public boolean isStopBacktrack() {
return (type & STOP_BACKTRACK) != 0;
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
index 26cde98506f..c87de29d74a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
@@ -21,9 +21,10 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.Config;
import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
-import jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce;
import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.*;
+
public final class QuantifierNode extends StateNode {
public Node target;
@@ -37,8 +38,33 @@ public final class QuantifierNode extends StateNode {
public Node nextHeadExact;
public boolean isRefered; /* include called node. don't eliminate even if {0} */
- // USE_COMBINATION_EXPLOSION_CHECK
- public int combExpCheckNum; /* 1,2,3...: check, 0: no check */
+ enum ReduceType {
+ ASIS, /* as is */
+ DEL, /* delete parent */
+ A, /* to '*' */
+ AQ, /* to '*?' */
+ QQ, /* to '??' */
+ P_QQ, /* to '+)??' */
+ PQ_Q, /* to '+?)?' */
+ }
+
+ private final static ReduceType[][] REDUCE_TABLE = {
+ {DEL, A, A, QQ, AQ, ASIS}, /* '?' */
+ {DEL, DEL, DEL, P_QQ, P_QQ, DEL}, /* '*' */
+ {A, A, DEL, ASIS, P_QQ, DEL}, /* '+' */
+ {DEL, AQ, AQ, DEL, AQ, AQ}, /* '??' */
+ {DEL, DEL, DEL, DEL, DEL, DEL}, /* '*?' */
+ {ASIS, PQ_Q, DEL, AQ, AQ, DEL} /* '+?' */
+ };
+
+ private final static String PopularQStr[] = new String[] {
+ "?", "*", "+", "??", "*?", "+?"
+ };
+
+ private final static String ReduceQStr[]= new String[] {
+ "", "", "*", "*?", "??", "+ and ??", "+? and ?"
+ };
+
public QuantifierNode(int lower, int upper, boolean byNumber) {
this.lower = lower;
@@ -92,7 +118,6 @@ public final class QuantifierNode extends StateNode {
value.append("\n headExact: " + pad(headExact, level + 1));
value.append("\n nextHeadExact: " + pad(nextHeadExact, level + 1));
value.append("\n isRefered: " + isRefered);
- value.append("\n combExpCheckNum: " + combExpCheckNum);
return value.toString();
}
@@ -134,7 +159,6 @@ public final class QuantifierNode extends StateNode {
headExact = other.headExact;
nextHeadExact = other.nextHeadExact;
isRefered = other.isRefered;
- combExpCheckNum = other.combExpCheckNum;
}
public void reduceNestedQuantifier(QuantifierNode other) {
@@ -143,7 +167,7 @@ public final class QuantifierNode extends StateNode {
if (pnum < 0 || cnum < 0) return;
- switch(Reduce.REDUCE_TABLE[cnum][pnum]) {
+ switch(REDUCE_TABLE[cnum][pnum]) {
case DEL:
// no need to set the parent here...
// swap ?
@@ -226,7 +250,7 @@ public final class QuantifierNode extends StateNode {
if (Config.USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR) {
if (!isByNumber() && !qnt.isByNumber() && env.syntax.warnReduntantNestedRepeat()) {
- switch(Reduce.REDUCE_TABLE[targetQNum][nestQNum]) {
+ switch(REDUCE_TABLE[targetQNum][nestQNum]) {
case ASIS:
break;
@@ -237,9 +261,9 @@ public final class QuantifierNode extends StateNode {
default:
env.reg.getWarnings().warn(new String(chars, p, end) +
- " nested repeat operator " + Reduce.PopularQStr[targetQNum] +
- " and " + Reduce.PopularQStr[nestQNum] + " was replaced with '" +
- Reduce.ReduceQStr[Reduce.REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
+ " nested repeat operator " + PopularQStr[targetQNum] +
+ " and " + PopularQStr[nestQNum] + " was replaced with '" +
+ ReduceQStr[REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
}
}
} // USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
index 18101a4aed4..3f75f8630a8 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
@@ -40,7 +40,6 @@ public abstract class StateNode extends Node implements NodeStatus {
if (isRecursion()) states.append("RECURSION ");
if (isCalled()) states.append("CALLED ");
if (isAddrFixed()) states.append("ADDR_FIXED ");
- if (isNamedGroup()) states.append("NAMED_GROUP ");
if (isNameRef()) states.append("NAME_REF ");
if (isInRepeat()) states.append("IN_REPEAT ");
if (isNestLevel()) states.append("NEST_LEVEL ");
@@ -57,10 +56,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MIN_FIXED;
}
- public void clearMinFixed() {
- state &= ~NST_MIN_FIXED;
- }
-
public boolean isMaxFixed() {
return (state & NST_MAX_FIXED) != 0;
}
@@ -69,10 +64,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MAX_FIXED;
}
- public void clearMaxFixed() {
- state &= ~NST_MAX_FIXED;
- }
-
public boolean isCLenFixed() {
return (state & NST_CLEN_FIXED) != 0;
}
@@ -81,10 +72,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_CLEN_FIXED;
}
- public void clearCLenFixed() {
- state &= ~NST_CLEN_FIXED;
- }
-
public boolean isMark1() {
return (state & NST_MARK1) != 0;
}
@@ -93,10 +80,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MARK1;
}
- public void clearMark1() {
- state &= ~NST_MARK1;
- }
-
public boolean isMark2() {
return (state & NST_MARK2) != 0;
}
@@ -117,10 +100,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MEM_BACKREFED;
}
- public void clearMemBackrefed() {
- state &= ~NST_MEM_BACKREFED;
- }
-
public boolean isStopBtSimpleRepeat() {
return (state & NST_STOP_BT_SIMPLE_REPEAT) != 0;
}
@@ -129,10 +108,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_STOP_BT_SIMPLE_REPEAT;
}
- public void clearStopBtSimpleRepeat() {
- state &= ~NST_STOP_BT_SIMPLE_REPEAT;
- }
-
public boolean isRecursion() {
return (state & NST_RECURSION) != 0;
}
@@ -141,10 +116,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_RECURSION;
}
- public void clearRecursion() {
- state &= ~NST_RECURSION;
- }
-
public boolean isCalled() {
return (state & NST_CALLED) != 0;
}
@@ -153,10 +124,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_CALLED;
}
- public void clearCAlled() {
- state &= ~NST_CALLED;
- }
-
public boolean isAddrFixed() {
return (state & NST_ADDR_FIXED) != 0;
}
@@ -165,22 +132,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_ADDR_FIXED;
}
- public void clearAddrFixed() {
- state &= ~NST_ADDR_FIXED;
- }
-
- public boolean isNamedGroup() {
- return (state & NST_NAMED_GROUP) != 0;
- }
-
- public void setNamedGroup() {
- state |= NST_NAMED_GROUP;
- }
-
- public void clearNamedGroup() {
- state &= ~NST_NAMED_GROUP;
- }
-
public boolean isNameRef() {
return (state & NST_NAME_REF) != 0;
}
@@ -189,10 +140,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_NAME_REF;
}
- public void clearNameRef() {
- state &= ~NST_NAME_REF;
- }
-
public boolean isInRepeat() {
return (state & NST_IN_REPEAT) != 0;
}
@@ -201,10 +148,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_IN_REPEAT;
}
- public void clearInRepeat() {
- state &= ~NST_IN_REPEAT;
- }
-
public boolean isNestLevel() {
return (state & NST_NEST_LEVEL) != 0;
}
@@ -213,10 +156,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_NEST_LEVEL;
}
- public void clearNestLevel() {
- state &= ~NST_NEST_LEVEL;
- }
-
public boolean isByNumber() {
return (state & NST_BY_NUMBER) != 0;
}
@@ -225,8 +164,4 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_BY_NUMBER;
}
- public void clearByNumber() {
- state &= ~NST_BY_NUMBER;
- }
-
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/AbstractBench.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/AbstractBench.java
deleted file mode 100644
index 9751b51d5c0..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/bench/AbstractBench.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package jdk.nashorn.internal.runtime.regexp.joni.bench;
-
-import jdk.nashorn.internal.runtime.regexp.joni.Option;
-import jdk.nashorn.internal.runtime.regexp.joni.Regex;
-import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
-
-public abstract class AbstractBench {
- protected void bench(String _reg, String _str, int warmup, int times) throws Exception {
- char[] reg = _reg.toCharArray();
- char[] str = _str.toCharArray();
-
- Regex p = new Regex(reg,0,reg.length,Option.DEFAULT,Syntax.DEFAULT);
-
- System.err.println("::: /" + _reg + "/ =~ \"" + _str + "\", " + warmup + " * " + times + " times");
-
- for(int j=0;j {
public T p;
- static final ObjPtr NULL = new ObjPtr();
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/PosixBracket.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/PosixBracket.java
deleted file mode 100644
index 48978bf48ee..00000000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/PosixBracket.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS".toCharArray(), WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package jdk.nashorn.internal.runtime.regexp.joni.encoding;
-
-import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
-import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
-
-import java.util.HashMap;
-
-public class PosixBracket {
-
- public static final char[][] PBSNamesLower = {
- "alnum".toCharArray(),
- "alpha".toCharArray(),
- "blank".toCharArray(),
- "cntrl".toCharArray(),
- "digit".toCharArray(),
- "graph".toCharArray(),
- "lower".toCharArray(),
- "print".toCharArray(),
- "punct".toCharArray(),
- "space".toCharArray(),
- "upper".toCharArray(),
- "xdigit".toCharArray(),
- "ascii".toCharArray(),
- "word".toCharArray()
- };
-
- public static final int PBSValues[] = {
- CharacterType.ALNUM,
- CharacterType.ALPHA,
- CharacterType.BLANK,
- CharacterType.CNTRL,
- CharacterType.DIGIT,
- CharacterType.GRAPH,
- CharacterType.LOWER,
- CharacterType.PRINT,
- CharacterType.PUNCT,
- CharacterType.SPACE,
- CharacterType.UPPER,
- CharacterType.XDIGIT,
- CharacterType.ASCII,
- CharacterType.WORD,
- };
-
- public static int propertyNameToCType(String name) {
- name = name.toLowerCase();
- if (!PBSTableUpper.containsKey(name)) {
- throw new JOniException(ErrorMessages.ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
- }
- return PBSTableUpper.get(name);
- }
-
- private static final HashMap PBSTableUpper = new HashMap();
-
- static {
- for (int i=0; i" : "invalid char in group number <%n>";
- final String ERR_UNDEFINED_NAME_REFERENCE = "undefined name <%n> reference";
- final String ERR_UNDEFINED_GROUP_REFERENCE = "undefined group <%n> reference";
- final String ERR_MULTIPLEX_DEFINED_NAME = "multiplex defined name <%n>";
- final String ERR_MULTIPLEX_DEFINITION_NAME_CALL = "multiplex definition name <%n> call";
- final String ERR_NEVER_ENDING_RECURSION = "never ending recursion";
+ final String ERR_INVALID_CHAR_IN_GROUP_NAME = "invalid char in group number <%n>";
final String ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY = "group number is too big for capture history";
- final String ERR_NOT_SUPPORTED_ENCODING_COMBINATION = "not supported encoding combination";
final String ERR_INVALID_COMBINATION_OF_OPTIONS = "invalid combination of options";
- final String ERR_OVER_THREAD_PASS_LIMIT_COUNT = "over thread pass limit count";
- final String ERR_TOO_BIG_SB_CHAR_VALUE = "too big singlebyte char value";
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
index d56a35a4190..597fe221572 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
@@ -30,8 +30,4 @@ public class ValueException extends SyntaxException{
super(message.replaceAll("%n", str));
}
- public ValueException(String message, byte[]bytes, int p, int end) {
- this(message, new String(bytes, p, end - p));
- }
-
}
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
new file mode 100644
index 00000000000..c22838fb277
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.runtime.regexp;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import jdk.nashorn.internal.runtime.ParserException;
+import org.testng.annotations.Test;
+
+/**
+ * Basic tests for the JDK based RegExp implementation.
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.regexp.JdkRegExpTest
+ */
+public class JdkRegExpTest {
+
+ /**
+ * Compile a regular expression using the JDK implementation
+ */
+ @Test
+ public void testMatcher() {
+ RegExp regexp = new RegExpFactory().compile("f(o)o", "");
+ RegExpMatcher matcher = regexp.match("foo");
+ assertNotNull(matcher);
+ assertTrue(matcher.search(0));
+ assertEquals(matcher.getInput(), "foo");
+ assertEquals(matcher.groupCount(), 1);
+ assertEquals(matcher.group(), "foo");
+ assertEquals(matcher.start(), 0);
+ assertEquals(matcher.end(), 3);
+ assertEquals(matcher.group(1), "o");
+ assertEquals(matcher.start(1), 1);
+ assertEquals(matcher.end(1), 2);
+ }
+}
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
new file mode 100644
index 00000000000..a6981c8dc8c
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.runtime.regexp.joni;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+
+/**
+ * Joni coverage tests
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.regexp.joni.JoniTest
+ */
+public class JoniTest {
+
+ @Test
+ public void testDump() {
+ new Regex("^a{3,}(.*)[z]++\\s\\1x$").dumpTree();
+ new Regex("^a{3,}(.*)[z]++\\s\\1x$").dumpByteCode();
+ new Regex("(abc){4,}{2,5}").dumpTree();
+ new Regex("(abc){4,}{2,5}").dumpByteCode();
+ new Regex("aaa|aa|bbbb|ccc").dumpTree();
+ new Regex("aaa|aa|bbbb|ccc").dumpByteCode();
+ new Regex("(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))").dumpTree();
+ new Regex("(?:ZFVR.(\\d+\\.\\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\\d+\\.\\d+))|(?:Bcren.(\\d+\\.\\d+))|(?:NccyrJroXvg.(\\d+(?:\\.\\d+)?))").dumpByteCode();
+ }
+}
From a8783e010fa95887b5d56795cdbe30f1e9240644 Mon Sep 17 00:00:00 2001
From: Dan Xu
Date: Fri, 17 May 2013 12:04:18 -0700
Subject: [PATCH 016/101] 8011136: FileInputStream.available and skip
inconsistencies
Correct the behavior of available() and update related java specs for available() and skip() in InputStream and FileInputStream classes.
Reviewed-by: alanb
---
.../classes/java/io/FileInputStream.java | 21 ++++++++------
.../share/classes/java/io/InputStream.java | 8 ++++--
.../share/native/java/io/FileInputStream.c | 4 ++-
.../FileInputStream/LargeFileAvailable.java | 28 ++++++++++---------
.../io/FileInputStream/NegativeAvailable.java | 19 ++++++++-----
5 files changed, 47 insertions(+), 33 deletions(-)
diff --git a/jdk/src/share/classes/java/io/FileInputStream.java b/jdk/src/share/classes/java/io/FileInputStream.java
index 740b6744047..90d1ad5cc3e 100644
--- a/jdk/src/share/classes/java/io/FileInputStream.java
+++ b/jdk/src/share/classes/java/io/FileInputStream.java
@@ -240,13 +240,15 @@ class FileInputStream extends InputStream
*
*
The skip method may, for a variety of
* reasons, end up skipping over some smaller number of bytes,
- * possibly 0. If n is negative, an
- * IOException is thrown, even though the skip
- * method of the {@link InputStream} superclass does nothing in this case.
- * The actual number of bytes skipped is returned.
+ * possibly 0. If n is negative, the method
+ * will try to skip backwards. In case the backing file does not support
+ * backward skip at its current position, an IOException is
+ * thrown. The actual number of bytes skipped is returned. If it skips
+ * forwards, it returns a positive value. If it skips backwards, it
+ * returns a negative value.
*
- *
This method may skip more bytes than are remaining in the backing
- * file. This produces no exception and the number of bytes skipped
+ *
This method may skip more bytes than what are remaining in the
+ * backing file. This produces no exception and the number of bytes skipped
* may include some number of bytes that were beyond the EOF of the
* backing file. Attempting to read from the stream after skipping past
* the end will result in -1 indicating the end of the file.
@@ -261,9 +263,10 @@ class FileInputStream extends InputStream
/**
* Returns an estimate of the number of remaining bytes that can be read (or
* skipped over) from this input stream without blocking by the next
- * invocation of a method for this input stream. The next invocation might be
- * the same thread or another thread. A single read or skip of this
- * many bytes will not block, but may read or skip fewer bytes.
+ * invocation of a method for this input stream. Returns 0 when the file
+ * position is beyond EOF. The next invocation might be the same thread
+ * or another thread. A single read or skip of this many bytes will not
+ * block, but may read or skip fewer bytes.
*
*
In some cases, a non-blocking read (or skip) may appear to be
* blocked when it is merely slow, for example when reading large
diff --git a/jdk/src/share/classes/java/io/InputStream.java b/jdk/src/share/classes/java/io/InputStream.java
index cb61314b01d..3c7ff17f609 100644
--- a/jdk/src/share/classes/java/io/InputStream.java
+++ b/jdk/src/share/classes/java/io/InputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -193,8 +193,10 @@ public abstract class InputStream implements Closeable {
* up skipping over some smaller number of bytes, possibly 0.
* This may result from any of a number of conditions; reaching end of file
* before n bytes have been skipped is only one possibility.
- * The actual number of bytes skipped is returned. If n is
- * negative, no bytes are skipped.
+ * The actual number of bytes skipped is returned. If {@code n} is
+ * negative, the {@code skip} method for class {@code InputStream} always
+ * returns 0, and no bytes are skipped. Subclasses may handle the negative
+ * value differently.
*
*
The skip method of this class creates a
* byte array and then repeatedly reads into it until n bytes
diff --git a/jdk/src/share/native/java/io/FileInputStream.c b/jdk/src/share/native/java/io/FileInputStream.c
index 37deaf84efb..52e2cdd8e6b 100644
--- a/jdk/src/share/native/java/io/FileInputStream.c
+++ b/jdk/src/share/native/java/io/FileInputStream.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -100,6 +100,8 @@ Java_java_io_FileInputStream_available(JNIEnv *env, jobject this) {
if (IO_Available(fd, &ret)) {
if (ret > INT_MAX) {
ret = (jlong) INT_MAX;
+ } else if (ret < 0) {
+ ret = 0;
}
return jlong_to_jint(ret);
}
diff --git a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java
index 90eed30d1dc..94f6f856c2a 100644
--- a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java
+++ b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6402006 7030573
+ * @bug 6402006 7030573 8011136
* @summary Test if available returns correct value when reading
* a large file.
*/
@@ -61,9 +61,12 @@ public class LargeFileAvailable {
remaining -= skipBytes(fis, bigSkip, remaining);
remaining -= skipBytes(fis, 10L, remaining);
remaining -= skipBytes(fis, bigSkip, remaining);
- if (fis.available() != (int) remaining) {
- throw new RuntimeException("available() returns "
- + fis.available() + " but expected " + remaining);
+ int expected = (remaining >= Integer.MAX_VALUE)
+ ? Integer.MAX_VALUE
+ : (remaining > 0 ? (int) remaining : 0);
+ if (fis.available() != expected) {
+ throw new RuntimeException("available() returns "
+ + fis.available() + " but expected " + expected);
}
} finally {
file.delete();
@@ -77,19 +80,18 @@ public class LargeFileAvailable {
long skip = is.skip(toSkip);
if (skip != toSkip) {
throw new RuntimeException("skip() returns " + skip
- + " but expected " + toSkip);
+ + " but expected " + toSkip);
}
long remaining = avail - skip;
- int expected = remaining >= Integer.MAX_VALUE
- ? Integer.MAX_VALUE
- : (int) remaining;
+ int expected = (remaining >= Integer.MAX_VALUE)
+ ? Integer.MAX_VALUE
+ : (remaining > 0 ? (int) remaining : 0);
- System.out.println("Skipped " + skip + " bytes "
- + " available() returns " + expected +
- " remaining=" + remaining);
+ System.out.println("Skipped " + skip + " bytes, available() returns "
+ + expected + ", remaining " + remaining);
if (is.available() != expected) {
throw new RuntimeException("available() returns "
- + is.available() + " but expected " + expected);
+ + is.available() + " but expected " + expected);
}
return skip;
}
diff --git a/jdk/test/java/io/FileInputStream/NegativeAvailable.java b/jdk/test/java/io/FileInputStream/NegativeAvailable.java
index a4dedbcdcf7..a0e0e999231 100644
--- a/jdk/test/java/io/FileInputStream/NegativeAvailable.java
+++ b/jdk/test/java/io/FileInputStream/NegativeAvailable.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8010837
+ * @bug 8010837 8011136
* @summary Test if available returns correct value when skipping beyond
* the end of a file.
* @author Dan Xu
@@ -42,6 +42,7 @@ public class NegativeAvailable {
public static void main(String[] args) throws IOException {
final int SIZE = 10;
final int SKIP = 5;
+ final int NEGATIVE_SKIP = -5;
// Create a temporary file with size of 10 bytes.
Path tmp = Files.createTempFile(null, null);
@@ -56,12 +57,15 @@ public class NegativeAvailable {
try (FileInputStream fis = new FileInputStream(tempFile)) {
if (tempFile.length() != SIZE) {
throw new RuntimeException("unexpected file size = "
- + tempFile.length());
+ + tempFile.length());
}
long space = skipBytes(fis, SKIP, SIZE);
+ space = skipBytes(fis, NEGATIVE_SKIP, space);
space = skipBytes(fis, SKIP, space);
space = skipBytes(fis, SKIP, space);
space = skipBytes(fis, SKIP, space);
+ space = skipBytes(fis, NEGATIVE_SKIP, space);
+ space = skipBytes(fis, NEGATIVE_SKIP, space);
}
Files.deleteIfExists(tmp);
}
@@ -74,17 +78,18 @@ public class NegativeAvailable {
long skip = fis.skip(toSkip);
if (skip != toSkip) {
throw new RuntimeException("skip() returns " + skip
- + " but expected " + toSkip);
+ + " but expected " + toSkip);
}
- long remaining = space - toSkip;
+ long newSpace = space - toSkip;
+ long remaining = newSpace > 0 ? newSpace : 0;
int avail = fis.available();
if (avail != remaining) {
throw new RuntimeException("available() returns " + avail
- + " but expected " + remaining);
+ + " but expected " + remaining);
}
System.out.println("Skipped " + skip + " bytes "
- + " available() returns " + avail);
- return remaining;
+ + " available() returns " + avail);
+ return newSpace;
}
}
From aab6997ce09c3c27fe6567edaa4a692e68160ec0 Mon Sep 17 00:00:00 2001
From: Weijun Wang
Date: Sat, 18 May 2013 10:15:06 +0800
Subject: [PATCH 017/101] 8012261: update policytool to support
java.net.HttpURLPermission
Reviewed-by: mullan
---
.../sun/security/tools/policytool/PolicyTool.java | 15 +++++++++++++++
.../sun/security/tools/policytool/Resources.java | 3 +++
2 files changed, 18 insertions(+)
diff --git a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java
index 17f9d9c5278..9a325e5ac2e 100644
--- a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java
+++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java
@@ -1447,6 +1447,7 @@ class ToolDialog extends Dialog {
PERM_ARRAY.add(new AWTPerm());
PERM_ARRAY.add(new DelegationPerm());
PERM_ARRAY.add(new FilePerm());
+ PERM_ARRAY.add(new HttpURLPerm());
PERM_ARRAY.add(new InqSecContextPerm());
PERM_ARRAY.add(new LogPerm());
PERM_ARRAY.add(new MgmtPerm());
@@ -3842,6 +3843,20 @@ class FilePerm extends Perm {
}
}
+class HttpURLPerm extends Perm {
+ public HttpURLPerm() {
+ super("HttpURLPermission",
+ "java.net.HttpURLPermission",
+ new String[] {
+ "<"+ PolicyTool.rb.getString("url") + ">",
+ },
+ new String[] {
+ "<" + PolicyTool.rb.getString("method.list") + ">:<"
+ + PolicyTool.rb.getString("request.headers.list") + ">",
+ });
+ }
+}
+
class InqSecContextPerm extends Perm {
public InqSecContextPerm() {
super("InquireSecContextPermission",
diff --git a/jdk/src/share/classes/sun/security/tools/policytool/Resources.java b/jdk/src/share/classes/sun/security/tools/policytool/Resources.java
index c155dcea92b..b24f7b03a4a 100644
--- a/jdk/src/share/classes/sun/security/tools/policytool/Resources.java
+++ b/jdk/src/share/classes/sun/security/tools/policytool/Resources.java
@@ -139,6 +139,9 @@ public class Resources extends java.util.ListResourceBundle {
{"policy.type", "policy type"},
{"property.name", "property name"},
{"provider.name", "provider name"},
+ {"url", "url"},
+ {"method.list", "method list"},
+ {"request.headers.list", "request headers list"},
{"Principal.List", "Principal List"},
{"Permission.List", "Permission List"},
{"Code.Base", "Code Base"},
From 2548b20c9ef9c42b97a36dd02626615a412ea0fb Mon Sep 17 00:00:00 2001
From: Peter Levart
Date: Fri, 17 May 2013 14:41:39 +0200
Subject: [PATCH 018/101] 8014477: (str) Race condition in String.contentEquals
when comparing with StringBuffer
Reviewed-by: alanb, mduigou, dholmes
---
jdk/src/share/classes/java/lang/String.java | 23 ++--
.../lang/String/StringContentEqualsBug.java | 107 ++++++++++++++++++
2 files changed, 119 insertions(+), 11 deletions(-)
create mode 100644 jdk/test/java/lang/String/StringContentEqualsBug.java
diff --git a/jdk/src/share/classes/java/lang/String.java b/jdk/src/share/classes/java/lang/String.java
index c738a9eb619..748c8a4bbef 100644
--- a/jdk/src/share/classes/java/lang/String.java
+++ b/jdk/src/share/classes/java/lang/String.java
@@ -1010,13 +1010,14 @@ public final class String
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
char v1[] = value;
char v2[] = sb.getValue();
- int i = 0;
- int n = value.length;
- while (n-- != 0) {
+ int n = v1.length;
+ if (n != sb.length()) {
+ return false;
+ }
+ for (int i = 0; i < n; i++) {
if (v1[i] != v2[i]) {
return false;
}
- i++;
}
return true;
}
@@ -1038,8 +1039,6 @@ public final class String
* @since 1.5
*/
public boolean contentEquals(CharSequence cs) {
- if (value.length != cs.length())
- return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
@@ -1055,12 +1054,14 @@ public final class String
return true;
// Argument is a generic CharSequence
char v1[] = value;
- int i = 0;
- int n = value.length;
- while (n-- != 0) {
- if (v1[i] != cs.charAt(i))
+ int n = v1.length;
+ if (n != cs.length()) {
+ return false;
+ }
+ for (int i = 0; i < n; i++) {
+ if (v1[i] != cs.charAt(i)) {
return false;
- i++;
+ }
}
return true;
}
diff --git a/jdk/test/java/lang/String/StringContentEqualsBug.java b/jdk/test/java/lang/String/StringContentEqualsBug.java
new file mode 100644
index 00000000000..660d8d7eea3
--- /dev/null
+++ b/jdk/test/java/lang/String/StringContentEqualsBug.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8014477
+ * @summary test String.contentEquals(StringBuffer)
+ */
+public class StringContentEqualsBug {
+
+ static abstract class Task extends Thread {
+ volatile StringBuffer sb;
+ volatile Exception exception;
+
+ Task(StringBuffer sb) {
+ this.sb = sb;
+ }
+
+ @Override
+ public void run() {
+ try {
+ StringBuffer sb;
+ while ((sb = this.sb) != null) {
+ doWith(sb);
+ }
+ }
+ catch (Exception e) {
+ exception = e;
+ }
+ }
+
+ protected abstract void doWith(StringBuffer sb);
+ }
+
+ static class Tester extends Task {
+ Tester(StringBuffer sb) {
+ super(sb);
+ }
+
+ @Override
+ protected void doWith(StringBuffer sb) {
+ "AA".contentEquals(sb);
+ }
+ }
+
+ static class Disturber extends Task {
+ Disturber(StringBuffer sb) {
+ super(sb);
+ }
+
+ @Override
+ protected void doWith(StringBuffer sb) {
+ sb.setLength(0);
+ sb.trimToSize();
+ sb.append("AA");
+ }
+ }
+
+
+ public static void main(String[] args) throws Exception {
+ StringBuffer sb = new StringBuffer();
+ Task[] tasks = new Task[3];
+ (tasks[0] = new Tester(sb)).start();
+ for (int i = 1; i < tasks.length; i++) {
+ (tasks[i] = new Disturber(sb)).start();
+ }
+
+ try
+ {
+ // wait at most 5 seconds for any of the threads to throw exception
+ for (int i = 0; i < 20; i++) {
+ for (Task task : tasks) {
+ if (task.exception != null) {
+ throw task.exception;
+ }
+ }
+ Thread.sleep(250L);
+ }
+ }
+ finally {
+ for (Task task : tasks) {
+ task.sb = null;
+ task.join();
+ }
+ }
+ }
+}
From 0ad376b3a8e0ca48aa6a9a4f9a9a23db6666b7be Mon Sep 17 00:00:00 2001
From: Johnny Chen
Date: Fri, 17 May 2013 10:04:39 -0700
Subject: [PATCH 019/101] 8003444: Fix potential NULL pointer dereference
Reviewed-by: jgodinez, prr
---
jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c | 2 ++
jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c
index 15a2439448e..bf5015604a7 100644
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c
@@ -634,6 +634,8 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer)
cmsFloat64Number dnum = 0.0;
int sign = 1;
+ if (Buffer == NULL) return 0.0;
+
if (*Buffer == '-' || *Buffer == '+') {
sign = (*Buffer == '-') ? -1 : 1;
diff --git a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c
index 76b14238bf7..6fc76a8b919 100644
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c
@@ -1021,6 +1021,8 @@ cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID)
mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
cmsFreeToneCurveTriple(LabTable);
+ if (mpe == NULL) return NULL;
+
mpe ->Implements = cmsSigLabV2toV4;
return mpe;
}
From e0fcb74c7e43171e3425503ba4e250b2884d6b26 Mon Sep 17 00:00:00 2001
From: Konstantin Shefov
Date: Fri, 17 May 2013 16:44:22 -0300
Subject: [PATCH 020/101] 8014823: Reprise - Smoke test fail: Windows
JDK-8008554.js - access denied ("java.io.FilePermission"
"//C/aurora/sandbox/nashorn~source/test/script/basic/NASHORN-99.js" "read")
Reviewed-by: jlaskey
---
nashorn/test/script/basic/JDK-8008554.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nashorn/test/script/basic/JDK-8008554.js b/nashorn/test/script/basic/JDK-8008554.js
index 0cbe8b8e699..f8ec9587c34 100644
--- a/nashorn/test/script/basic/JDK-8008554.js
+++ b/nashorn/test/script/basic/JDK-8008554.js
@@ -32,5 +32,5 @@
var dir = __DIR__;
var file = __FILE__.replace("JDK-8008554", "NASHORN-99");
load(file);
-file = "file://" + __DIR__ + "NASHORN-99.js";
+file = "file:///" + __DIR__ + "NASHORN-99.js";
load(file);
From cc79bd12371e6df1dc416992e9ca01a5f989ae2d Mon Sep 17 00:00:00 2001
From: Marcus Lagergren
Date: Mon, 20 May 2013 16:38:38 +0200
Subject: [PATCH 021/101] 8006069: Range analysis first iteration, runtime
specializations
Reviewed-by: jlaskey, sundar
---
.../internal/codegen/CompilationPhase.java | 94 ++-
.../nashorn/internal/codegen/Compiler.java | 7 +-
.../internal/codegen/CompilerConstants.java | 2 +-
.../internal/codegen/MethodEmitter.java | 9 +-
.../internal/codegen/RangeAnalyzer.java | 474 ++++++++++++
.../nashorn/internal/codegen/types/Range.java | 705 ++++++++++++++++++
.../nashorn/internal/codegen/types/Type.java | 12 +-
.../jdk/nashorn/internal/ir/BinaryNode.java | 17 +
.../jdk/nashorn/internal/ir/FunctionNode.java | 2 +-
.../nashorn/internal/ir/LexicalContext.java | 20 +-
nashorn/src/jdk/nashorn/internal/ir/Node.java | 8 +
.../src/jdk/nashorn/internal/ir/Symbol.java | 33 +-
.../internal/runtime/CompiledFunction.java | 32 +-
.../runtime/FinalScriptFunctionData.java | 4 +-
.../RecompilableScriptFunctionData.java | 236 ++++--
.../internal/runtime/ScriptEnvironment.java | 6 +-
.../internal/runtime/ScriptFunctionData.java | 5 +-
.../runtime/resources/Options.properties | 6 +
nashorn/test/script/basic/ranges_disabled.js | 32 +
.../script/basic/ranges_disabled.js.EXPECTED | 4 +
nashorn/test/script/basic/ranges_enabled.js | 33 +
.../script/basic/ranges_enabled.js.EXPECTED | 4 +
nashorn/test/script/basic/ranges_payload.js | 74 ++
23 files changed, 1720 insertions(+), 99 deletions(-)
create mode 100644 nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
create mode 100644 nashorn/src/jdk/nashorn/internal/codegen/types/Range.java
create mode 100644 nashorn/test/script/basic/ranges_disabled.js
create mode 100644 nashorn/test/script/basic/ranges_disabled.js.EXPECTED
create mode 100644 nashorn/test/script/basic/ranges_enabled.js
create mode 100644 nashorn/test/script/basic/ranges_enabled.js.EXPECTED
create mode 100644 nashorn/test/script/basic/ranges_payload.js
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
index bfc71cc2198..f2603393612 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
@@ -11,13 +11,21 @@ import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
+
+import jdk.nashorn.internal.codegen.types.Range;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.CallNode;
import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.ReturnNode;
+import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.Node;
@@ -174,7 +182,7 @@ enum CompilationPhase {
FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
final TemporarySymbols ts = compiler.getTemporarySymbols();
final FunctionNode newFunctionNode = (FunctionNode)enterAttr(fn, ts).accept(new Attr(ts));
- if(compiler.getEnv()._print_mem_usage) {
+ if (compiler.getEnv()._print_mem_usage) {
Compiler.LOG.info("Attr temporary symbol count: " + ts.getTotalSymbolCount());
}
return newFunctionNode;
@@ -207,6 +215,89 @@ enum CompilationPhase {
}
},
+ /*
+ * Range analysis
+ * Conservatively prove that certain variables can be narrower than
+ * the most generic number type
+ */
+ RANGE_ANALYSIS_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
+ @Override
+ FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
+ if (!compiler.getEnv()._range_analysis) {
+ return fn;
+ }
+
+ FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer());
+ final List returns = new ArrayList<>();
+
+ newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor() {
+ private final Deque> returnStack = new ArrayDeque<>();
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ returnStack.push(new ArrayList());
+ return true;
+ }
+
+ @Override
+ public Node leaveFunctionNode(final FunctionNode functionNode) {
+ Type returnType = Type.UNKNOWN;
+ for (final ReturnNode ret : returnStack.pop()) {
+ if (ret.getExpression() == null) {
+ returnType = Type.OBJECT;
+ break;
+ }
+ returnType = Type.widest(returnType, ret.getExpression().getType());
+ }
+ return functionNode.setReturnType(getLexicalContext(), returnType);
+ }
+
+ @Override
+ public Node leaveReturnNode(final ReturnNode returnNode) {
+ final ReturnNode result = (ReturnNode)leaveDefault(returnNode);
+ returns.add(result);
+ return result;
+ }
+
+ @Override
+ public Node leaveDefault(final Node node) {
+ final Symbol symbol = node.getSymbol();
+ if (symbol != null) {
+ final Range range = symbol.getRange();
+ final Type symbolType = symbol.getSymbolType();
+ if (!symbolType.isNumeric()) {
+ return node;
+ }
+ final Type rangeType = range.getType();
+ if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
+ RangeAnalyzer.LOG.info("[", getLexicalContext().getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
+ return node.setSymbol(getLexicalContext(), symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
+ }
+ }
+ return node;
+ }
+ });
+
+ Type returnType = Type.UNKNOWN;
+ for (final ReturnNode node : returns) {
+ if (node.getExpression() != null) {
+ returnType = Type.widest(returnType, node.getExpression().getType());
+ } else {
+ returnType = Type.OBJECT;
+ break;
+ }
+ }
+
+ return newFunctionNode.setReturnType(null, returnType);
+ }
+
+ @Override
+ public String toString() {
+ return "[Range Analysis]";
+ }
+ },
+
+
/*
* Splitter Split the AST into several compile units based on a size
* heuristic Splitter needs attributed AST for weight calculations (e.g. is
@@ -218,7 +309,6 @@ enum CompilationPhase {
FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName());
-// assert fn.isProgram() ;
final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn);
assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
index 81a76186ce8..faf7a3c5a09 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
@@ -99,7 +99,7 @@ public final class Compiler {
private boolean strict;
- private CodeInstaller installer;
+ private final CodeInstaller installer;
private final TemporarySymbols temporarySymbols = new TemporarySymbols();
@@ -219,6 +219,7 @@ public final class Compiler {
CompilationPhase.CONSTANT_FOLDING_PHASE,
CompilationPhase.LOWERING_PHASE,
CompilationPhase.ATTRIBUTION_PHASE,
+ CompilationPhase.RANGE_ANALYSIS_PHASE,
CompilationPhase.SPLITTING_PHASE,
CompilationPhase.TYPE_FINALIZATION_PHASE,
CompilationPhase.BYTECODE_GENERATION_PHASE);
@@ -384,6 +385,8 @@ public final class Compiler {
if (info) {
final StringBuilder sb = new StringBuilder();
sb.append("Compile job for '").
+ append(newFunctionNode.getSource()).
+ append(':').
append(newFunctionNode.getName()).
append("' finished");
@@ -487,7 +490,7 @@ public final class Compiler {
}
if (sb != null) {
- LOG.info(sb);
+ LOG.fine(sb);
}
return rootClass;
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
index 6912534dee6..d9c68ad8288 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
@@ -262,7 +262,7 @@ public enum CompilerConstants {
* @return the internal descriptor for this type
*/
public static String typeDescriptor(final Class> clazz) {
- return Type.getDescriptor(clazz);
+ return Type.typeFor(clazz).getDescriptor();
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
index c156c865f69..4e07c4777dc 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
@@ -2081,7 +2081,9 @@ public class MethodEmitter implements Emitter {
* @param args debug information to print
*/
private void debug(final Object... args) {
- debug(30, args);
+ if (DEBUG) {
+ debug(30, args);
+ }
}
/**
@@ -2091,7 +2093,9 @@ public class MethodEmitter implements Emitter {
* @param args debug information to print
*/
private void debug_label(final Object... args) {
- debug(26, args);
+ if (DEBUG) {
+ debug(22, args);
+ }
}
private void debug(final int padConstant, final Object... args) {
@@ -2164,7 +2168,6 @@ public class MethodEmitter implements Emitter {
new Throwable().printStackTrace(LOG.getOutputStream());
}
}
-
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
new file mode 100644
index 00000000000..1229caa1fea
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
@@ -0,0 +1,474 @@
+/*
+ * 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.codegen;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import jdk.nashorn.internal.codegen.types.Range;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Assignment;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
+import jdk.nashorn.internal.ir.LoopNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.RuntimeNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.DebugLogger;
+
+/**
+ * Range analysis and narrowing of type where it can be proven
+ * that there is no spillover, e.g.
+ *
+ * function func(c) {
+ * var v = c & 0xfff;
+ * var w = c & 0xeee;
+ * var x = v * w;
+ * return x;
+ * }
+ *
+ * Proves that the multiplication never exceeds 24 bits and can thus be an int
+ */
+final class RangeAnalyzer extends NodeOperatorVisitor {
+ static final DebugLogger LOG = new DebugLogger("ranges");
+
+ private static final Range.Functionality RANGE = new Range.Functionality(LOG);
+
+ private final Map loopCounters = new HashMap<>();
+
+ RangeAnalyzer() {
+ }
+
+ @Override
+ public boolean enterForNode(final ForNode forNode) {
+ //conservatively attempt to identify the loop counter. Null means that it wasn't
+ //properly identified and that no optimizations can be made with it - its range is
+ //simply unknown in that case, if it is assigned in the loop
+ final Symbol counter = findLoopCounter(forNode);
+ LOG.fine("Entering forNode " + forNode + " counter = " + counter);
+ if (counter != null && !assignedInLoop(forNode, counter)) {
+ loopCounters.put(forNode, counter);
+ }
+ return true;
+ }
+
+ //destination visited
+ private Symbol setRange(final Node dest, final Range range) {
+ if (range.isUnknown()) {
+ return null;
+ }
+
+ final Symbol symbol = dest.getSymbol();
+ assert symbol != null : dest + " " + dest.getClass() + " has no symbol";
+ assert symbol.getRange() != null : symbol + " has no range";
+ final Range symRange = RANGE.join(symbol.getRange(), range);
+
+ //anything assigned in the loop, not being the safe loop counter(s) invalidates its entire range
+ if (getLexicalContext().inLoop() && !isLoopCounter(getLexicalContext().getCurrentLoop(), symbol)) {
+ symbol.setRange(Range.createGenericRange());
+ return symbol;
+ }
+
+ if (!symRange.equals(symbol.getRange())) {
+ LOG.fine("Modify range for " + dest + " " + symbol + " from " + symbol.getRange() + " to " + symRange + " (in node = " + dest + ")" );
+ symbol.setRange(symRange);
+ }
+
+ return null;
+ }
+
+ @Override
+ public Node leaveADD(final BinaryNode node) {
+ setRange(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveSUB(final BinaryNode node) {
+ setRange(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveMUL(final BinaryNode node) {
+ setRange(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveDIV(final BinaryNode node) {
+ setRange(node, RANGE.div(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveMOD(final BinaryNode node) {
+ setRange(node, RANGE.mod(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveBIT_AND(final BinaryNode node) {
+ setRange(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveBIT_OR(final BinaryNode node) {
+ setRange(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveBIT_XOR(final BinaryNode node) {
+ setRange(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveSAR(final BinaryNode node) {
+ setRange(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveSHL(final BinaryNode node) {
+ setRange(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveSHR(final BinaryNode node) {
+ setRange(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ private Node leaveCmp(final BinaryNode node) {
+ setRange(node, Range.createTypeRange(Type.BOOLEAN));
+ return node;
+ }
+
+ @Override
+ public Node leaveEQ(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveEQ_STRICT(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveNE(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveNE_STRICT(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveLT(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveLE(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveGT(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveGE(final BinaryNode node) {
+ return leaveCmp(node);
+ }
+
+ @Override
+ public Node leaveASSIGN(final BinaryNode node) {
+ Range range = node.rhs().getSymbol().getRange();
+ if (range.isUnknown()) {
+ range = Range.createGenericRange();
+ }
+
+ setRange(node.lhs(), range);
+ setRange(node, range);
+
+ return node;
+ }
+
+ private Node leaveSelfModifyingAssign(final BinaryNode node, final Range range) {
+ setRange(node.lhs(), range);
+ setRange(node, range);
+ return node;
+ }
+
+ private Node leaveSelfModifyingAssign(final UnaryNode node, final Range range) {
+ setRange(node.rhs(), range);
+ setRange(node, range);
+ return node;
+ }
+
+ @Override
+ public Node leaveASSIGN_ADD(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_SUB(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_MUL(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_DIV(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
+ }
+
+ @Override
+ public Node leaveASSIGN_MOD(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
+ }
+
+ @Override
+ public Node leaveASSIGN_BIT_AND(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_BIT_OR(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_BIT_XOR(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_SAR(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_SHR(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveASSIGN_SHL(final BinaryNode node) {
+ return leaveSelfModifyingAssign(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
+ }
+
+ @Override
+ public Node leaveDECINC(final UnaryNode node) {
+ switch (node.tokenType()) {
+ case DECPREFIX:
+ case DECPOSTFIX:
+ return leaveSelfModifyingAssign(node, RANGE.sub(node.rhs().getSymbol().getRange(), Range.createRange(1)));
+ case INCPREFIX:
+ case INCPOSTFIX:
+ return leaveSelfModifyingAssign(node, RANGE.add(node.rhs().getSymbol().getRange(), Range.createRange(1)));
+ default:
+ assert false;
+ return node;
+ }
+ }
+
+ @Override
+ public Node leaveADD(final UnaryNode node) {
+ Range range = node.rhs().getSymbol().getRange();
+ if (!range.getType().isNumeric()) {
+ range = Range.createTypeRange(Type.NUMBER);
+ }
+ setRange(node, range);
+ return node;
+ }
+
+ @Override
+ public Node leaveBIT_NOT(final UnaryNode node) {
+ setRange(node, Range.createTypeRange(Type.INT));
+ return node;
+ }
+
+ @Override
+ public Node leaveNOT(final UnaryNode node) {
+ setRange(node, Range.createTypeRange(Type.BOOLEAN));
+ return node;
+ }
+
+ @Override
+ public Node leaveSUB(final UnaryNode node) {
+ setRange(node, RANGE.neg(node.rhs().getSymbol().getRange()));
+ return node;
+ }
+
+ @Override
+ public Node leaveVarNode(final VarNode node) {
+ if (node.isAssignment()) {
+ Range range = node.getInit().getSymbol().getRange();
+ range = range.isUnknown() ? Range.createGenericRange() : range;
+
+ setRange(node.getName(), range);
+ setRange(node, range);
+ }
+
+ return node;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public boolean enterLiteralNode(final LiteralNode node) {
+ // ignore array literals
+ return !(node instanceof ArrayLiteralNode);
+ }
+
+ @Override
+ public Node leaveLiteralNode(@SuppressWarnings("rawtypes") final LiteralNode node) {
+ if (node.getType().isInteger()) {
+ setRange(node, Range.createRange(node.getInt32()));
+ } else if (node.getType().isNumber()) {
+ setRange(node, Range.createRange(node.getNumber()));
+ } else if (node.getType().isLong()) {
+ setRange(node, Range.createRange(node.getLong()));
+ } else if (node.getType().isBoolean()) {
+ setRange(node, Range.createTypeRange(Type.BOOLEAN));
+ } else {
+ setRange(node, Range.createGenericRange());
+ }
+ return node;
+ }
+
+ @Override
+ public boolean enterRuntimeNode(final RuntimeNode node) {
+ // a runtime node that cannot be specialized is no point entering
+ return node.getRequest().canSpecialize();
+ }
+
+ /**
+ * Check whether a symbol is unsafely assigned in a loop - i.e. repeteadly assigned and
+ * not being identified as the loop counter. That means we don't really know anything
+ * about its range.
+ * @param loopNode loop node
+ * @param symbol symbol
+ * @return true if assigned in loop
+ */
+ // TODO - this currently checks for nodes only - needs to be augmented for while nodes
+ // assignment analysis is also very conservative
+ private static boolean assignedInLoop(final LoopNode loopNode, final Symbol symbol) {
+ final HashSet skip = new HashSet<>();
+ final HashSet assignmentsInLoop = new HashSet<>();
+
+ loopNode.accept(new NodeVisitor() {
+ private boolean assigns(final Node node, final Symbol s) {
+ return node.isAssignment() && ((Assignment>)node).getAssignmentDest().getSymbol() == s;
+ }
+
+ @Override
+ public boolean enterForNode(final ForNode forNode) {
+ if (forNode.getInit() != null) {
+ skip.add(forNode.getInit());
+ }
+ if (forNode.getModify() != null) {
+ skip.add(forNode.getModify());
+ }
+ return true;
+ }
+
+ @Override
+ public Node leaveDefault(final Node node) {
+ //if this is an assignment to symbol
+ if (!skip.contains(node) && assigns(node, symbol)) {
+ assignmentsInLoop.add(node);
+ }
+ return node;
+ }
+ });
+
+ return !assignmentsInLoop.isEmpty();
+ }
+
+ /**
+ * Check for a loop counter. This is currently quite conservative, in that it only handles
+ * x <= counter and x < counter.
+ *
+ * @param node loop node to check
+ * @return
+ */
+ private static Symbol findLoopCounter(final LoopNode node) {
+ final Node test = node.getTest();
+
+ if (test != null && test.isComparison()) {
+ final BinaryNode binaryNode = (BinaryNode)test;
+ final Node lhs = binaryNode.lhs();
+ final Node rhs = binaryNode.rhs();
+
+ //detect ident cmp int_literal
+ if (lhs instanceof IdentNode && rhs instanceof LiteralNode && ((LiteralNode>)rhs).getType().isInteger()) {
+ final Symbol symbol = lhs.getSymbol();
+ final int margin = ((LiteralNode>)rhs).getInt32();
+ final TokenType op = test.tokenType();
+
+ switch (op) {
+ case LT:
+ case LE:
+ symbol.setRange(RANGE.join(symbol.getRange(), Range.createRange(op == TokenType.LT ? margin - 1 : margin)));
+ return symbol;
+ case GT:
+ case GE:
+ //setRange(lhs, Range.createRange(op == TokenType.GT ? margin + 1 : margin));
+ //return symbol;
+ default:
+ break;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isLoopCounter(final LoopNode loopNode, final Symbol symbol) {
+ //this only works if loop nodes aren't replaced by other ones during this transform, but they are not
+ return loopCounters.get(loopNode) == symbol;
+ }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java b/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java
new file mode 100644
index 00000000000..2845d90240e
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java
@@ -0,0 +1,705 @@
+/*
+ * 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.codegen.types;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.JSType;
+
+/**
+ * Represents the value range of a symbol.
+ */
+public abstract class Range {
+
+ private static final Range GENERIC_RANGE = new Range() {
+ @Override
+ public Type getType() {
+ return Type.OBJECT;
+ }
+ };
+
+ private static final Range NUMBER_RANGE = new Range() {
+ @Override
+ public Type getType() {
+ return Type.NUMBER;
+ }
+ };
+
+ private static final Range UNKNOWN_RANGE = new Range() {
+ @Override
+ public Type getType() {
+ return Type.UNKNOWN;
+ }
+
+ @Override
+ public boolean isUnknown() {
+ return true;
+ }
+ };
+
+ private static class IntegerRange extends Range {
+ private final long min;
+ private final long max;
+ private final Type type;
+
+ private IntegerRange(final long min, final long max) {
+ assert min <= max;
+ this.min = min;
+ this.max = max;
+ this.type = typeFromRange(min, max);
+ }
+
+ private static Type typeFromRange(final long from, final long to) {
+ if (from >= Integer.MIN_VALUE && to <= Integer.MAX_VALUE) {
+ return Type.INT;
+ }
+ return Type.LONG;
+ }
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+
+ public long getMin() {
+ return min;
+ }
+
+ public long getMax() {
+ return max;
+ }
+
+ @Override
+ public boolean isIntegerConst() {
+ return getMin() == getMax();
+ }
+
+ private long getBitMask() {
+ if (min == max) {
+ return min;
+ }
+
+ if (min < 0) {
+ return ~0L;
+ }
+
+ long mask = 1;
+ while (mask < max) {
+ mask = (mask << 1) | 1;
+ }
+ return mask;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof IntegerRange) {
+ final IntegerRange other = (IntegerRange)obj;
+ return this.type == other.type && this.min == other.min && this.max == other.max;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.hashCode(min) ^ Long.hashCode(max);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "[" + min +", " + max + "]";
+ }
+ }
+
+ /**
+ * Get narrowest type for this range
+ * @return type
+ */
+ public abstract Type getType();
+
+ /**
+ * Is this range unknown
+ * @return true if unknown
+ */
+ public boolean isUnknown() {
+ return false;
+ }
+
+ /**
+ * Check if an integer is enough to span this range
+ * @return true if integer is enough
+ */
+ public boolean isIntegerType() {
+ return this instanceof IntegerRange;
+ }
+
+ /**
+ * Check if an integer is enough to span this range
+ * @return true if integer is enough
+ */
+ public boolean isIntegerConst() {
+ return false;
+ }
+
+ /**
+ * Create an unknown range - this is most likely a singleton object
+ * and it represents "we have no known range information"
+ * @return the range
+ */
+ public static Range createUnknownRange() {
+ return UNKNOWN_RANGE;
+ }
+
+ /**
+ * Create a constant range: [value, value]
+ * @param value value
+ * @return the range
+ */
+ public static Range createRange(final int value) {
+ return createIntegerRange(value, value);
+ }
+
+ /**
+ * Create a constant range: [value, value]
+ * @param value value
+ * @return the range
+ */
+ public static Range createRange(final long value) {
+ return createIntegerRange(value, value);
+ }
+
+ /**
+ * Create a constant range: [value, value]
+ * @param value value
+ * @return the range
+ */
+ public static Range createRange(final double value) {
+ if (isRepresentableAsLong(value)) {
+ return createIntegerRange((long) value, (long) value);
+ }
+ return createNumberRange();
+ }
+
+ /**
+ * Create a constant range: [value, value]
+ * @param value value
+ * @return the range
+ */
+ public static Range createRange(final Object value) {
+ if (value instanceof Integer) {
+ return createRange((int)value);
+ } else if (value instanceof Long) {
+ return createRange((long)value);
+ } else if (value instanceof Double) {
+ return createRange((double)value);
+ }
+
+ return createGenericRange();
+ }
+
+ /**
+ * Create a generic range - object symbol that carries no range
+ * information
+ * @return the range
+ */
+ public static Range createGenericRange() {
+ return GENERIC_RANGE;
+ }
+
+ /**
+ * Create a number range - number symbol that carries no range
+ * information
+ * @return the range
+ */
+ public static Range createNumberRange() {
+ return NUMBER_RANGE;
+ }
+
+ /**
+ * Create an integer range [min, max]
+ * @param min minimum value, inclusive
+ * @param max maximum value, inclusive
+ * @return the range
+ */
+ public static IntegerRange createIntegerRange(final long min, final long max) {
+ return new IntegerRange(min, max);
+ }
+
+ /**
+ * Create an integer range of maximum type width for the given type
+ * @param type the type
+ * @return the range
+ */
+ public static IntegerRange createIntegerRange(final Type type) {
+ assert type.isNumeric() && !type.isNumber();
+ final long min;
+ final long max;
+ if (type.isInteger()) {
+ min = Integer.MIN_VALUE;
+ max = Integer.MAX_VALUE;
+ } else if (type.isLong()) {
+ min = Long.MIN_VALUE;
+ max = Long.MAX_VALUE;
+ } else {
+ throw new AssertionError(); //type incompatible with integer range
+ }
+ return new IntegerRange(min, max);
+ }
+
+ /**
+ * Create an range of maximum type width for the given type
+ * @param type the type
+ * @return the range
+ */
+ public static Range createTypeRange(final Type type) {
+ if (type.isNumber()) {
+ return createNumberRange();
+ } else if (type.isNumeric()) {
+ return createIntegerRange(type);
+ } else {
+ return createGenericRange();
+ }
+ }
+
+ // check that add doesn't overflow
+ private static boolean checkAdd(final long a, final long b) {
+ final long result = a + b;
+ return ((a ^ result) & (b ^ result)) >= 0;
+ }
+
+ // check that sub doesn't overflow
+ private static boolean checkSub(final long a, final long b) {
+ final long result = a - b;
+ return ((a ^ result) & (b ^ result)) >= 0;
+ }
+
+ private static boolean checkMul(final long a, final long b) {
+ // TODO correct overflow check
+ return a >= Integer.MIN_VALUE && a <= Integer.MAX_VALUE && b >= Integer.MIN_VALUE && b <= Integer.MAX_VALUE;
+ }
+
+ /**
+ * The range functionality class responsible for merging ranges and drawing
+ * range conclusions from operations executed
+ */
+ public static class Functionality {
+ /** logger */
+ protected final DebugLogger log;
+
+ /**
+ * Constructor
+ * @param log logger
+ */
+ public Functionality(final DebugLogger log) {
+ this.log = log;
+ }
+
+ /**
+ * Join two ranges
+ * @param a first range
+ * @param b second range
+ * @return the joined range
+ */
+ public Range join(final Range a, final Range b) {
+ if (a.equals(b)) {
+ return a;
+ }
+
+ Type joinedType = a.getType();
+ if (a.getType() != b.getType()) {
+ if (a.isUnknown()) {
+ return b;
+ }
+ if (b.isUnknown()) {
+ return a;
+ }
+
+ joinedType = Type.widest(a.getType(), b.getType());
+ }
+
+ if (joinedType.isInteger() || joinedType.isLong()) {
+ return createIntegerRange(
+ Math.min(((IntegerRange) a).getMin(), ((IntegerRange) b).getMin()),
+ Math.max(((IntegerRange) a).getMax(), ((IntegerRange) b).getMax()));
+ }
+
+ return createTypeRange(joinedType);
+ }
+
+ /**
+ * Add operation
+ * @param a range of first symbol to be added
+ * @param b range of second symbol to be added
+ * @return resulting range representing the value range after add
+ */
+ public Range add(final Range a, final Range b) {
+ if (a.isIntegerType() && b.isIntegerType()) {
+ final IntegerRange lhs = (IntegerRange)a;
+ final IntegerRange rhs = (IntegerRange)b;
+ if (checkAdd(lhs.getMin(), rhs.getMin()) && checkAdd(lhs.getMax(), rhs.getMax())) {
+ return createIntegerRange(lhs.getMin() + rhs.getMin(), lhs.getMax() + rhs.getMax());
+ }
+ }
+
+ if (a.getType().isNumeric() && b.getType().isNumeric()) {
+ return createNumberRange();
+ }
+
+ return createGenericRange();
+ }
+
+ /**
+ * Sub operation
+ * @param a range of first symbol to be subtracted
+ * @param b range of second symbol to be subtracted
+ * @return resulting range representing the value range after subtraction
+ */
+ public Range sub(final Range a, final Range b) {
+ if (a.isIntegerType() && b.isIntegerType()) {
+ final IntegerRange lhs = (IntegerRange)a;
+ final IntegerRange rhs = (IntegerRange)b;
+ if (checkSub(lhs.getMin(), rhs.getMax()) && checkSub(lhs.getMax(), rhs.getMin())) {
+ return createIntegerRange(lhs.getMin() - rhs.getMax(), lhs.getMax() - rhs.getMin());
+ }
+ }
+
+ if (a.getType().isNumeric() && b.getType().isNumeric()) {
+ return createNumberRange();
+ }
+
+ return createGenericRange();
+ }
+
+ /**
+ * Mul operation
+ * @param a range of first symbol to be multiplied
+ * @param b range of second symbol to be multiplied
+ * @return resulting range representing the value range after multiplication
+ */
+ public Range mul(final Range a, final Range b) {
+ if (a.isIntegerType() && b.isIntegerType()) {
+ final IntegerRange lhs = (IntegerRange)a;
+ final IntegerRange rhs = (IntegerRange)b;
+
+ //ensure that nothing ever overflows or underflows
+ if (checkMul(lhs.getMin(), rhs.getMin()) &&
+ checkMul(lhs.getMax(), rhs.getMax()) &&
+ checkMul(lhs.getMin(), rhs.getMax()) &&
+ checkMul(lhs.getMax(), rhs.getMin())) {
+
+ final List results =
+ Arrays.asList(
+ lhs.getMin() * rhs.getMin(),
+ lhs.getMin() * rhs.getMax(),
+ lhs.getMax() * rhs.getMin(),
+ lhs.getMax() * rhs.getMax());
+ return createIntegerRange(Collections.min(results), Collections.max(results));
+ }
+ }
+
+ if (a.getType().isNumeric() && b.getType().isNumeric()) {
+ return createNumberRange();
+ }
+
+ return createGenericRange();
+ }
+
+ /**
+ * Neg operation
+ * @param a range of value symbol to be negated
+ * @return resulting range representing the value range after neg
+ */
+ public Range neg(final Range a) {
+ if (a.isIntegerType()) {
+ final IntegerRange rhs = (IntegerRange)a;
+ if (rhs.getMin() != Long.MIN_VALUE && rhs.getMax() != Long.MIN_VALUE) {
+ return createIntegerRange(-rhs.getMax(), -rhs.getMin());
+ }
+ }
+
+ if (a.getType().isNumeric()) {
+ return createNumberRange();
+ }
+
+ return createGenericRange();
+ }
+
+ /**
+ * Bitwise and operation
+ * @param a range of first symbol to be and:ed
+ * @param b range of second symbol to be and:ed
+ * @return resulting range representing the value range after and
+ */
+ public Range and(final Range a, final Range b) {
+ if (a.isIntegerType() && b.isIntegerType()) {
+ final int resultMask = (int) (((IntegerRange)a).getBitMask() & ((IntegerRange)b).getBitMask());
+ if (resultMask >= 0) {
+ return createIntegerRange(0, resultMask);
+ }
+ } else if (a.isUnknown() && b.isIntegerType()) {
+ final long operandMask = ((IntegerRange)b).getBitMask();
+ if (operandMask >= 0) {
+ return createIntegerRange(0, operandMask);
+ }
+ } else if (a.isIntegerType() && b.isUnknown()) {
+ final long operandMask = ((IntegerRange)a).getBitMask();
+ if (operandMask >= 0) {
+ return createIntegerRange(0, operandMask);
+ }
+ }
+
+ return createTypeRange(Type.INT);
+ }
+
+ /**
+ * Bitwise or operation
+ * @param a range of first symbol to be or:ed
+ * @param b range of second symbol to be or:ed
+ * @return resulting range representing the value range after or
+ */
+ public Range or(final Range a, final Range b) {
+ if (a.isIntegerType() && b.isIntegerType()) {
+ final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
+ if (resultMask >= 0) {
+ return createIntegerRange(0, resultMask);
+ }
+ }
+
+ return createTypeRange(Type.INT);
+ }
+
+ /**
+ * Bitwise xor operation
+ * @param a range of first symbol to be xor:ed
+ * @param b range of second symbol to be xor:ed
+ * @return resulting range representing the value range after and
+ */
+ public Range xor(final Range a, final Range b) {
+ if (a.isIntegerConst() && b.isIntegerConst()) {
+ return createRange(((IntegerRange)a).getMin() ^ ((IntegerRange)b).getMin());
+ }
+
+ if (a.isIntegerType() && b.isIntegerType()) {
+ final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
+ if (resultMask >= 0) {
+ return createIntegerRange(0, createIntegerRange(0, resultMask).getBitMask());
+ }
+ }
+ return createTypeRange(Type.INT);
+ }
+
+ /**
+ * Bitwise shl operation
+ * @param a range of first symbol to be shl:ed
+ * @param b range of second symbol to be shl:ed
+ * @return resulting range representing the value range after shl
+ */
+ public Range shl(final Range a, final Range b) {
+ if (b.isIntegerType() && b.isIntegerConst()) {
+ final IntegerRange left = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
+ final int shift = (int)((IntegerRange) b).getMin() & 0x1f;
+ final int min = (int)left.getMin() << shift;
+ final int max = (int)left.getMax() << shift;
+ if (min >> shift == left.getMin() && max >> shift == left.getMax()) {
+ return createIntegerRange(min, max);
+ }
+ }
+
+ return createTypeRange(Type.INT);
+ }
+
+ /**
+ * Bitwise shr operation
+ * @param a range of first symbol to be shr:ed
+ * @param b range of second symbol to be shr:ed
+ * @return resulting range representing the value range after shr
+ */
+ public Range shr(final Range a, final Range b) {
+ if (b.isIntegerType() && b.isIntegerConst()) {
+ final long shift = ((IntegerRange) b).getMin() & 0x1f;
+ final IntegerRange left = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
+ if (left.getMin() >= 0) {
+ long min = left.getMin() >>> shift;
+ long max = left.getMax() >>> shift;
+ return createIntegerRange(min, max);
+ } else if (shift >= 1) {
+ return createIntegerRange(0, JSType.MAX_UINT >>> shift);
+ }
+ }
+
+ return createTypeRange(Type.INT);
+ }
+
+ /**
+ * Bitwise sar operation
+ * @param a range of first symbol to be sar:ed
+ * @param b range of second symbol to be sar:ed
+ * @return resulting range representing the value range after sar
+ */
+ public Range sar(final Range a, final Range b) {
+ if (b.isIntegerType() && b.isIntegerConst()) {
+ final IntegerRange left = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
+ final long shift = ((IntegerRange) b).getMin() & 0x1f;
+ final long min = left.getMin() >> shift;
+ final long max = left.getMax() >> shift;
+ return createIntegerRange(min, max);
+ }
+
+ return createTypeRange(Type.INT);
+ }
+
+ /**
+ * Modulo operation
+ * @param a range of first symbol to the mod operation
+ * @param b range of second symbol to be mod operation
+ * @return resulting range representing the value range after mod
+ */
+ public Range mod(final Range a, final Range b) {
+ if (a.isIntegerType() && b.isIntegerType()) {
+ final IntegerRange rhs = (IntegerRange) b;
+ if (rhs.getMin() > 0 || rhs.getMax() < 0) { // divisor range must not include 0
+ final long absmax = Math.max(Math.abs(rhs.getMin()), Math.abs(rhs.getMax())) - 1;
+ return createIntegerRange(rhs.getMin() > 0 ? 0 : -absmax, rhs.getMax() < 0 ? 0 : +absmax);
+ }
+ }
+ return createTypeRange(Type.NUMBER);
+ }
+
+ /**
+ * Division operation
+ * @param a range of first symbol to the division
+ * @param b range of second symbol to be division
+ * @return resulting range representing the value range after division
+ */
+ public Range div(final Range a, final Range b) {
+ // TODO
+ return createTypeRange(Type.NUMBER);
+ }
+ }
+
+ /**
+ * Simple trace functionality that will log range creation
+ */
+ public static class TraceFunctionality extends Functionality {
+ TraceFunctionality(final DebugLogger log) {
+ super(log);
+ }
+
+ private Range trace(final Range result, final String operation, final Range... operands) {
+ log.fine("range::" + operation + Arrays.toString(operands) + " => " + result);
+ return result;
+ }
+
+ @Override
+ public Range join(final Range a, final Range b) {
+ final Range result = super.join(a, b);
+ if (!a.equals(b)) {
+ trace(result, "join", a, b);
+ }
+ return result;
+ }
+
+ @Override
+ public Range add(final Range a, final Range b) {
+ return trace(super.add(a, b), "add", a, b);
+ }
+
+ @Override
+ public Range sub(final Range a, final Range b) {
+ return trace(super.sub(a, b), "sub", a, b);
+ }
+
+ @Override
+ public Range mul(final Range a, final Range b) {
+ return trace(super.mul(a, b), "mul", a, b);
+ }
+
+ @Override
+ public Range neg(final Range a) {
+ return trace(super.neg(a), "neg", a);
+ }
+
+ @Override
+ public Range and(final Range a, final Range b) {
+ return trace(super.and(a, b), "and", a, b);
+ }
+
+ @Override
+ public Range or(final Range a, final Range b) {
+ return trace(super.or(a, b), "or", a, b);
+ }
+
+ @Override
+ public Range xor(final Range a, final Range b) {
+ return trace(super.xor(a, b), "xor", a, b);
+ }
+
+ @Override
+ public Range shl(final Range a, final Range b) {
+ return trace(super.shl(a, b), "shl", a, b);
+ }
+
+ @Override
+ public Range shr(final Range a, final Range b) {
+ return trace(super.shr(a, b), "shr", a, b);
+ }
+
+ @Override
+ public Range sar(final Range a, final Range b) {
+ return trace(super.sar(a, b), "sar", a, b);
+ }
+
+ @Override
+ public Range mod(final Range a, final Range b) {
+ return trace(super.mod(a, b), "mod", a, b);
+ }
+
+ @Override
+ public Range div(final Range a, final Range b) {
+ return trace(super.div(a, b), "div", a, b);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(getType());
+ }
+
+ @SuppressWarnings("unused")
+ private static boolean isRepresentableAsInt(final double number) {
+ return (int)number == number && !isNegativeZero(number);
+ }
+
+ private static boolean isRepresentableAsLong(final double number) {
+ return (long)number == number && !isNegativeZero(number);
+ }
+
+ private static boolean isNegativeZero(final double number) {
+ return Double.doubleToLongBits(number) == Double.doubleToLongBits(-0.0);
+ }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
index 747793e8d5c..57b0212a59b 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
@@ -106,22 +106,12 @@ public abstract class Type implements Comparable, BytecodeOps {
Type(final String name, final Class> clazz, final int weight, final int slots) {
this.name = name;
this.clazz = clazz;
- this.descriptor = Type.getDescriptor(clazz);
+ this.descriptor = jdk.internal.org.objectweb.asm.Type.getDescriptor(clazz);
this.weight = weight;
assert weight >= MIN_WEIGHT && weight <= MAX_WEIGHT : "illegal type weight: " + weight;
this.slots = slots;
}
- /**
- * Return an internal descriptor for a type
- *
- * @param type the type
- * @return descriptor string
- */
- public static String getDescriptor(final Class> type) {
- return jdk.internal.org.objectweb.asm.Type.getDescriptor(type);
- }
-
/**
* Get the weight of this type - use this e.g. for sorting method descriptors
* @return the weight
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
index 61454fef0a1..51a0664688d 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
@@ -59,6 +59,23 @@ public final class BinaryNode extends Node implements Assignment {
this.rhs = rhs;
}
+ @Override
+ public boolean isComparison() {
+ switch (tokenType()) {
+ case EQ:
+ case EQ_STRICT:
+ case NE:
+ case NE_STRICT:
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/**
* Return the widest possible type for this operation. This is used for compile time
* static type inference
diff --git a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
index 715d4507ac3..d271985cc8b 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
@@ -340,7 +340,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags iter = new NodeIterator<>(LoopNode.class, getCurrentFunction());
+ return iter.hasNext() ? iter.next() : null;
+ }
+
/**
* Find the breakable node corresponding to this label.
* @param label label to search for, if null the closest breakable node will be returned unconditionally, e.g. a while loop with no label
@@ -461,8 +478,7 @@ public class LexicalContext {
}
private LoopNode getContinueTo() {
- final Iterator iter = new NodeIterator<>(LoopNode.class, getCurrentFunction());
- return iter.hasNext() ? iter.next() : null;
+ return getCurrentLoop();
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Node.java b/nashorn/src/jdk/nashorn/internal/ir/Node.java
index 0fb95cc3852..99e543e6110 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Node.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Node.java
@@ -152,6 +152,14 @@ public abstract class Node implements Cloneable {
return Type.OBJECT;
}
+ /**
+ * Returns true if this node represents a comparison operator
+ * @return true if comparison
+ */
+ public boolean isComparison() {
+ return false;
+ }
+
/**
* For reference copies - ensure that labels in the copy node are unique
* using an appropriate copy constructor
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Symbol.java b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java
index 05495152709..d26fe561627 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Symbol.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java
@@ -29,6 +29,8 @@ import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
+
+import jdk.nashorn.internal.codegen.types.Range;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
@@ -89,6 +91,9 @@ public final class Symbol implements Comparable {
/** Number of times this symbol is used in code */
private int useCount;
+ /** Range for symbol */
+ private Range range;
+
/** Debugging option - dump info and stack trace when symbols with given names are manipulated */
private static final Set TRACE_SYMBOLS;
private static final Set TRACE_SYMBOLS_STACKTRACE;
@@ -131,6 +136,7 @@ public final class Symbol implements Comparable {
this.type = type;
this.slot = slot;
this.fieldIndex = -1;
+ this.range = Range.createUnknownRange();
trace("CREATE SYMBOL");
}
@@ -157,12 +163,13 @@ public final class Symbol implements Comparable {
private Symbol(final Symbol base, final String name, final int flags) {
this.flags = flags;
- this.name = name;
+ this.name = name;
this.fieldIndex = base.fieldIndex;
- this.slot = base.slot;
- this.type = base.type;
- this.useCount = base.useCount;
+ this.slot = base.slot;
+ this.type = base.type;
+ this.useCount = base.useCount;
+ this.range = base.range;
}
private static String align(final String string, final int max) {
@@ -276,7 +283,7 @@ public final class Symbol implements Comparable {
@Override
public String toString() {
- final StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
sb.append(name).
append(' ').
@@ -409,6 +416,22 @@ public final class Symbol implements Comparable {
return (flags & KINDMASK) == IS_PARAM;
}
+ /**
+ * Get the range for this symbol
+ * @return range for symbol
+ */
+ public Range getRange() {
+ return range;
+ }
+
+ /**
+ * Set the range for this symbol
+ * @param range range
+ */
+ public void setRange(final Range range) {
+ this.range = range;
+ }
+
/**
* Check if this symbol is a function parameter of known
* narrowest type
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java
index d36f216c2b0..afa3657c1b5 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java
@@ -35,21 +35,27 @@ import jdk.nashorn.internal.codegen.types.Type;
*/
final class CompiledFunction implements Comparable {
+ /** The method type may be more specific than the invoker, if. e.g.
+ * the invoker is guarded, and a guard with a generic object only
+ * fallback, while the target is more specific, we still need the
+ * more specific type for sorting */
+ private final MethodType type;
private final MethodHandle invoker;
private MethodHandle constructor;
- CompiledFunction(final MethodHandle invoker) {
- this(invoker, null);
+ CompiledFunction(final MethodType type, final MethodHandle invoker) {
+ this(type, invoker, null);
}
- CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) {
- this.invoker = invoker;
- this.constructor = constructor; //isConstructor
+ CompiledFunction(final MethodType type, final MethodHandle invoker, final MethodHandle constructor) {
+ this.type = type;
+ this.invoker = invoker;
+ this.constructor = constructor;
}
@Override
public String toString() {
- return "";
+ return "";
}
MethodHandle getInvoker() {
@@ -69,7 +75,7 @@ final class CompiledFunction implements Comparable {
}
MethodType type() {
- return invoker.type();
+ return type;
}
@Override
@@ -103,8 +109,8 @@ final class CompiledFunction implements Comparable {
return weight() > o.weight();
}
- boolean moreGenericThan(final MethodType type) {
- return weight() > weight(type);
+ boolean moreGenericThan(final MethodType mt) {
+ return weight() > weight(mt);
}
/**
@@ -112,15 +118,15 @@ final class CompiledFunction implements Comparable {
* It is compatible if the types are narrower than the invocation type so that
* a semantically equivalent linkage can be performed.
*
- * @param typesc
+ * @param mt type to check against
* @return
*/
- boolean typeCompatible(final MethodType type) {
- final Class>[] wantedParams = type.parameterArray();
+ boolean typeCompatible(final MethodType mt) {
+ final Class>[] wantedParams = mt.parameterArray();
final Class>[] existingParams = type().parameterArray();
//if we are not examining a varargs type, the number of parameters must be the same
- if (wantedParams.length != existingParams.length && !isVarArgsType(type)) {
+ if (wantedParams.length != existingParams.length && !isVarArgsType(mt)) {
return false;
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
index ed54b2e92a3..469245f113a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
@@ -78,9 +78,9 @@ public final class FinalScriptFunctionData extends ScriptFunctionData {
//only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor
//is too conservative a check. However, isConstructor(mh) always implies isConstructor param
assert isConstructor();
- code.add(new CompiledFunction(MH.insertArguments(mh, 0, false), composeConstructor(MH.insertArguments(mh, 0, true), needsCallee))); //make sure callee state can be determined when we reach constructor
+ code.add(new CompiledFunction(mh.type(), MH.insertArguments(mh, 0, false), composeConstructor(MH.insertArguments(mh, 0, true), needsCallee))); //make sure callee state can be determined when we reach constructor
} else {
- code.add(new CompiledFunction(mh));
+ code.add(new CompiledFunction(mh.type(), mh));
}
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
index 03a25dab1b7..226d83d1b76 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
@@ -30,6 +30,8 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.LinkedList;
import jdk.nashorn.internal.codegen.Compiler;
@@ -49,9 +51,16 @@ import jdk.nashorn.internal.parser.TokenType;
*/
public final class RecompilableScriptFunctionData extends ScriptFunctionData {
+ /** FunctionNode with the code for this ScriptFunction */
private FunctionNode functionNode;
- private final PropertyMap allocatorMap;
+
+ /** Allocator map from makeMap() */
+ private final PropertyMap allocatorMap;
+
+ /** Code installer used for all further recompilation/specialization of this ScriptFunction */
private final CodeInstaller installer;
+
+ /** Name of class where allocator function resides */
private final String allocatorClassName;
/** lazily generated allocator */
@@ -59,6 +68,23 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+ /**
+ * Used for specialization based on runtime arguments. Whenever we specialize on
+ * callsite parameter types at runtime, we need to use a parameter type guard to
+ * ensure that the specialized version of the script function continues to be
+ * applicable for a particular callsite *
+ */
+ private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class, Object[].class);
+
+ /**
+ * It is usually a good gamble whever we detect a runtime callsite with a double
+ * (or java.lang.Number instance) to specialize the parameter to an integer, if the
+ * parameter in question can be represented as one. The double typically only exists
+ * because the compiler doesn't know any better than "a number type" and conservatively
+ * picks doubles when it can't prove that an integer addition wouldn't overflow
+ */
+ private static final MethodHandle ENSURE_INT = findOwnMH("ensureInt", int.class, Object.class);
+
/**
* Constructor - public as scripts use it
*
@@ -141,14 +167,6 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
return; // nothing to do, we have code, at least some.
}
- // check if function node is lazy, need to compile it.
- // note that currently function cloning is not working completely, which
- // means that the compiler will mutate the function node it has been given
- // once it has been compiled, it cannot be recompiled. This means that
- // lazy compilation works (not compiled yet) but e.g. specializations won't
- // until the copy-on-write changes for IR are in, making cloning meaningless.
- // therefore, currently method specialization is disabled. TODO
-
if (functionNode.isLazy()) {
Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
final Compiler compiler = new Compiler(installer);
@@ -156,38 +174,55 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
assert !functionNode.isLazy();
compiler.install(functionNode);
- // we don't need to update any flags - varArgs and needsCallee are instrincic
- // in the function world we need to get a destination node from the compile instead
- // and replace it with our function node. TODO
+ /*
+ * We don't need to update any flags - varArgs and needsCallee are instrincic
+ * in the function world we need to get a destination node from the compile instead
+ * and replace it with our function node. TODO
+ */
}
- // we can't get here unless we have bytecode, either from eager compilation or from
- // running a lazy compile on the lines above
+ /*
+ * We can't get to this program point unless we have bytecode, either from
+ * eager compilation or from running a lazy compile on the lines above
+ */
assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
// code exists - look it up and add it into the automatically sorted invoker list
- addCode(functionNode, null, null);
+ addCode(functionNode);
}
- private MethodHandle addCode(final FunctionNode fn, final MethodHandle guard, final MethodHandle fallback) {
- final MethodHandle target =
+ private MethodHandle addCode(final FunctionNode fn) {
+ return addCode(fn, null, null, null);
+ }
+
+ private MethodHandle addCode(final FunctionNode fn, final MethodType runtimeType, final MethodHandle guard, final MethodHandle fallback) {
+ final MethodType targetType = new FunctionSignature(fn).getMethodType();
+ MethodHandle target =
MH.findStatic(
LOOKUP,
fn.getCompileUnit().getCode(),
fn.getName(),
- new FunctionSignature(fn).
- getMethodType());
- MethodHandle mh = target;
- if (guard != null) {
- try {
- mh = MH.guardWithTest(MH.asCollector(guard, Object[].class, target.type().parameterCount()), MH.asType(target, fallback.type()), fallback);
- } catch (Throwable e) {
- e.printStackTrace();
+ targetType);
+
+ /*
+ * For any integer argument. a double that is representable as an integer is OK.
+ * otherwise the guard would have failed. in that case introduce a filter that
+ * casts the double to an integer, which we know will preserve all precision.
+ */
+ for (int i = 0; i < targetType.parameterCount(); i++) {
+ if (targetType.parameterType(i) == int.class) {
+ //representable as int
+ target = MH.filterArguments(target, i, ENSURE_INT);
}
}
- final CompiledFunction cf = new CompiledFunction(mh);
+ MethodHandle mh = target;
+ if (guard != null) {
+ mh = MH.guardWithTest(MH.asCollector(guard, Object[].class, target.type().parameterCount()), MH.asType(target, fallback.type()), fallback);
+ }
+
+ final CompiledFunction cf = new CompiledFunction(runtimeType == null ? targetType : runtimeType, mh);
code.add(cf);
return cf.getInvoker();
@@ -212,69 +247,162 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
return Type.OBJECT;
}
- @SuppressWarnings("unused")
- private static boolean paramTypeGuard(final Type[] compileTimeTypes, final Type[] runtimeTypes, Object... args) {
- //System.err.println("Param type guard " + Arrays.asList(args));
+ private static boolean canCoerce(final Object arg, final Type type) {
+ Type argType = runtimeType(arg);
+ if (Type.widest(argType, type) == type || arg == ScriptRuntime.UNDEFINED) {
+ return true;
+ }
+ System.err.println(arg + " does not fit in "+ argType + " " + type + " " + arg.getClass());
+ new Throwable().printStackTrace();
return false;
}
- private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class, Type[].class, Object[].class);
+ @SuppressWarnings("unused")
+ private static boolean paramTypeGuard(final Type[] paramTypes, final Object... args) {
+ final int length = args.length;
+ assert args.length >= paramTypes.length;
+
+ //i==start, skip the this, callee params etc
+ int start = args.length - paramTypes.length;
+ for (int i = start; i < args.length; i++) {
+ final Object arg = args[i];
+ if (!canCoerce(arg, paramTypes[i - start])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unused")
+ private static int ensureInt(final Object arg) {
+ if (arg instanceof Number) {
+ return ((Number)arg).intValue();
+ } else if (arg instanceof Undefined) {
+ return 0;
+ }
+ throw new AssertionError(arg);
+ }
+
+ /**
+ * Given the runtime callsite args, compute a method type that is equivalent to what
+ * was passed - this is typically a lot more specific that what the compiler has been
+ * able to deduce
+ * @param callSiteType callsite type for the compiled callsite target
+ * @param args runtime arguments to the compiled callsite target
+ * @return adjusted method type, narrowed as to conform to runtime callsite type instead
+ */
+ private static MethodType runtimeType(final MethodType callSiteType, final Object[] args) {
+ if (args == null) {
+ //for example bound, or otherwise runtime arguments to callsite unavailable, then
+ //do not change the type
+ return callSiteType;
+ }
+ final Class>[] paramTypes = new Class>[callSiteType.parameterCount()];
+ final int start = args.length - callSiteType.parameterCount();
+ for (int i = start; i < args.length; i++) {
+ paramTypes[i - start] = runtimeType(args[i]).getTypeClass();
+ }
+ return MH.type(callSiteType.returnType(), paramTypes);
+ }
+
+ private static ArrayList runtimeType(final MethodType mt) {
+ final ArrayList type = new ArrayList<>();
+ for (int i = 0; i < mt.parameterCount(); i++) {
+ type.add(Type.typeFor(mt.parameterType(i)));
+ }
+ return type;
+ }
@Override
MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
- final MethodHandle mh = super.getBestInvoker(callSiteType, args);
+ final MethodType runtimeType = runtimeType(callSiteType, args);
+ assert runtimeType.parameterCount() == callSiteType.parameterCount();
- if (!functionNode.canSpecialize() || !code.isLessSpecificThan(callSiteType)) {
+ final MethodHandle mh = super.getBestInvoker(runtimeType, args);
+
+ /*
+ * Not all functions can be specialized, for example, if we deemed memory
+ * footprint too large to store a parse snapshot, or if it is meaningless
+ * to do so, such as e.g. for runScript
+ */
+ if (!functionNode.canSpecialize()) {
return mh;
}
- final FunctionNode snapshot = functionNode.getSnapshot();
- if (snapshot == null) {
+ /*
+ * Check if best invoker is equally specific or more specific than runtime
+ * type. In that case, we don't need further specialization, but can use
+ * whatever we have already. We know that it will match callSiteType, or it
+ * would not have been returned from getBestInvoker
+ */
+ if (!code.isLessSpecificThan(runtimeType)) {
return mh;
}
int i;
+ final FunctionNode snapshot = functionNode.getSnapshot();
+ assert snapshot != null;
- //classes known at runtime
- final LinkedList runtimeArgs = new LinkedList<>();
- for (i = args.length - 1; i >= args.length - snapshot.getParameters().size(); i--) {
- runtimeArgs.addLast(runtimeType(args[i]));
- }
-
- //classes known at compile time
+ /*
+ * Create a list of the arg types that the compiler knows about
+ * typically, the runtime args are a lot more specific, and we should aggressively
+ * try to use those whenever possible
+ * We WILL try to make an aggressive guess as possible, and add guards if needed.
+ * For example, if the compiler can deduce that we have a number type, but the runtime
+ * passes and int, we might still want to keep it an int, and the gamble to
+ * check that whatever is passed is int representable usually pays off
+ * If the compiler only knows that a parameter is an "Object", it is still worth
+ * it to try to specialize it by looking at the runtime arg.
+ */
final LinkedList compileTimeArgs = new LinkedList<>();
for (i = callSiteType.parameterCount() - 1; i >= 0 && compileTimeArgs.size() < snapshot.getParameters().size(); i--) {
- compileTimeArgs.addLast(Type.typeFor(callSiteType.parameterType(i)));
+ compileTimeArgs.addFirst(Type.typeFor(callSiteType.parameterType(i)));
}
- //the classes known at compile time are a safe to generate as primitives without parameter guards
- //the classes known at runtime are safe to generate as primitives IFF there are parameter guards
+ /*
+ * The classes known at compile time are a safe to generate as primitives without parameter guards
+ * But the classes known at runtime (if more specific than compile time types) are safe to generate as primitives
+ * IFF there are parameter guards
+ */
MethodHandle guard = null;
+ final ArrayList runtimeParamTypes = runtimeType(runtimeType);
+ while (runtimeParamTypes.size() > functionNode.getParameters().size()) {
+ runtimeParamTypes.remove(0);
+ }
for (i = 0; i < compileTimeArgs.size(); i++) {
- final Type runtimeType = runtimeArgs.get(i);
- final Type compileType = compileTimeArgs.get(i);
+ final Type rparam = Type.typeFor(runtimeType.parameterType(i));
+ final Type cparam = compileTimeArgs.get(i);
- if (compileType.isObject() && !runtimeType.isObject()) {
+ if (cparam.isObject() && !rparam.isObject()) {
+ //check that the runtime object is still coercible to the runtime type, because compiler can't prove it's always primitive
if (guard == null) {
- guard = PARAM_TYPE_GUARD;
- guard = MH.insertArguments(guard, 0, compileTimeArgs.toArray(new Type[compileTimeArgs.size()]), runtimeArgs.toArray(new Type[runtimeArgs.size()]));
+ guard = MH.insertArguments(PARAM_TYPE_GUARD, 0, (Object)runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]));
}
}
}
- //System.err.println("Specialized " + name + " " + runtimeArgs + " known=" + compileTimeArgs);
+ Compiler.LOG.info("Callsite specialized ", name, " runtimeType=", runtimeType, " parameters=", snapshot.getParameters(), " args=", Arrays.asList(args));
assert snapshot != null;
assert snapshot != functionNode;
final Compiler compiler = new Compiler(installer);
- final FunctionNode compiledSnapshot = compiler.compile(snapshot.setHints(null, new Compiler.Hints(compileTimeArgs.toArray(new Type[compileTimeArgs.size()]))));
+ final FunctionNode compiledSnapshot = compiler.compile(
+ snapshot.setHints(
+ null,
+ new Compiler.Hints(runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]))));
+
+ /*
+ * No matter how narrow your types were, they can never be narrower than Attr during recompile made them. I.e. you
+ * can put an int into the function here, if you see it as a runtime type, but if the function uses a multiplication
+ * on it, it will still need to be a double. At least until we have overflow checks. Similarly, if an int is
+ * passed but it is used as a string, it makes no sense to make the parameter narrower than Object. At least until
+ * the "different types for one symbol in difference places" work is done
+ */
compiler.install(compiledSnapshot);
- final MethodHandle nmh = addCode(compiledSnapshot, guard, mh);
-
- return nmh;
+ return addCode(compiledSnapshot, runtimeType, guard, mh);
}
private static MethodHandle findOwnMH(final String name, final Class> rtype, final Class>... types) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
index 0a556f9d51c..3bcf9d4f5a3 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@@ -54,7 +54,7 @@ public final class ScriptEnvironment {
private final Namespace namespace;
/** Current Options object. */
- private Options options;
+ private final Options options;
/** Always allow functions as statements */
public final boolean _anon_functions;
@@ -155,6 +155,9 @@ public final class ScriptEnvironment {
/** print symbols and their contents for the script */
public final boolean _print_symbols;
+ /** range analysis for known types */
+ public final boolean _range_analysis;
+
/** is this environment in scripting mode? */
public final boolean _scripting;
@@ -219,6 +222,7 @@ public final class ScriptEnvironment {
_print_parse = options.getBoolean("print.parse");
_print_lower_parse = options.getBoolean("print.lower.parse");
_print_symbols = options.getBoolean("print.symbols");
+ _range_analysis = options.getBoolean("range.analysis");
_scripting = options.getBoolean("scripting");
_strict = options.getBoolean("strict");
_version = options.getBoolean("version");
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
index 1e899be5805..f98817c8ee6 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
@@ -91,12 +91,13 @@ public abstract class ScriptFunctionData {
CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
final MethodHandle boundInvoker = bindInvokeHandle(originalInv.getInvoker(), fn, self, args);
+ //TODO the boundinvoker.type() could actually be more specific here
if (isConstructor()) {
ensureConstructor(originalInv);
- return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args));
+ return new CompiledFunction(boundInvoker.type(), boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args));
}
- return new CompiledFunction(boundInvoker);
+ return new CompiledFunction(boundInvoker.type(), boundInvoker);
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties
index 4717319710f..59e971917eb 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties
@@ -277,6 +277,12 @@ nashorn.option.print.symbols = { \
desc="Print the symbol table." \
}
+nashorn.option.range.analysis = { \
+ name="--range-analysis", \
+ is_undocumented=true, \
+ desc="Do range analysis using known compile time types, and try to narrow number types" \
+}
+
nashorn.option.D = { \
name="-D", \
desc="-Dname=value. Set a system property. This option can be repeated.", \
diff --git a/nashorn/test/script/basic/ranges_disabled.js b/nashorn/test/script/basic/ranges_disabled.js
new file mode 100644
index 00000000000..5bc8846ee54
--- /dev/null
+++ b/nashorn/test/script/basic/ranges_disabled.js
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * range analysis test. check that computation return values are correct
+ * both with and without range analysis
+ *
+ * @test
+ * @run
+ */
+
+load(__DIR__ + "ranges_payload.js");
diff --git a/nashorn/test/script/basic/ranges_disabled.js.EXPECTED b/nashorn/test/script/basic/ranges_disabled.js.EXPECTED
new file mode 100644
index 00000000000..1a99c91b7e6
--- /dev/null
+++ b/nashorn/test/script/basic/ranges_disabled.js.EXPECTED
@@ -0,0 +1,4 @@
+289
+11094405
+4294967293
+-4722
diff --git a/nashorn/test/script/basic/ranges_enabled.js b/nashorn/test/script/basic/ranges_enabled.js
new file mode 100644
index 00000000000..45d9efb08d9
--- /dev/null
+++ b/nashorn/test/script/basic/ranges_enabled.js
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * range analysis test. check that computation return values are correct
+ * both with and without range analysis
+ *
+ * @test
+ * @option --range-analysis
+ * @run
+ */
+
+load(__DIR__ + "ranges_payload.js");
diff --git a/nashorn/test/script/basic/ranges_enabled.js.EXPECTED b/nashorn/test/script/basic/ranges_enabled.js.EXPECTED
new file mode 100644
index 00000000000..1a99c91b7e6
--- /dev/null
+++ b/nashorn/test/script/basic/ranges_enabled.js.EXPECTED
@@ -0,0 +1,4 @@
+289
+11094405
+4294967293
+-4722
diff --git a/nashorn/test/script/basic/ranges_payload.js b/nashorn/test/script/basic/ranges_payload.js
new file mode 100644
index 00000000000..f10a4a28b1f
--- /dev/null
+++ b/nashorn/test/script/basic/ranges_payload.js
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * range analysis test. check that computation return values are correct
+ * both with and without range analysis
+ *
+ * @subtest
+ */
+
+function f(c) {
+ var v = c & 0xffff;
+ var w = v & 0xfff;
+ var x = v * w;
+ return x;
+}
+
+function g() {
+ var sum = 0;
+ for (var x = 0; x < 4711; x++) {
+ sum += x;
+ }
+ return sum;
+}
+
+function g2() {
+ var sum = 0;
+ //make sure we overflow
+ var displacement = 0x7ffffffe;
+ for (var x = displacement; x < (displacement + 2); x++) {
+ sum += x;
+ }
+ return sum;
+}
+
+//mostly provide code coverage for all the range operations
+function h() {
+ var sum = 0;
+ sum += 4711;
+ sum &= 0xffff;
+ sum /= 2;
+ sum *= 2;
+ sum -= 4;
+ sum |= 2;
+ sum ^= 17;
+ sum = sum % 10000;
+ sum = -sum;
+ return sum
+}
+
+print(f(17));
+print(g());
+print(g2());
+print(h());
From 32261c12b2f6a3983665dafa276f6d6c17601a50 Mon Sep 17 00:00:00 2001
From: Athijegannathan Sundararajan
Date: Mon, 20 May 2013 23:04:01 +0530
Subject: [PATCH 022/101] 8014909: ant test compilation error with
JoniTest.java
Reviewed-by: jlaskey
---
nashorn/make/build.xml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml
index c647ba4b922..7c05e789fe9 100644
--- a/nashorn/make/build.xml
+++ b/nashorn/make/build.xml
@@ -212,7 +212,9 @@
target="${javac.target}"
debug="${javac.debug}"
encoding="${javac.encoding}"
- includeantruntime="false"/>
+ includeantruntime="false">
+
+
From c6619c912d65c655a3c665d43951971de1f5cbc2 Mon Sep 17 00:00:00 2001
From: Philippe Marschall
Date: Mon, 20 May 2013 11:56:46 -0700
Subject: [PATCH 023/101] 8004789: (zipfs) zip provider doesn't work correctly
with file systems providers rather than the default
To use Files.createTempFile(...) to create the temp file on the same fs as the targeted path.
Reviewed-by: alanb, sherman
---
.../demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java
index b872a59b501..07c71bb5d46 100644
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java
+++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java
@@ -1085,13 +1085,13 @@ public class ZipFileSystem extends FileSystem {
}
// Creates a new empty temporary file in the same directory as the
- // specified file. A variant of File.createTempFile.
+ // specified file. A variant of Files.createTempFile.
private Path createTempFileInSameDirectoryAs(Path path)
throws IOException
{
Path parent = path.toAbsolutePath().getParent();
- String dir = (parent == null)? "." : parent.toString();
- Path tmpPath = File.createTempFile("zipfstmp", null, new File(dir)).toPath();
+ Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
+ Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
tmppaths.add(tmpPath);
return tmpPath;
}
From 34bc5ff07fc75ef6adc513fe8b2818ebf1c93a0b Mon Sep 17 00:00:00 2001
From: Attila Szegedi
Date: Mon, 20 May 2013 21:25:14 +0200
Subject: [PATCH 024/101] 8014797: rename Java.toJavaArray/toJavaScriptArray to
Java.to/from, respectively
Reviewed-by: jlaskey, sundar
---
.../docs/JavaScriptingProgrammersGuide.html | 10 ++--
nashorn/docs/source/javaarray.js | 4 +-
.../nashorn/api/scripting/resources/engine.js | 2 +-
.../nashorn/internal/objects/NativeJava.java | 51 ++++++++++++-------
.../runtime/resources/Messages.properties | 1 +
nashorn/test/script/basic/NASHORN-556.js | 24 ++++-----
.../test/script/basic/javaarrayconversion.js | 16 +++---
.../script/currently-failing/logcoverage.js | 3 +-
nashorn/test/script/trusted/NASHORN-638.js | 3 +-
nashorn/test/script/trusted/NASHORN-653.js | 3 +-
10 files changed, 64 insertions(+), 53 deletions(-)
diff --git a/nashorn/docs/JavaScriptingProgrammersGuide.html b/nashorn/docs/JavaScriptingProgrammersGuide.html
index a9af9612271..a9803f7fd81 100644
--- a/nashorn/docs/JavaScriptingProgrammersGuide.html
+++ b/nashorn/docs/JavaScriptingProgrammersGuide.html
@@ -616,26 +616,26 @@ print(a[0]);
It is also possible to convert between JavaScript and Java arrays.
-Given a JavaScript array and a Java type, Java.toJavaArray returns a Java array with the same initial contents, and with the specified component type.
+Given a JavaScript array and a Java type, Java.to returns a Java array with the same initial contents, and with the specified array type.
var anArray = [1, "13", false]
- var javaIntArray = Java.toJavaArray(anArray, "int")
+ var javaIntArray = Java.to(anArray, "int[]")
print(javaIntArray[0]) // prints 1
print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
-You can use either a string or a type object returned from Java.type() to specify the component type of the array.
+You can use either a string or a type object returned from Java.type() to specify the type of the array.
You can also omit the array type, in which case a Object[] will be created.
-Given a Java array or Collection, Java.toJavaScriptArray returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method.
+Given a Java array or Collection, Java.from returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method.
var File = Java.type("java.io.File");
var listCurDir = new File(".").listFiles();
-var jsList = Java.toJavaScriptArray(listCurDir);
+var jsList = Java.from(listCurDir);
print(jsList);
diff --git a/nashorn/docs/source/javaarray.js b/nashorn/docs/source/javaarray.js
index a02aa3ca9f6..d0de9124684 100644
--- a/nashorn/docs/source/javaarray.js
+++ b/nashorn/docs/source/javaarray.js
@@ -40,7 +40,7 @@ print(a[0]);
// convert a script array to Java array
var anArray = [1, "13", false];
-var javaIntArray = Java.toJavaArray(anArray, "int");
+var javaIntArray = Java.to(anArray, "int[]");
print(javaIntArray[0]);// prints 1
print(javaIntArray[1]); // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
print(javaIntArray[2]);// prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
@@ -48,5 +48,5 @@ print(javaIntArray[2]);// prints 0, as boolean false was converted to number 0 a
// convert a Java array to a JavaScript array
var File = Java.type("java.io.File");
var listCurDir = new File(".").listFiles();
-var jsList = Java.toJavaScriptArray(listCurDir);
+var jsList = Java.from(listCurDir);
print(jsList);
diff --git a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js b/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js
index e95607287d4..62d6735ee3f 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js
+++ b/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js
@@ -88,7 +88,7 @@ Object.defineProperty(this, "sprintf", {
}
}
- array = Java.toJavaArray(array);
+ array = Java.to(array);
return Packages.jdk.nashorn.api.scripting.ScriptUtils.format(format, array);
}
});
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
index 5faec5ea98b..800b224f10d 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -240,39 +240,52 @@ public final class NativeJava {
}
/**
- * Given a JavaScript array and a Java type, returns a Java array with the same initial contents, and with the
- * specified component type. Example:
+ * Given a script object and a Java type, converts the script object into the desired Java type. Currently it only
+ * performs shallow creation of Java arrays, but might be extended for other types in the future. Example:
*
* var anArray = [1, "13", false]
- * var javaIntArray = Java.toJavaArray(anArray, "int")
+ * var javaIntArray = Java.to(anArray, "int[]")
* print(javaIntArray[0]) // prints 1
* print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
* print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
*
* @param self not used
- * @param objArray the JavaScript array. Can be null.
- * @param objType either a {@link #type(Object, Object) type object} or a String describing the component type of
- * the Java array to create. Can not be null. If undefined, Object is assumed (allowing the argument to be omitted).
- * @return a Java array with the copy of JavaScript array's contents, converted to the appropriate Java component
- * type. Returns null if objArray is null.
+ * @param objArray the script object. Can be null.
+ * @param objType either a {@link #type(Object, Object) type object} or a String describing the type of the Java
+ * object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be
+ * omitted).
+ * @return a Java object whose value corresponds to the original script object's value. Specifically, for array
+ * target types, returns a Java array of the same type with contents converted to the array's component type. Does
+ * not recursively convert for multidimensional arrays.
+ * type. Returns null if scriptObject is null.
* @throws ClassNotFoundException if the class described by objType is not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object toJavaArray(final Object self, final Object objArray, final Object objType) throws ClassNotFoundException {
- final StaticClass componentType =
- objType instanceof StaticClass ?
- (StaticClass)objType :
- objType == UNDEFINED ?
- StaticClass.forClass(Object.class) :
- type(objType);
-
+ public static Object to(final Object self, final Object objArray, final Object objType) throws ClassNotFoundException {
if (objArray == null) {
return null;
}
+ final Class> componentType;
+ if(objType == UNDEFINED) {
+ componentType = Object.class;
+ } else {
+ final StaticClass arrayType;
+ if(objType instanceof StaticClass) {
+ arrayType = (StaticClass)objType;
+ } else {
+ arrayType = type(objType);
+ }
+ final Class> arrayClass = arrayType.getRepresentedClass();
+ if(!arrayClass.isArray()) {
+ throw typeError("to.expects.array.type", arrayClass.getName());
+ }
+ componentType = arrayClass.getComponentType();
+ }
+
Global.checkObject(objArray);
- return ((ScriptObject)objArray).getArray().asArrayOfType(componentType.getRepresentedClass());
+ return ((ScriptObject)objArray).getArray().asArrayOfType(componentType);
}
/**
@@ -283,7 +296,7 @@ public final class NativeJava {
*
* var File = Java.type("java.io.File")
* var listHomeDir = new File("~").listFiles()
- * var jsListHome = Java.toJavaScriptArray(listHomeDir)
+ * var jsListHome = Java.from(listHomeDir)
* var jpegModifiedDates = jsListHome
* .filter(function(val) { return val.getName().endsWith(".jpg") })
* .map(function(val) { return val.lastModified() })
@@ -294,7 +307,7 @@ public final class NativeJava {
* null.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object toJavaScriptArray(final Object self, final Object objArray) {
+ public static Object from(final Object self, final Object objArray) {
if (objArray == null) {
return null;
} else if (objArray instanceof Collection) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
index 9f327521bcc..4f435ea2e96 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -125,6 +125,7 @@ type.error.no.constructor.matches.args=Can not construct {0} with the passed arg
type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures.
type.error.method.not.constructor=Java method {0} can't be used as a constructor.
type.error.env.not.object=$ENV must be an Object.
+type.error.to.expects.array.type=Java.to() expects an array target type. {0} is not an array type.
range.error.inappropriate.array.length=inappropriate array length: {0}
range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20]
range.error.invalid.precision=precision argument toPrecision() must be in [1, 21]
diff --git a/nashorn/test/script/basic/NASHORN-556.js b/nashorn/test/script/basic/NASHORN-556.js
index 5cb164a0cf3..1332d02bef8 100644
--- a/nashorn/test/script/basic/NASHORN-556.js
+++ b/nashorn/test/script/basic/NASHORN-556.js
@@ -47,7 +47,7 @@ function f1() {
// (NoTypeArrayData)
var empty = {};
empty.length = 10;
- Java.toJavaArray(empty);
+ Java.to(empty);
delete empty[0];
Array.prototype.slice.call(empty, 0, 1);
Array.prototype.pop.call(empty);
@@ -63,7 +63,7 @@ function f1() {
function f2() {
// DeletedArrayFilter
var deleted = [,1,,2,,3,,4,,];
- assertEq(2, Java.toJavaArray(deleted)[3]);
+ assertEq(2, Java.to(deleted)[3]);
assertEq(undefined, deleted.pop());
assertEq(4, deleted.pop());
deleted.unshift(5);
@@ -78,7 +78,7 @@ function f2() {
function f3() {
// DeletedRangeArrayFilter
var delrange = [1,2,3,,,,,,,,,,];
- Java.toJavaArray(delrange);
+ Java.to(delrange);
delrange.unshift(4);
p.apply(null, delrange);
print(delrange.slice(1,3), delrange.slice(2,6));
@@ -88,7 +88,7 @@ function f3() {
function f4() {
// NumberArrayData
var num = [1.1,2.2,3.3,4.4,5.5];
- Java.toJavaArray(num);
+ Java.to(num);
assertEq(2, num[3] >>> 1);
assertEq(5, num[4] | 0);
assertEq(5.5, num.pop());
@@ -104,7 +104,7 @@ function f4() {
function f5() {
// ObjectArrayData
var obj = [2,"two",3.14,"pi",14,"fourteen"];
- Java.toJavaArray(obj);
+ Java.to(obj);
assertEq(-12.86, obj[2] - 16);
assertEq(7, obj[4] >>> 1);
obj.unshift("one");
@@ -131,14 +131,14 @@ function f6() {
sparse.length = 1024*1024;
sparse.push(sparse.length);
delete sparse[sparse.length-1];
- //print(Java.toJavaArray(sparse).length);
+ //print(Java.to(sparse).length);
(function(){}).apply(null, sparse);
}
function f7() {
// UndefinedArrayFilter
var undef = [1,2,3,4,5,undefined,7,8,9,19];
- Java.toJavaArray(undef);
+ Java.to(undef);
assertEq(4, undef[8] >>> 1);
var tmp = undef[9] >>> 1;
undef[8] = tmp;
@@ -154,8 +154,8 @@ function f7() {
function f8() {
// LongArrayData
- var j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
- Java.toJavaArray(j);
+ var j = Java.from(Java.to([23,37,42,86,47], "long[]"));
+ Java.to(j);
p.apply(null, j);
assertEq(43, j[3] >>> 1);
assertEq(36, j[4] - 11);
@@ -164,12 +164,12 @@ function f8() {
assertEq(7, j.shift());
assertEq(47, j.pop());
j.push("asdf");
- j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
+ j = Java.from(Java.to([23,37,42,86,47], "long[]"));
j.length = 3;
j[0] = 13;
- j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
+ j = Java.from(Java.to([23,37,42,86,47], "long[]"));
delete j[0];
- j = Java.toJavaScriptArray(Java.toJavaArray([23,37,42,86,47], "long"));
+ j = Java.from(Java.to([23,37,42,86,47], "long[]"));
j.length = 20;
j[0] = 13.37;
}
diff --git a/nashorn/test/script/basic/javaarrayconversion.js b/nashorn/test/script/basic/javaarrayconversion.js
index 34e2f95fb12..96ebe904668 100644
--- a/nashorn/test/script/basic/javaarrayconversion.js
+++ b/nashorn/test/script/basic/javaarrayconversion.js
@@ -34,7 +34,7 @@ var x; // used for undefined
var testCount = 0;
function testF(inputValue, type, testFn) {
- var x = Java.toJavaArray([inputValue], type)[0];
+ var x = Java.to([inputValue], type + "[]")[0];
if(!testFn(x)) {
throw ("unexpected value: " + x)
}
@@ -130,7 +130,7 @@ test({ valueOf: function() { return "42"; }, toString: function() { return "43"
function assertCantConvert(sourceType, targetType) {
try {
- Java.toJavaArray([new Java.type(sourceType)()], targetType)
+ Java.to([new Java.type(sourceType)()], targetType + "[]")
throw "no TypeError encountered"
} catch(e) {
if(!(e instanceof TypeError)) {
@@ -164,7 +164,7 @@ var intArray = new (Java.type("int[]"))(3)
intArray[0] = 1234;
intArray[1] = 42;
intArray[2] = 5;
-var jsIntArray = Java.toJavaScriptArray(intArray)
+var jsIntArray = Java.from(intArray)
assert(jsIntArray instanceof Array);
assert(jsIntArray[0] === 1234);
assert(jsIntArray[1] === 42);
@@ -179,7 +179,7 @@ assert(intArray[2] === 6);
var byteArray = new (Java.type("byte[]"))(2)
byteArray[0] = -128;
byteArray[1] = 127;
-var jsByteArray = Java.toJavaScriptArray(byteArray)
+var jsByteArray = Java.from(byteArray)
assert(jsByteArray instanceof Array);
assert(jsByteArray[0] === -128);
assert(jsByteArray[1] === 127);
@@ -187,7 +187,7 @@ assert(jsByteArray[1] === 127);
var shortArray = new (Java.type("short[]"))(2)
shortArray[0] = -32768;
shortArray[1] = 32767;
-var jsShortArray = Java.toJavaScriptArray(shortArray)
+var jsShortArray = Java.from(shortArray)
assert(jsShortArray instanceof Array);
assert(jsShortArray[0] === -32768);
assert(jsShortArray[1] === 32767);
@@ -195,7 +195,7 @@ assert(jsShortArray[1] === 32767);
var floatArray = new (Java.type("float[]"))(2)
floatArray[0] = java.lang.Float.MIN_VALUE;
floatArray[1] = java.lang.Float.MAX_VALUE;
-var jsFloatArray = Java.toJavaScriptArray(floatArray)
+var jsFloatArray = Java.from(floatArray)
assert(jsFloatArray instanceof Array);
assert(jsFloatArray[0] == java.lang.Float.MIN_VALUE);
assert(jsFloatArray[1] == java.lang.Float.MAX_VALUE);
@@ -204,7 +204,7 @@ var charArray = new (Java.type("char[]"))(3)
charArray[0] = "a";
charArray[1] = "b";
charArray[2] = "1";
-var jsCharArray = Java.toJavaScriptArray(charArray)
+var jsCharArray = Java.from(charArray)
assert(jsCharArray instanceof Array);
assert(jsCharArray[0] === 97);
assert(jsCharArray[1] === 98);
@@ -213,7 +213,7 @@ assert(jsCharArray[2] === 49);
var booleanArray = new (Java.type("boolean[]"))(2)
booleanArray[0] = true;
booleanArray[1] = false;
-var jsBooleanArray = Java.toJavaScriptArray(booleanArray)
+var jsBooleanArray = Java.from(booleanArray)
assert(jsBooleanArray instanceof Array);
assert(jsBooleanArray[0] === true);
assert(jsBooleanArray[1] === false);
diff --git a/nashorn/test/script/currently-failing/logcoverage.js b/nashorn/test/script/currently-failing/logcoverage.js
index 18b16aa1e00..2d8d410a881 100644
--- a/nashorn/test/script/currently-failing/logcoverage.js
+++ b/nashorn/test/script/currently-failing/logcoverage.js
@@ -53,8 +53,7 @@ function runScriptEngine(opts, name) {
// set new standard err
System.setErr(newErr);
System.setOut(newOut);
- var strType = Java.type("java.lang.String");
- var engine = fac.getScriptEngine(Java.toJavaArray(opts, strType));
+ var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
var reader = new java.io.FileReader(name);
engine.eval(reader);
newErr.flush();
diff --git a/nashorn/test/script/trusted/NASHORN-638.js b/nashorn/test/script/trusted/NASHORN-638.js
index 9cb6d694c55..1ff789a919b 100644
--- a/nashorn/test/script/trusted/NASHORN-638.js
+++ b/nashorn/test/script/trusted/NASHORN-638.js
@@ -47,8 +47,7 @@ function runScriptEngine(opts, code) {
try {
// set new standard err
System.setErr(newErr);
- var strType = Java.type("java.lang.String");
- var engine = fac.getScriptEngine(Java.toJavaArray(opts, strType));
+ var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
engine.eval(code);
newErr.flush();
return new java.lang.String(baos.toByteArray());
diff --git a/nashorn/test/script/trusted/NASHORN-653.js b/nashorn/test/script/trusted/NASHORN-653.js
index 2084bf70aeb..14a2cbc4c1c 100644
--- a/nashorn/test/script/trusted/NASHORN-653.js
+++ b/nashorn/test/script/trusted/NASHORN-653.js
@@ -85,8 +85,7 @@ function runScriptEngine(opts, code) {
try {
// set new standard err
System.setErr(newErr);
- var strType = Java.type("java.lang.String");
- var engine = fac.getScriptEngine(Java.toJavaArray(opts, strType));
+ var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
engine.eval(code);
newErr.flush();
return new java.lang.String(baos.toByteArray());
From d463e0c4ae2d4d65d0be89e2942341a8de06b056 Mon Sep 17 00:00:00 2001
From: Dmitry Markov
Date: Tue, 21 May 2013 03:20:27 +0400
Subject: [PATCH 025/101] 7011777: JDK 6 parses html text with script tags
within comments differently from previous releases
Reviewed-by: alexsch
---
.../javax/swing/text/html/parser/Parser.java | 12 +++-
.../parser/Parser/7011777/bug7011777.java | 63 +++++++++++++++++++
2 files changed, 73 insertions(+), 2 deletions(-)
create mode 100644 jdk/test/javax/swing/text/html/parser/Parser/7011777/bug7011777.java
diff --git a/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java b/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java
index bd0cebc7373..d511109c10b 100644
--- a/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -1980,11 +1980,12 @@ class Parser implements DTDConstants {
void parseScript() throws IOException {
char[] charsToAdd = new char[SCRIPT_END_TAG.length];
+ boolean insideComment = false;
/* Here, ch should be the first character after \";\n" +
+ " var tag2 = \"
\";\n" +
+ " var tag3 = \"
\";\n" +
+ " var tag4 = \"";
+ public static void main(String[] args) throws Exception {
+ new ParserDelegator().parse(new StringReader(html), new MyParserCallback(), true);
+ }
+
+ static class MyParserCallback extends HTMLEditorKit.ParserCallback {
+
+ @Override
+ public void handleComment(char[] data, int pos) {
+ String commentWithoutTags = comment.substring("".length());
+ String str = new String(data);
+ if (!commentWithoutTags.equals(str)) {
+ System.out.println("Sample string:\n" + commentWithoutTags);
+ System.out.println("Returned string:\n" + str);
+ throw new RuntimeException("Test Failed, sample and returned strings are mismatched!");
+ }
+ }
+ }
+
+}
From 075f3e82d97dc41486d93f603f29ebb61859dbcf Mon Sep 17 00:00:00 2001
From: Anton Litvinov
Date: Tue, 21 May 2013 05:02:21 +0400
Subject: [PATCH 026/101] 8005607: Recursion in J2DXErrHandler() Causes a Stack
Overflow on Linux
Reviewed-by: art, anthony, prr
---
.../sun/awt/X11/MotifDnDConstants.java | 42 ++---
.../awt/X11/MotifDnDDropTargetProtocol.java | 40 ++---
.../sun/awt/X11/WindowPropertyGetter.java | 6 +-
.../classes/sun/awt/X11/XConstants.java | 7 +-
.../sun/awt/X11/XDnDDragSourceProtocol.java | 18 +-
.../sun/awt/X11/XDnDDropTargetProtocol.java | 94 +++++-----
.../sun/awt/X11/XDragSourceProtocol.java | 24 +--
.../sun/awt/X11/XDropTargetRegistry.java | 38 ++--
.../classes/sun/awt/X11/XEmbedCanvasPeer.java | 12 +-
.../classes/sun/awt/X11/XErrorHandler.java | 74 +++++++-
.../sun/awt/X11/XErrorHandlerUtil.java | 162 ++++++++++++++++++
.../classes/sun/awt/X11/XQueryTree.java | 6 +-
.../solaris/classes/sun/awt/X11/XToolkit.java | 77 +--------
.../sun/awt/X11/XTranslateCoordinates.java | 6 +-
jdk/src/solaris/classes/sun/awt/X11/XWM.java | 13 +-
.../solaris/classes/sun/awt/X11/XlibUtil.java | 14 +-
.../awt/X11/generator/WrapperGenerator.java | 6 +-
.../solaris/native/sun/awt/awt_GraphicsEnv.c | 50 +++---
.../solaris/native/sun/awt/awt_GraphicsEnv.h | 5 +-
jdk/src/solaris/native/sun/awt/awt_util.c | 14 +-
jdk/src/solaris/native/sun/awt/awt_util.h | 65 +++----
.../native/sun/java2d/opengl/GLXSurfaceData.c | 31 ++--
.../native/sun/java2d/x11/X11SurfaceData.c | 12 +-
jdk/src/solaris/native/sun/xawt/XlibWrapper.c | 6 +-
24 files changed, 478 insertions(+), 344 deletions(-)
create mode 100644 jdk/src/solaris/classes/sun/awt/X11/XErrorHandlerUtil.java
diff --git a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java
index 7ee367d4f86..f35ba1c7e43 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -190,7 +190,7 @@ class MotifDnDConstants {
try {
Native.putLong(data, motifWindow);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
defaultRootWindow,
XA_MOTIF_DRAG_WINDOW.getAtom(),
@@ -198,10 +198,10 @@ class MotifDnDConstants {
XConstants.PropModeReplace,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write motif drag window handle.");
}
@@ -394,7 +394,7 @@ class MotifDnDConstants {
}
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
motifWindow,
XA_MOTIF_DRAG_TARGETS.getAtom(),
@@ -402,15 +402,15 @@ class MotifDnDConstants {
XConstants.PropModeReplace,
data, tableSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
// Create a new motif window and retry.
motifWindow = createMotifWindow();
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
motifWindow,
XA_MOTIF_DRAG_TARGETS.getAtom(),
@@ -418,10 +418,10 @@ class MotifDnDConstants {
XConstants.PropModeReplace,
data, tableSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write motif drag targets property.");
}
}
@@ -534,16 +534,16 @@ class MotifDnDConstants {
// CARD32 icc_handle
unsafe.putInt(structData + 4, (int)XA_MOTIF_ATOM_0.getAtom());
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
XA_MOTIF_ATOM_0.getAtom(),
XA_MOTIF_DRAG_INITIATOR_INFO.getAtom(),
8, XConstants.PropModeReplace,
structData, MOTIF_INITIATOR_INFO_SIZE);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write drag initiator info");
}
} finally {
@@ -567,16 +567,16 @@ class MotifDnDConstants {
unsafe.putShort(data + 10, (short)0); /* pad */
unsafe.putInt(data + 12, dataSize);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
8, XConstants.PropModeReplace,
data, dataSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write Motif receiver info property");
}
} finally {
diff --git a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java
index 030c02f557b..652b9e9e3af 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -162,16 +162,16 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
unsafe.putInt(data + 12, dataSize);
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
8, XConstants.PropModeReplace,
data, dataSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write Motif receiver info property");
}
} finally {
@@ -236,16 +236,16 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
unsafe.putInt(data + 4, tproxy);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
8, XConstants.PropModeReplace,
data, dataSize);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write Motif receiver info property");
}
}
@@ -412,15 +412,15 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
*/
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
source_win, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -429,15 +429,15 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
wattr.dispose();
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
source_win_mask |
XConstants.StructureNotifyMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
@@ -1024,10 +1024,10 @@ class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
if (sourceWindow != 0) {
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
sourceWindowMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
} finally {
XToolkit.awtUnlock();
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java b/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java
index ab7afac304c..0cda6fa2fdf 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/WindowPropertyGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -99,7 +99,7 @@ public class WindowPropertyGetter {
}
if (errorHandler != null) {
- XToolkit.WITH_XERROR_HANDLER(errorHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
}
Native.putLong(data, 0);
int status = XlibWrapper.XGetWindowProperty(XToolkit.getDisplay(), window, property.getAtom(),
@@ -112,7 +112,7 @@ public class WindowPropertyGetter {
}
if (errorHandler != null) {
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
return status;
} finally {
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XConstants.java b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java
index d72ff07273b..e1903d81f40 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XConstants.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -674,4 +674,9 @@ final public class XConstants {
public static final long XkbModifierMapMask = (1L<<2);
public static final long XkbVirtualModsMask = (1L<<6); //server map
+ /*****************************************************************
+ * X SHARED MEMORY EXTENSION FUNCTIONS
+ *****************************************************************/
+
+ public static final int X_ShmAttach = 1;
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java b/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java
index f8ef1dc6d7c..c2da2e69995 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDragSourceProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -96,14 +96,14 @@ class XDnDDragSourceProtocol extends XDragSourceProtocol {
action_count++;
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndActionList.setAtomData(window,
XAtom.XA_ATOM,
data, action_count);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error) != null &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
cleanup();
throw new XException("Cannot write XdndActionList property");
}
@@ -117,14 +117,14 @@ class XDnDDragSourceProtocol extends XDragSourceProtocol {
try {
Native.put(data, formats);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndTypeList.setAtomData(window,
XAtom.XA_ATOM,
data, formats.length);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
cleanup();
throw new XException("Cannot write XdndActionList property");
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java b/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java
index 38c6abb2477..3dc2c96efc9 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDnDDropTargetProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -88,12 +88,12 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol {
try {
Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(window, XAtom.XA_ATOM, data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
} finally {
@@ -205,54 +205,50 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol {
/* The proxy window must have the XdndAware set, as XDnD protocol
prescribes to check the proxy window for XdndAware. */
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(newProxy, XAtom.XA_ATOM,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
Native.putLong(data, 0, newProxy);
/* The proxy window must have the XdndProxy set to point to itself.*/
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndProxy.setAtomData(newProxy, XAtom.XA_WINDOW,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndProxy property");
}
Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
Native.putLong(data, 0, newProxy);
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndProxy property");
}
} finally {
@@ -278,27 +274,25 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol {
try {
Native.putLong(data, 0, entry.getVersion());
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndAware property");
}
Native.putLong(data, 0, (int)entry.getProxy());
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
data, 1);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() !=
- XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("Cannot write XdndProxy property");
}
} finally {
@@ -541,15 +535,15 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol {
*/
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
source_win, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -558,15 +552,15 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol {
wattr.dispose();
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
source_win_mask |
XConstants.StructureNotifyMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
@@ -963,10 +957,10 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol {
if (sourceWindow != 0) {
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
sourceWindowMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
} finally {
XToolkit.awtUnlock();
}
@@ -1111,15 +1105,15 @@ class XDnDDropTargetProtocol extends XDropTargetProtocol {
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XDnDConstants.XA_XdndTypeList.setAtomData(xclient.get_window(),
XAtom.XA_ATOM,
wpg.getData(),
wpg.getNumberOfItems());
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
if (logger.isLoggable(PlatformLogger.WARNING)) {
logger.warning("Cannot set XdndTypeList on the proxy window");
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java b/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java
index 2ef5a504ceb..af25f6b8652 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDragSourceProtocol.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -181,15 +181,15 @@ abstract class XDragSourceProtocol {
long time) {
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
targetWindow, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -198,15 +198,15 @@ abstract class XDragSourceProtocol {
wattr.dispose();
}
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
targetWindowMask |
XConstants.StructureNotifyMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
@@ -214,10 +214,10 @@ abstract class XDragSourceProtocol {
}
protected final void finalizeDrop() {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
targetWindowMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
public abstract boolean processProxyModeEvent(XClientMessageEvent xclient,
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java b/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java
index be1a518eb15..f08db55c2b3 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -168,14 +168,14 @@ final class XDropTargetRegistry {
if (dest_x >= 0 && dest_y >= 0) {
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
window, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
continue;
}
@@ -222,14 +222,14 @@ final class XDropTargetRegistry {
long event_mask = 0;
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
embedder, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
throw new XException("XGetWindowAttributes failed");
}
@@ -240,13 +240,13 @@ final class XDropTargetRegistry {
}
if ((event_mask & XConstants.PropertyChangeMask) == 0) {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
event_mask | XConstants.PropertyChangeMask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
}
@@ -394,13 +394,13 @@ final class XDropTargetRegistry {
/* Restore the original event mask for the embedder. */
if ((event_mask & XConstants.PropertyChangeMask) == 0) {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
event_mask);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
throw new XException("XSelectInput failed");
}
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java
index 2c3bb349cff..194eb8f7511 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedCanvasPeer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -301,15 +301,15 @@ public class XEmbedCanvasPeer extends XCanvasPeer implements WindowFocusListener
try {
XWindowAttributes wattr = new XWindowAttributes();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
xembed.handle, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (status == 0 ||
- (XToolkit.saved_error != null &&
- XToolkit.saved_error.get_error_code() != XConstants.Success)) {
+ if ((status == 0) ||
+ ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
return null;
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java
index 26e563b2655..ec09cea5198 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -38,7 +38,30 @@ public abstract class XErrorHandler {
public static class XBaseErrorHandler extends XErrorHandler {
@Override
public int handleError(long display, XErrorEvent err) {
- return XToolkit.SAVED_ERROR_HANDLER(display, err);
+ return XErrorHandlerUtil.SAVED_XERROR_HANDLER(display, err);
+ }
+ }
+
+ /**
+ * This is a base synthetic error handler containing a boolean flag which allows
+ * to show that an error is handled or not.
+ */
+ public static class XErrorHandlerWithFlag extends XBaseErrorHandler {
+ private volatile boolean errorOccurred = false;
+
+ public boolean getErrorOccurredFlag() {
+ return errorOccurred;
+ }
+
+ /**
+ * Sets an internal boolean flag to a particular value. Should be always called with
+ * false value of the parameter errorOccurred before this
+ * error handler is set as current.
+ * @param errorOccurred true to indicate that an error was handled,
+ * false to reset the internal boolean flag
+ */
+ public void setErrorOccurredFlag(boolean errorOccurred) {
+ this.errorOccurred = errorOccurred;
}
}
@@ -76,4 +99,51 @@ public abstract class XErrorHandler {
return theInstance;
}
}
+
+ /**
+ * This is a synthetic error handler for errors generated by the native function
+ * XShmAttach. If an error is handled, an internal boolean flag of the
+ * handler is set to true.
+ */
+ public static final class XShmAttachHandler extends XErrorHandlerWithFlag {
+ private XShmAttachHandler() {}
+
+ @Override
+ public int handleError(long display, XErrorEvent err) {
+ if (err.get_minor_code() == XConstants.X_ShmAttach) {
+ setErrorOccurredFlag(true);
+ return 0;
+ }
+ return super.handleError(display, err);
+ }
+
+ // Shared instance
+ private static XShmAttachHandler theInstance = new XShmAttachHandler();
+ public static XShmAttachHandler getInstance() {
+ return theInstance;
+ }
+ }
+
+ /**
+ * This is a synthetic error handler for BadAlloc errors generated by the
+ * native glX* functions. Its internal boolean flag is set to true,
+ * if an error is handled.
+ */
+ public static final class GLXBadAllocHandler extends XErrorHandlerWithFlag {
+ private GLXBadAllocHandler() {}
+
+ @Override
+ public int handleError(long display, XErrorEvent err) {
+ if (err.get_error_code() == XConstants.BadAlloc) {
+ setErrorOccurredFlag(true);
+ return 0;
+ }
+ return super.handleError(display, err);
+ }
+
+ private static GLXBadAllocHandler theInstance = new GLXBadAllocHandler();
+ public static GLXBadAllocHandler getInstance() {
+ return theInstance;
+ }
+ }
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XErrorHandlerUtil.java b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandlerUtil.java
new file mode 100644
index 00000000000..500226a0403
--- /dev/null
+++ b/jdk/src/solaris/classes/sun/awt/X11/XErrorHandlerUtil.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 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 sun.awt.X11;
+
+import java.security.AccessController;
+import sun.awt.SunToolkit;
+import sun.security.action.GetBooleanAction;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * This class contains code of the global toolkit error handler, exposes static
+ * methods which allow to set and unset synthetic error handlers.
+ */
+public final class XErrorHandlerUtil {
+ private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XErrorHandlerUtil");
+
+ /**
+ * The connection to X11 window server.
+ */
+ private static long display;
+
+ /**
+ * Error handler at the moment of XErrorHandlerUtil initialization.
+ */
+ private static long saved_error_handler;
+
+ /**
+ * XErrorEvent being handled.
+ */
+ static volatile XErrorEvent saved_error;
+
+ /**
+ * Current error handler or null if no error handler is set.
+ */
+ private static XErrorHandler current_error_handler;
+
+ /**
+ * Value of sun.awt.noisyerrorhandler system property.
+ */
+ private static boolean noisyAwtHandler = AccessController.doPrivileged(
+ new GetBooleanAction("sun.awt.noisyerrorhandler"));
+
+ /**
+ * The flag indicating that init was called already.
+ */
+ private static boolean initPassed;
+
+ /**
+ * Guarantees that no instance of this class can be created.
+ */
+ private XErrorHandlerUtil() {}
+
+ /**
+ * Sets the toolkit global error handler, stores the connection to X11 server, which
+ * will be used during an error handling process. This method is called once from
+ * awt_init_Display function defined in awt_GraphicsEnv.c
+ * file immediately after the connection to X11 window server is opened.
+ * @param display the connection to X11 server which should be stored
+ */
+ private static void init(long display) {
+ SunToolkit.awtLock();
+ try {
+ if (!initPassed) {
+ XErrorHandlerUtil.display = display;
+ saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
+ initPassed = true;
+ }
+ } finally {
+ SunToolkit.awtUnlock();
+ }
+ }
+
+ /**
+ * Sets a synthetic error handler. Must be called with the acquired AWT lock.
+ * @param handler the synthetic error handler to set
+ */
+ public static void WITH_XERROR_HANDLER(XErrorHandler handler) {
+ saved_error = null;
+ current_error_handler = handler;
+ }
+
+ /**
+ * Unsets a current synthetic error handler. Must be called with the acquired AWT lock.
+ */
+ public static void RESTORE_XERROR_HANDLER() {
+ // Wait until all requests are processed by the X server
+ // and only then uninstall the error handler.
+ XSync();
+ current_error_handler = null;
+ }
+
+ /**
+ * Should be called under LOCK.
+ */
+ public static int SAVED_XERROR_HANDLER(long display, XErrorEvent error) {
+ if (saved_error_handler != 0) {
+ // Default XErrorHandler may just terminate the process. Don't call it.
+ // return XlibWrapper.CallErrorHandler(saved_error_handler, display, error.pData);
+ }
+ if (log.isLoggable(PlatformLogger.FINE)) {
+ log.fine("Unhandled XErrorEvent: " +
+ "id=" + error.get_resourceid() + ", " +
+ "serial=" + error.get_serial() + ", " +
+ "ec=" + error.get_error_code() + ", " +
+ "rc=" + error.get_request_code() + ", " +
+ "mc=" + error.get_minor_code());
+ }
+ return 0;
+ }
+
+ /**
+ * Called from the native code when an error occurs.
+ */
+ private static int globalErrorHandler(long display, long event_ptr) {
+ if (noisyAwtHandler) {
+ XlibWrapper.PrintXErrorEvent(display, event_ptr);
+ }
+ XErrorEvent event = new XErrorEvent(event_ptr);
+ saved_error = event;
+ try {
+ if (current_error_handler != null) {
+ return current_error_handler.handleError(display, event);
+ } else {
+ return SAVED_XERROR_HANDLER(display, event);
+ }
+ } catch (Throwable z) {
+ log.fine("Error in GlobalErrorHandler", z);
+ }
+ return 0;
+ }
+
+ private static void XSync() {
+ SunToolkit.awtLock();
+ try {
+ XlibWrapper.XSync(display, 0);
+ } finally {
+ SunToolkit.awtUnlock();
+ }
+ }
+}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java b/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java
index 94921826cbc..dede21f6e30 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XQueryTree.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -61,7 +61,7 @@ public class XQueryTree {
}
__executed = true;
if (errorHandler != null) {
- XToolkit.WITH_XERROR_HANDLER(errorHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
}
Native.putLong(children_ptr, 0);
int status =
@@ -72,7 +72,7 @@ public class XQueryTree {
children_ptr,
nchildren_ptr );
if (errorHandler != null) {
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
return status;
} finally {
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java
index 68658d6b5a0..607537cdaa4 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -128,7 +128,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
initIDs();
setBackingStoreType();
}
- noisyAwtHandler = AccessController.doPrivileged(new GetBooleanAction("sun.awt.noisyerrorhandler"));
}
/*
@@ -137,78 +136,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
*/
static native long getTrayIconDisplayTimeout();
- //---- ERROR HANDLER CODE ----//
-
- /*
- * Error handler at the moment of XToolkit initialization
- */
- private static long saved_error_handler;
-
- /*
- * XErrorEvent being handled
- */
- static volatile XErrorEvent saved_error;
-
- /*
- * Current error handler or null if no error handler is set
- */
- private static XErrorHandler current_error_handler;
-
- /*
- * Value of sun.awt.noisyerrorhandler system property
- */
- private static boolean noisyAwtHandler;
-
- public static void WITH_XERROR_HANDLER(XErrorHandler handler) {
- saved_error = null;
- current_error_handler = handler;
- }
-
- public static void RESTORE_XERROR_HANDLER() {
- // wait until all requests are processed by the X server
- // and only then uninstall the error handler
- XSync();
- current_error_handler = null;
- }
-
- // Should be called under LOCK
- public static int SAVED_ERROR_HANDLER(long display, XErrorEvent error) {
- if (saved_error_handler != 0) {
- // Default XErrorHandler may just terminate the process. Don't call it.
- // return XlibWrapper.CallErrorHandler(saved_error_handler, display, error.pData);
- }
- if (log.isLoggable(PlatformLogger.FINE)) {
- log.fine("Unhandled XErrorEvent: " +
- "id=" + error.get_resourceid() + ", " +
- "serial=" + error.get_serial() + ", " +
- "ec=" + error.get_error_code() + ", " +
- "rc=" + error.get_request_code() + ", " +
- "mc=" + error.get_minor_code());
- }
- return 0;
- }
-
- // Called from the native code when an error occurs
- private static int globalErrorHandler(long display, long event_ptr) {
- if (noisyAwtHandler) {
- XlibWrapper.PrintXErrorEvent(display, event_ptr);
- }
- XErrorEvent event = new XErrorEvent(event_ptr);
- saved_error = event;
- try {
- if (current_error_handler != null) {
- return current_error_handler.handleError(display, event);
- } else {
- return SAVED_ERROR_HANDLER(display, event);
- }
- } catch (Throwable z) {
- log.fine("Error in GlobalErrorHandler", z);
- }
- return 0;
- }
-
- //---- END OF ERROR HANDLER CODE ----//
-
private native static void initIDs();
native static void waitForEvents(long nextTaskTime);
static Thread toolkitThread;
@@ -306,8 +233,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
//set system property if not yet assigned
System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled);
- saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
-
// Detect display mode changes
XlibWrapper.XSelectInput(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), XConstants.StructureNotifyMask);
XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), new XEventDispatcher() {
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java b/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java
index ba805a472b0..42a3a42844e 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XTranslateCoordinates.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -68,7 +68,7 @@ public class XTranslateCoordinates {
}
__executed = true;
if (errorHandler != null) {
- XToolkit.WITH_XERROR_HANDLER(errorHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);
}
int status =
XlibWrapper.XTranslateCoordinates(XToolkit.getDisplay(),
@@ -80,7 +80,7 @@ public class XTranslateCoordinates {
dest_y_ptr,
child_ptr );
if (errorHandler != null) {
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
}
return status;
} finally {
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XWM.java b/jdk/src/solaris/classes/sun/awt/X11/XWM.java
index 6dd929460c9..94410519dca 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XWM.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -284,12 +284,12 @@ final class XWM
winmgr_running = false;
substruct.set_event_mask(XConstants.SubstructureRedirectMask);
- XToolkit.WITH_XERROR_HANDLER(detectWMHandler);
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(detectWMHandler);
XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
XToolkit.getDefaultRootWindow(),
XConstants.CWEventMask,
substruct.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
/*
* If no WM is running then our selection for SubstructureRedirect
@@ -632,15 +632,16 @@ final class XWM
XToolkit.awtLock();
try {
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangePropertyS(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
XA_ICEWM_WINOPTHINT.getAtom(),
XA_ICEWM_WINOPTHINT.getAtom(),
8, XConstants.PropModeReplace,
new String(opt));
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
- if (XToolkit.saved_error != null && XToolkit.saved_error.get_error_code() != XConstants.Success) {
+ if ((XErrorHandlerUtil.saved_error != null) &&
+ (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
log.finer("Erorr getting XA_ICEWM_WINOPTHINT property");
return false;
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java b/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java
index 875ab16f642..f06af9856ae 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/XlibUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -151,8 +151,8 @@ public class XlibUtil
{
int status = xtc.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
if ((status != 0) &&
- ((XToolkit.saved_error == null) ||
- (XToolkit.saved_error.get_error_code() == XConstants.Success)))
+ ((XErrorHandlerUtil.saved_error == null) ||
+ (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success)))
{
translated = new Point(xtc.get_dest_x(), xtc.get_dest_y());
}
@@ -345,13 +345,13 @@ public class XlibUtil
XWindowAttributes wattr = new XWindowAttributes();
try
{
- XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
+ XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
window, wattr.pData);
- XToolkit.RESTORE_XERROR_HANDLER();
+ XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
if ((status != 0) &&
- ((XToolkit.saved_error == null) ||
- (XToolkit.saved_error.get_error_code() == XConstants.Success)))
+ ((XErrorHandlerUtil.saved_error == null) ||
+ (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success)))
{
return wattr.get_map_state();
}
diff --git a/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java b/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java
index fd66a03fda5..9da0fd93442 100644
--- a/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java
+++ b/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -996,7 +996,7 @@ public class WrapperGenerator {
pw.println("\t\t\t}");
pw.println("\t\t\t__executed = true;");
pw.println("\t\t\tif (errorHandler != null) {");
- pw.println("\t\t\t XToolkit.WITH_XERROR_HANDLER(errorHandler);");
+ pw.println("\t\t\t XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler);");
pw.println("\t\t\t}");
iter = ft.getArguments().iterator();
while (iter.hasNext()) {
@@ -1025,7 +1025,7 @@ public class WrapperGenerator {
}
pw.println("\t\t\t);");
pw.println("\t\t\tif (errorHandler != null) {");
- pw.println("\t\t\t XToolkit.RESTORE_XERROR_HANDLER();");
+ pw.println("\t\t\t XErrorHandlerUtil.RESTORE_XERROR_HANDLER();");
pw.println("\t\t\t}");
if (!ft.isVoid()) {
pw.println("\t\t\treturn status;");
diff --git a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c
index 7ae4cdd3259..0c62dca97a2 100644
--- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -758,6 +758,8 @@ awt_init_Display(JNIEnv *env, jobject this)
}
XSetIOErrorHandler(xioerror_handler);
+ JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V",
+ ptr_to_jlong(awt_display));
/* set awt_numScreens, and whether or not we're using Xinerama */
xineramaInit();
@@ -904,28 +906,12 @@ Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this)
static jint canUseShmExt = UNSET_MITSHM;
static jint canUseShmExtPixmaps = UNSET_MITSHM;
-static jboolean xshmAttachFailed = JNI_FALSE;
-
-int J2DXErrHandler(Display *display, XErrorEvent *xerr) {
- int ret = 0;
- if (xerr->minor_code == X_ShmAttach) {
- xshmAttachFailed = JNI_TRUE;
- } else {
- ret = (*xerror_saved_handler)(display, xerr);
- }
- return ret;
-}
-jboolean isXShmAttachFailed() {
- return xshmAttachFailed;
-}
-void resetXShmAttachFailed() {
- xshmAttachFailed = JNI_FALSE;
-}
void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
XShmSegmentInfo shminfo;
int XShmMajor, XShmMinor;
int a, b, c;
+ jboolean xShmAttachResult;
AWT_LOCK();
if (canUseShmExt != UNSET_MITSHM) {
@@ -963,21 +949,14 @@ void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
}
shminfo.readOnly = True;
- resetXShmAttachFailed();
- /**
- * The J2DXErrHandler handler will set xshmAttachFailed
- * to JNI_TRUE if any Shm error has occured.
- */
- EXEC_WITH_XERROR_HANDLER(J2DXErrHandler,
- XShmAttach(awt_display, &shminfo));
-
+ xShmAttachResult = TryXShmAttach(env, awt_display, &shminfo);
/**
* Get rid of the id now to reduce chances of leaking
* system resources.
*/
shmctl(shminfo.shmid, IPC_RMID, 0);
- if (isXShmAttachFailed() == JNI_FALSE) {
+ if (xShmAttachResult == JNI_TRUE) {
canUseShmExt = CAN_USE_MITSHM;
/* check if we can use shared pixmaps */
XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,
@@ -992,6 +971,23 @@ void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
}
AWT_UNLOCK();
}
+
+/*
+ * Must be called with the acquired AWT lock.
+ */
+jboolean TryXShmAttach(JNIEnv *env, Display *display, XShmSegmentInfo *shminfo) {
+ jboolean errorOccurredFlag = JNI_FALSE;
+ jobject errorHandlerRef;
+
+ /*
+ * XShmAttachHandler will set its internal flag to JNI_TRUE, if any Shm error occurs.
+ */
+ EXEC_WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$XShmAttachHandler",
+ "()Lsun/awt/X11/XErrorHandler$XShmAttachHandler;", JNI_TRUE,
+ errorHandlerRef, errorOccurredFlag,
+ XShmAttach(display, shminfo));
+ return errorOccurredFlag == JNI_FALSE ? JNI_TRUE : JNI_FALSE;
+}
#endif /* MITSHM */
/*
diff --git a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h
index 39ea6d596a5..cb06ae1bd08 100644
--- a/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h
+++ b/jdk/src/solaris/native/sun/awt/awt_GraphicsEnv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -50,8 +50,7 @@
extern int XShmQueryExtension();
void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps);
-void resetXShmAttachFailed();
-jboolean isXShmAttachFailed();
+jboolean TryXShmAttach(JNIEnv *env, Display *display, XShmSegmentInfo *shminfo);
#endif /* MITSHM */
diff --git a/jdk/src/solaris/native/sun/awt/awt_util.c b/jdk/src/solaris/native/sun/awt/awt_util.c
index f1f897c1564..d92c96e5e92 100644
--- a/jdk/src/solaris/native/sun/awt/awt_util.c
+++ b/jdk/src/solaris/native/sun/awt/awt_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -41,18 +41,6 @@
#include "java_awt_event_MouseWheelEvent.h"
-/*
- * Since X reports protocol errors asynchronously, we often need to
- * install an error handler that acts like a callback. While that
- * specialized handler is installed we save original handler here.
- */
-XErrorHandler xerror_saved_handler;
-
-/*
- * A place for error handler to report the error code.
- */
-unsigned char xerror_code;
-
extern jint getModifiers(uint32_t state, jint button, jint keyCode);
extern jint getButton(uint32_t button);
diff --git a/jdk/src/solaris/native/sun/awt/awt_util.h b/jdk/src/solaris/native/sun/awt/awt_util.h
index 5fb113fc405..6e350727806 100644
--- a/jdk/src/solaris/native/sun/awt/awt_util.h
+++ b/jdk/src/solaris/native/sun/awt/awt_util.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -29,42 +29,47 @@
#ifndef HEADLESS
#include "gdefs.h"
-#define WITH_XERROR_HANDLER(f) do { \
- XSync(awt_display, False); \
- xerror_code = Success; \
- xerror_saved_handler = XSetErrorHandler(f); \
-} while (0)
-
-/* Convenience macro for handlers to use */
-#define XERROR_SAVE(err) do { \
- xerror_code = (err)->error_code; \
-} while (0)
-
-#define RESTORE_XERROR_HANDLER do { \
- XSync(awt_display, False); \
- XSetErrorHandler(xerror_saved_handler); \
-} while (0)
-
-#define EXEC_WITH_XERROR_HANDLER(f, code) do { \
- WITH_XERROR_HANDLER(f); \
- do { \
- code; \
- } while (0); \
- RESTORE_XERROR_HANDLER; \
+/*
+ * Expected types of arguments of the macro.
+ * (JNIEnv*, const char*, const char*, jboolean, jobject)
+ */
+#define WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, \
+ handlerHasFlag, handlerRef) do { \
+ handlerRef = JNU_CallStaticMethodByName(env, NULL, handlerClassName, "getInstance", \
+ getInstanceSignature).l; \
+ if (handlerHasFlag == JNI_TRUE) { \
+ JNU_CallMethodByName(env, NULL, handlerRef, "setErrorOccurredFlag", "(Z)V", JNI_FALSE); \
+ } \
+ JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "WITH_XERROR_HANDLER", \
+ "(Lsun/awt/X11/XErrorHandler;)V", handlerRef); \
} while (0)
/*
- * Since X reports protocol errors asynchronously, we often need to
- * install an error handler that acts like a callback. While that
- * specialized handler is installed we save original handler here.
+ * Expected types of arguments of the macro.
+ * (JNIEnv*)
*/
-extern XErrorHandler xerror_saved_handler;
+#define RESTORE_XERROR_HANDLER(env) do { \
+ JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", \
+ "RESTORE_XERROR_HANDLER", "()V"); \
+} while (0)
/*
- * A place for error handler to report the error code.
+ * Expected types of arguments of the macro.
+ * (JNIEnv*, const char*, const char*, jboolean, jobject, jboolean, No type - C expression)
*/
-extern unsigned char xerror_code;
-
+#define EXEC_WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, handlerHasFlag, \
+ handlerRef, errorOccurredFlag, code) do { \
+ handlerRef = NULL; \
+ WITH_XERROR_HANDLER(env, handlerClassName, getInstanceSignature, handlerHasFlag, handlerRef); \
+ do { \
+ code; \
+ } while (0); \
+ RESTORE_XERROR_HANDLER(env); \
+ if (handlerHasFlag == JNI_TRUE) { \
+ errorOccurredFlag = JNU_CallMethodByName(env, NULL, handlerRef, "getErrorOccurredFlag", \
+ "()Z").z; \
+ } \
+} while (0)
#endif /* !HEADLESS */
#ifndef INTERSECTS
diff --git a/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c
index a9549e0cd03..4a4e75f6228 100644
--- a/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c
+++ b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -48,8 +48,6 @@ extern DisposeFunc OGLSD_Dispose;
extern void
OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);
-jboolean surfaceCreationFailed = JNI_FALSE;
-
#endif /* !HEADLESS */
JNIEXPORT void JNICALL
@@ -349,18 +347,6 @@ OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
return JNI_TRUE;
}
-static int
-GLXSD_BadAllocXErrHandler(Display *display, XErrorEvent *xerr)
-{
- int ret = 0;
- if (xerr->error_code == BadAlloc) {
- surfaceCreationFailed = JNI_TRUE;
- } else {
- ret = (*xerror_saved_handler)(display, xerr);
- }
- return ret;
-}
-
JNIEXPORT jboolean JNICALL
Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer
(JNIEnv *env, jobject glxsd,
@@ -376,6 +362,8 @@ Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer
int attrlist[] = {GLX_PBUFFER_WIDTH, 0,
GLX_PBUFFER_HEIGHT, 0,
GLX_PRESERVED_CONTENTS, GL_FALSE, 0};
+ jboolean errorOccurredFlag;
+ jobject errorHandlerRef;
J2dTraceLn3(J2D_TRACE_INFO,
"GLXSurfaceData_initPbuffer: w=%d h=%d opq=%d",
@@ -403,12 +391,13 @@ Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer
attrlist[1] = width;
attrlist[3] = height;
- surfaceCreationFailed = JNI_FALSE;
- EXEC_WITH_XERROR_HANDLER(
- GLXSD_BadAllocXErrHandler,
- pbuffer = j2d_glXCreatePbuffer(awt_display,
- glxinfo->fbconfig, attrlist));
- if ((pbuffer == 0) || surfaceCreationFailed) {
+ errorOccurredFlag = JNI_FALSE;
+ EXEC_WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$GLXBadAllocHandler",
+ "()Lsun/awt/X11/XErrorHandler$GLXBadAllocHandler;", JNI_TRUE,
+ errorHandlerRef, errorOccurredFlag,
+ pbuffer = j2d_glXCreatePbuffer(awt_display, glxinfo->fbconfig, attrlist));
+
+ if ((pbuffer == 0) || errorOccurredFlag) {
J2dRlsTraceLn(J2D_TRACE_ERROR,
"GLXSurfaceData_initPbuffer: could not create glx pbuffer");
return JNI_FALSE;
diff --git a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c
index cee9bb75bfd..57e121701ff 100644
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -65,7 +65,6 @@ static UnlockFunc X11SD_Unlock;
static DisposeFunc X11SD_Dispose;
static GetPixmapBgFunc X11SD_GetPixmapWithBg;
static ReleasePixmapBgFunc X11SD_ReleasePixmapWithBg;
-extern int J2DXErrHandler(Display *display, XErrorEvent *xerr);
extern AwtGraphicsConfigDataPtr
getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this);
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
@@ -521,6 +520,8 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo,
{
XImage *img = NULL;
XShmSegmentInfo *shminfo;
+ JNIEnv* env;
+ jboolean xShmAttachResult;
shminfo = malloc(sizeof(XShmSegmentInfo));
if (shminfo == NULL) {
@@ -559,9 +560,8 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo,
shminfo->readOnly = False;
- resetXShmAttachFailed();
- EXEC_WITH_XERROR_HANDLER(J2DXErrHandler,
- XShmAttach(awt_display, shminfo));
+ env = (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+ xShmAttachResult = TryXShmAttach(env, awt_display, shminfo);
/*
* Once the XSync round trip has finished then we
@@ -570,7 +570,7 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo,
*/
shmctl(shminfo->shmid, IPC_RMID, 0);
- if (isXShmAttachFailed() == JNI_TRUE) {
+ if (xShmAttachResult == JNI_FALSE) {
J2dRlsTraceLn1(J2D_TRACE_ERROR,
"X11SD_SetupSharedSegment XShmAttach has failed: %s",
strerror(errno));
diff --git a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c
index f48e833ad2d..ac6506c5a3c 100644
--- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c
+++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -1264,8 +1264,8 @@ static int ToolkitErrorHandler(Display * dpy, XErrorEvent * event) {
if (jvm != NULL) {
env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (env) {
- return JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XToolkit", "globalErrorHandler", "(JJ)I",
- ptr_to_jlong(dpy), ptr_to_jlong(event)).i;
+ return JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil",
+ "globalErrorHandler", "(JJ)I", ptr_to_jlong(dpy), ptr_to_jlong(event)).i;
}
}
return 0;
From aa649f097f319dc96ed7aa4f09a9674f8ec16545 Mon Sep 17 00:00:00 2001
From: David Holmes
Date: Tue, 21 May 2013 01:17:46 -0400
Subject: [PATCH 027/101] 8014857: Enable ergonomic VM selection in arm/jvm.cfg
Reviewed-by: darcy
---
jdk/src/solaris/bin/arm/jvm.cfg | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/jdk/src/solaris/bin/arm/jvm.cfg b/jdk/src/solaris/bin/arm/jvm.cfg
index e93034166b2..c46211325bc 100644
--- a/jdk/src/solaris/bin/arm/jvm.cfg
+++ b/jdk/src/solaris/bin/arm/jvm.cfg
@@ -30,6 +30,6 @@
# "-XXaltjvm=" option, but that too is unsupported
# and may not be available in a future release.
#
--client KNOWN
+-client IF_SERVER_CLASS -server
-server KNOWN
-minimal KNOWN
From 4ebf44cbe4a59c2e9d86e94df8d7c9a6a666232f Mon Sep 17 00:00:00 2001
From: Yong Jeffrey Huang
Date: Mon, 20 May 2013 23:03:35 -0700
Subject: [PATCH 028/101] 7074882: Locale data needs correction (Month names
for Maltese language)
Reviewed-by: naoto
---
.../share/classes/sun/text/resources/mt/FormatData_mt.java | 4 ++--
jdk/test/sun/text/resources/LocaleData | 4 ++++
jdk/test/sun/text/resources/LocaleDataTest.java | 2 +-
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java b/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java
index 056762fff14..12f266c5a26 100644
--- a/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java
+++ b/jdk/src/share/classes/sun/text/resources/mt/FormatData_mt.java
@@ -54,7 +54,7 @@ public class FormatData_mt extends ParallelListResourceBundle {
"Mejju",
"\u0120unju",
"Lulju",
- "Awissu",
+ "Awwissu",
"Settembru",
"Ottubru",
"Novembru",
@@ -71,7 +71,7 @@ public class FormatData_mt extends ParallelListResourceBundle {
"Mej",
"\u0120un",
"Lul",
- "Awi",
+ "Aww",
"Set",
"Ott",
"Nov",
diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData
index 87b9d44cb27..7d95a57d7ba 100644
--- a/jdk/test/sun/text/resources/LocaleData
+++ b/jdk/test/sun/text/resources/LocaleData
@@ -7663,3 +7663,7 @@ CurrencyNames//ZMW=ZMW
# bug 7114053
LocaleNames/sq/sq=shqip
+
+# bug 7074882
+FormatData/mt/MonthNames/7=Awwissu
+FormatData/mt/MonthAbbreviations/7=Aww
diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java
index 3fce3f6c36d..ca5d7fee153 100644
--- a/jdk/test/sun/text/resources/LocaleDataTest.java
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java
@@ -35,7 +35,7 @@
* 6645405 6650730 6910489 6573250 6870908 6585666 6716626 6914413 6916787
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
- * 7114053
+ * 7114053 7074882
* @summary Verify locale data
*
*/
From e2ffa5a3154c01aa4216f5b220626804787164d3 Mon Sep 17 00:00:00 2001
From: Amy Lu
Date: Tue, 21 May 2013 08:53:51 +0100
Subject: [PATCH 029/101] 8014892: More ProblemList.txt updates (5/2013)
Reviewed-by: alanb
---
jdk/test/ProblemList.txt | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index 56967a8bd22..734e68a0354 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -137,15 +137,12 @@ java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all
# 8008200
java/lang/Class/asSubclass/BasicUnit.java generic-all
-# 8009552
-vm/verifier/TestStaticIF.java generic-all
-
############################################################################
# jdk_management
# 8010897
-sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java macosx-all
+sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java macosx-all
############################################################################
@@ -305,9 +302,6 @@ sun/security/krb5/auto/BadKdc4.java solaris-sparcv9
# 7194428
sun/security/mscapi/ShortRSAKey1024.sh windows-all
-# 8000897, vm crash
-sun/security/provider/DSA/TestAlgParameterGenerator.java generic-all
-
# 7144048, performance issue
sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java generic-all
@@ -338,12 +332,9 @@ sun/tools/jconsole/ImmutableResourceTest.sh generic-all
sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
# Tests take too long, on sparcs see 7143279
-tools/pack200/CommandLineTests.java solaris-all, macosx-all
+tools/pack200/CommandLineTests.java solaris-all, macosx-all
tools/pack200/Pack200Test.java solaris-all, macosx-all
-# 7150569
-tools/launcher/UnicodeTest.java macosx-all
-
# 8007410
tools/launcher/FXLauncherTest.java linux-all
From 1a3b9278eb287f71508fa1ac2ecf77b1266d283a Mon Sep 17 00:00:00 2001
From: Attila Szegedi
Date: Tue, 21 May 2013 13:40:12 +0200
Subject: [PATCH 030/101] 8014953: Have NativeJavaPackage throw a
ClassNotFoundException when invoked
Reviewed-by: jlaskey, sundar
---
.../internal/runtime/NativeJavaPackage.java | 37 +++++++++++++++
nashorn/test/script/basic/JDK-8014953.js | 45 +++++++++++++++++++
.../test/script/basic/JDK-8014953.js.EXPECTED | 6 +++
3 files changed, 88 insertions(+)
create mode 100644 nashorn/test/script/basic/JDK-8014953.js
create mode 100644 nashorn/test/script/basic/JDK-8014953.js.EXPECTED
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
index b10b72df0ac..883ff85cf1f 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@@ -25,10 +25,16 @@
package jdk.nashorn.internal.runtime;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
import jdk.nashorn.internal.objects.NativeJava;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -65,6 +71,10 @@ import jdk.nashorn.internal.objects.annotations.Function;
*
*/
public final class NativeJavaPackage extends ScriptObject {
+ private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+ private static final MethodHandle CLASS_NOT_FOUND = findOwnMH("classNotFound", Void.TYPE, NativeJavaPackage.class);
+ private static final MethodHandle TYPE_GUARD = Guards.getClassGuard(NativeJavaPackage.class);
+
/** Full name of package (includes path.) */
private final String name;
@@ -123,6 +133,30 @@ public final class NativeJavaPackage extends ScriptObject {
return super.getDefaultValue(hint);
}
+ @Override
+ protected GuardedInvocation findNewMethod(CallSiteDescriptor desc) {
+ return createClassNotFoundInvocation(desc);
+ }
+
+ @Override
+ protected GuardedInvocation findCallMethod(CallSiteDescriptor desc, LinkRequest request) {
+ return createClassNotFoundInvocation(desc);
+ }
+
+ private static GuardedInvocation createClassNotFoundInvocation(final CallSiteDescriptor desc) {
+ // If NativeJavaPackage is invoked either as a constructor or as a function, throw a ClassNotFoundException as
+ // we can assume the user attempted to instantiate a non-existent class.
+ final MethodType type = desc.getMethodType();
+ return new GuardedInvocation(
+ MH.dropArguments(CLASS_NOT_FOUND, 1, type.parameterList().subList(1, type.parameterCount())),
+ type.parameterType(0) == NativeJavaPackage.class ? null : TYPE_GUARD);
+ }
+
+ @SuppressWarnings("unused")
+ private static void classNotFound(final NativeJavaPackage pkg) throws ClassNotFoundException {
+ throw new ClassNotFoundException(pkg.name);
+ }
+
/**
* "No such property" call placeholder.
*
@@ -188,4 +222,7 @@ public final class NativeJavaPackage extends ScriptObject {
return noSuchProperty(desc, request);
}
+ private static MethodHandle findOwnMH(final String name, final Class> rtype, final Class>... types) {
+ return MH.findStatic(MethodHandles.lookup(), NativeJavaPackage.class, name, MH.type(rtype, types));
+ }
}
diff --git a/nashorn/test/script/basic/JDK-8014953.js b/nashorn/test/script/basic/JDK-8014953.js
new file mode 100644
index 00000000000..ba7cef0f9ef
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8014953.js
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8014953: Have NativeJavaPackage throw a ClassNotFoundException when invoked with "new"
+ *
+ * @test
+ * @run
+ */
+
+try {
+ new java.util.ArrrayList(16)
+} catch(e) {
+ print("Invoked as constructor");
+ print("e.class=" + e.class)
+ print("e.message=" + e.message);
+}
+
+try {
+ java.util.ArrrayList(16)
+} catch(e) {
+ print("Invoked as method");
+ print("e.class=" + e.class)
+ print("e.message=" + e.message);
+}
diff --git a/nashorn/test/script/basic/JDK-8014953.js.EXPECTED b/nashorn/test/script/basic/JDK-8014953.js.EXPECTED
new file mode 100644
index 00000000000..d371112156b
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8014953.js.EXPECTED
@@ -0,0 +1,6 @@
+Invoked as constructor
+e.class=class java.lang.ClassNotFoundException
+e.message=java.util.ArrrayList
+Invoked as method
+e.class=class java.lang.ClassNotFoundException
+e.message=java.util.ArrrayList
From 9e9c04939b7e647a72b0f55ccfdb19f91317c328 Mon Sep 17 00:00:00 2001
From: James Laskey
Date: Tue, 21 May 2013 10:17:09 -0300
Subject: [PATCH 031/101] 8014827: readLine should accept a prompt as an
argument
Reviewed-by: sundar, hannesw
---
.../nashorn/internal/runtime/ScriptingFunctions.java | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
index 596ec1bf955..1d046ca96c8 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
@@ -46,7 +46,7 @@ import java.util.StringTokenizer;
public final class ScriptingFunctions {
/** Handle to implementation of {@link ScriptingFunctions#readLine} - Nashorn extension */
- public static final MethodHandle READLINE = findOwnMH("readLine", Object.class, Object.class);
+ public static final MethodHandle READLINE = findOwnMH("readLine", Object.class, Object.class, Object.class);
/** Handle to implementation of {@link ScriptingFunctions#readFully} - Nashorn extension */
public static final MethodHandle READFULLY = findOwnMH("readFully", Object.class, Object.class, Object.class);
@@ -78,13 +78,17 @@ public final class ScriptingFunctions {
* Nashorn extension: global.readLine (scripting-mode-only)
* Read one line of input from the standard input.
*
- * @param self self reference
+ * @param self self reference
+ * @param prompt String used as input prompt
*
* @return line that was read
*
* @throws IOException if an exception occurs
*/
- public static Object readLine(final Object self) throws IOException {
+ public static Object readLine(final Object self, final Object prompt) throws IOException {
+ if (prompt != UNDEFINED) {
+ System.out.print(JSType.toString(prompt));
+ }
final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
return reader.readLine();
}
From 41974c2e0729200c33cec32161143878662e7c46 Mon Sep 17 00:00:00 2001
From: Athijegannathan Sundararajan
Date: Wed, 22 May 2013 16:39:48 +0530
Subject: [PATCH 032/101] 8008947: ScriptEnvironment ctor should be public
Reviewed-by: lagergren, attila
---
nashorn/.hgignore | 1 +
nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/nashorn/.hgignore b/nashorn/.hgignore
index 56e01bae4c0..6d68c1d476d 100644
--- a/nashorn/.hgignore
+++ b/nashorn/.hgignore
@@ -24,3 +24,4 @@ jcov2/*
.idea/*
test/lib/testng.jar
test/script/external/*
+.project
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
index 3bcf9d4f5a3..c1c25b3eecc 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@@ -186,7 +186,7 @@ public final class ScriptEnvironment {
* @param out output print writer
* @param err error print writer
*/
- ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
+ public ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
this.out = out;
this.err = err;
this.namespace = new Namespace();
From 64b3efd73b0470ab6179fc4351a6b113b01c08c4 Mon Sep 17 00:00:00 2001
From: Chris Hegarty
Date: Wed, 22 May 2013 13:50:53 +0100
Subject: [PATCH 033/101] 8010182: Thread safety of Thread get/setName()
Reviewed-by: dholmes, alanb, mduigou
---
jdk/src/share/classes/java/lang/Thread.java | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/jdk/src/share/classes/java/lang/Thread.java b/jdk/src/share/classes/java/lang/Thread.java
index e418f1f9a93..81bebc58b21 100644
--- a/jdk/src/share/classes/java/lang/Thread.java
+++ b/jdk/src/share/classes/java/lang/Thread.java
@@ -145,10 +145,10 @@ class Thread implements Runnable {
registerNatives();
}
- private char name[];
- private int priority;
- private Thread threadQ;
- private long eetop;
+ private volatile char name[];
+ private int priority;
+ private Thread threadQ;
+ private long eetop;
/* Whether or not to single_step this thread. */
private boolean single_step;
@@ -1135,7 +1135,7 @@ class Thread implements Runnable {
* @see #getName
* @see #checkAccess()
*/
- public final void setName(String name) {
+ public final synchronized void setName(String name) {
checkAccess();
this.name = name.toCharArray();
if (threadStatus != 0) {
@@ -1150,7 +1150,7 @@ class Thread implements Runnable {
* @see #setName(String)
*/
public final String getName() {
- return String.valueOf(name);
+ return new String(name, true);
}
/**
From 2cd9f2dde4ea0d3a831c16d9fc54a274d48da084 Mon Sep 17 00:00:00 2001
From: Athijegannathan Sundararajan
Date: Wed, 22 May 2013 19:33:08 +0530
Subject: [PATCH 034/101] 8014735: Typed Array, BYTES_PER_ELEMENT should be a
class property
Reviewed-by: lagergren, jlaskey
---
.../internal/objects/ArrayBufferView.java | 6 +--
.../internal/objects/NativeFloat32Array.java | 6 ++-
.../internal/objects/NativeFloat64Array.java | 6 ++-
.../internal/objects/NativeInt16Array.java | 6 ++-
.../internal/objects/NativeInt32Array.java | 6 ++-
.../internal/objects/NativeInt8Array.java | 6 ++-
.../internal/objects/NativeUint16Array.java | 6 ++-
.../internal/objects/NativeUint32Array.java | 6 ++-
.../internal/objects/NativeUint8Array.java | 6 ++-
.../objects/NativeUint8ClampedArray.java | 6 ++-
nashorn/test/script/basic/JDK-8014735.js | 43 +++++++++++++++++++
.../test/script/basic/JDK-8014735.js.EXPECTED | 9 ++++
nashorn/test/script/basic/NASHORN-377.js | 4 +-
13 files changed, 100 insertions(+), 16 deletions(-)
create mode 100644 nashorn/test/script/basic/JDK-8014735.js
create mode 100644 nashorn/test/script/basic/JDK-8014735.js.EXPECTED
diff --git a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index a442a3876c7..ebab47b65f0 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -28,6 +28,7 @@ package jdk.nashorn.internal.objects;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Getter;
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.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -58,11 +59,6 @@ abstract class ArrayBufferView extends ScriptObject {
return factory().bytesPerElement;
}
- @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
- public static Object BYTES_PER_ELEMENT(final Object self) {
- return ((ArrayBufferView)self).bytesPerElement();
- }
-
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
public static Object buffer(final Object self) {
return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).buffer;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
index 98db34ba046..33d2d9ecc5d 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Float32Array")
public final class NativeFloat32Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 4;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 4;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
index e2ce624753f..ba6bffe8c38 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Float64Array")
public final class NativeFloat64Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 8;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 8;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
index c5951d91760..9afaf3a7ea0 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -37,7 +39,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Int16Array")
public final class NativeInt16Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 2;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 2;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
index 486e7a61fd5..199d223d25d 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -37,7 +39,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Int32Array")
public final class NativeInt32Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 4;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 4;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
index 9ad7d24c280..25e86c23d35 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -37,7 +39,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Int8Array")
public final class NativeInt8Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 1;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 1;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
index 740bb394511..ec5e99d3718 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -37,7 +39,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Uint16Array")
public final class NativeUint16Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 2;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 2;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
index 9be0131202c..d8a3f5240f4 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Uint32Array")
public final class NativeUint32Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 4;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 4;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteBegin, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
index 7d506c1d6b9..d62818a912b 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -37,7 +39,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Uint8Array")
public final class NativeUint8Array extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 1;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 1;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
index e3bacc2b9db..7eb3e650714 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
@@ -28,7 +28,9 @@ package jdk.nashorn.internal.objects;
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.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
@@ -38,7 +40,9 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
*/
@ScriptClass("Uint8ClampedArray")
public final class NativeUint8ClampedArray extends ArrayBufferView {
- private static final int BYTES_PER_ELEMENT = 1;
+ @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
+ public static final int BYTES_PER_ELEMENT = 1;
+
private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
@Override
public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
diff --git a/nashorn/test/script/basic/JDK-8014735.js b/nashorn/test/script/basic/JDK-8014735.js
new file mode 100644
index 00000000000..0fc367c0e96
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8014735.js
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8014735: Typed Array, BYTES_PER_ELEMENT should be a class property
+ *
+ * @test
+ * @run
+ */
+
+function bytesPerElement(func) {
+ print(func.name + ".BYTES_PER_ELEMENT = " + func.BYTES_PER_ELEMENT);
+}
+
+bytesPerElement(Int8Array);
+bytesPerElement(Int16Array);
+bytesPerElement(Int32Array);
+bytesPerElement(Uint8Array);
+bytesPerElement(Uint8ClampedArray);
+bytesPerElement(Uint16Array);
+bytesPerElement(Uint32Array);
+bytesPerElement(Float32Array);
+bytesPerElement(Float64Array);
diff --git a/nashorn/test/script/basic/JDK-8014735.js.EXPECTED b/nashorn/test/script/basic/JDK-8014735.js.EXPECTED
new file mode 100644
index 00000000000..bae22d618fb
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8014735.js.EXPECTED
@@ -0,0 +1,9 @@
+Int8Array.BYTES_PER_ELEMENT = 1
+Int16Array.BYTES_PER_ELEMENT = 2
+Int32Array.BYTES_PER_ELEMENT = 4
+Uint8Array.BYTES_PER_ELEMENT = 1
+Uint8ClampedArray.BYTES_PER_ELEMENT = 1
+Uint16Array.BYTES_PER_ELEMENT = 2
+Uint32Array.BYTES_PER_ELEMENT = 4
+Float32Array.BYTES_PER_ELEMENT = 4
+Float64Array.BYTES_PER_ELEMENT = 8
diff --git a/nashorn/test/script/basic/NASHORN-377.js b/nashorn/test/script/basic/NASHORN-377.js
index e77be2bf0e9..31d4df4941b 100644
--- a/nashorn/test/script/basic/NASHORN-377.js
+++ b/nashorn/test/script/basic/NASHORN-377.js
@@ -43,7 +43,7 @@ function tohex(d, w) {
function arrstr(a, n, w) {
var s = "";
if (typeof n == "undefined") n = a.length;
- if (typeof w == "undefined") w = a.BYTES_PER_ELEMENT * 2;
+ if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
for (var i = 0; i < n; i++) {
s += tohex(a[i], w);
}
@@ -96,7 +96,7 @@ function fillArray(a, start) {
var b = new ArrayBuffer(8);
for (var i in types) {
var x = new types[i](b);
- print(x.byteOffset, x.byteLength, x.length, x.BYTES_PER_ELEMENT);
+ print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
assertTrue(function(){ return x.constructor === types[i] });
}
})();
From aab1e4573c6fc749058190b8dd12b3c129149ae6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?=
Date: Wed, 22 May 2013 16:43:48 +0200
Subject: [PATCH 035/101] 8010804: Review long and integer usage conventions
Reviewed-by: jlaskey, sundar
---
.../internal/codegen/FoldConstants.java | 4 +-
.../nashorn/internal/objects/NativeArray.java | 39 ++-------
.../nashorn/internal/objects/NativeDate.java | 2 +-
.../jdk/nashorn/internal/runtime/JSType.java | 14 ++-
nashorn/test/script/basic/JDK-8010804.js | 86 +++++++++++++++++++
.../test/script/basic/JDK-8010804.js.EXPECTED | 42 +++++++++
6 files changed, 148 insertions(+), 39 deletions(-)
create mode 100644 nashorn/test/script/basic/JDK-8010804.js
create mode 100644 nashorn/test/script/basic/JDK-8010804.js.EXPECTED
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
index 686c9836da6..2e87631c5b6 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
@@ -279,9 +279,9 @@ final class FoldConstants extends NodeVisitor {
isLong &= value != 0.0 && JSType.isRepresentableAsLong(value);
if (isInteger) {
- return LiteralNode.newInstance(token, finish, JSType.toInt32(value));
+ return LiteralNode.newInstance(token, finish, (int)value);
} else if (isLong) {
- return LiteralNode.newInstance(token, finish, JSType.toLong(value));
+ return LiteralNode.newInstance(token, finish, (long)value);
}
return LiteralNode.newInstance(token, finish, value);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
index c9a71b57a92..6f9fbcec889 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -754,25 +754,11 @@ public final class NativeArray extends ScriptObject {
final Object obj = Global.toObject(self);
final ScriptObject sobj = (ScriptObject)obj;
final long len = JSType.toUint32(sobj.getLength());
- final double startNum = JSType.toNumber(start);
- final long relativeStartUint32 = JSType.toUint32(startNum);
- final long relativeStart = JSType.toInteger(startNum);
+ final long relativeStart = JSType.toLong(start);
+ final long relativeEnd = (end == ScriptRuntime.UNDEFINED) ? len : JSType.toLong(end);
- long k = relativeStart < 0 ?
- Math.max(len + relativeStart, 0) :
- Math.min(
- Math.max(relativeStartUint32, relativeStart),
- len);
-
- final double endNum = (end == ScriptRuntime.UNDEFINED)? Double.NaN : JSType.toNumber(end);
- final long relativeEndUint32 = (end == ScriptRuntime.UNDEFINED)? len : JSType.toUint32(endNum);
- final long relativeEnd = (end == ScriptRuntime.UNDEFINED)? len : JSType.toInteger(endNum);
-
- final long finale = relativeEnd < 0 ?
- Math.max(len + relativeEnd, 0) :
- Math.min(
- Math.max(relativeEndUint32, relativeEnd),
- len);
+ 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);
if (k >= finale) {
return new NativeArray(0);
@@ -909,21 +895,10 @@ public final class NativeArray extends ScriptObject {
final ScriptObject sobj = (ScriptObject)obj;
final boolean strict = Global.isStrict();
final long len = JSType.toUint32(sobj.getLength());
- final double startNum = JSType.toNumber(start);
- final long relativeStartUint32 = JSType.toUint32(startNum);
- final long relativeStart = JSType.toInteger(startNum);
+ final long relativeStart = JSType.toLong(start);
- //TODO: workaround overflow of relativeStart for start > Integer.MAX_VALUE
- final long actualStart = relativeStart < 0 ?
- Math.max(len + relativeStart, 0) :
- Math.min(
- Math.max(relativeStartUint32, relativeStart),
- len);
-
- final long actualDeleteCount =
- Math.min(
- Math.max(JSType.toInteger(deleteCount), 0),
- len - actualStart);
+ final long actualStart = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
+ final long actualDeleteCount = Math.min(Math.max(JSType.toLong(deleteCount), 0), len - actualStart);
final NativeArray array = new NativeArray(actualDeleteCount);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
index c97514a3131..fa2c9d17a81 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
@@ -770,7 +770,7 @@ public final class NativeDate extends ScriptObject {
nd.setTime(NaN);
return nd.getTime();
}
- int yearInt = JSType.toInteger(yearNum);
+ int yearInt = (int)yearNum;
if (0 <= yearInt && yearInt <= 99) {
yearInt += 1900;
}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
index e972a99ef63..58669144111 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
@@ -565,8 +565,11 @@ public enum JSType {
}
/**
- * JavaScript compliant Object to integer conversion
- * See ECMA 9.4 ToInteger
+ * JavaScript compliant Object to integer conversion. See ECMA 9.4 ToInteger
+ *
+ *
Note that this returns {@link java.lang.Integer#MAX_VALUE} or {@link java.lang.Integer#MIN_VALUE}
+ * for double values that exceed the int range, including positive and negative Infinity. It is the
+ * caller's responsibility to handle such values correctly.
*
* @param obj an object
* @return an integer
@@ -576,8 +579,11 @@ public enum JSType {
}
/**
- * JavaScript compliant Object to long conversion
- * See ECMA 9.4 ToInteger
+ * JavaScript compliant Object to long conversion. See ECMA 9.4 ToInteger
+ *
+ *
Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE}
+ * for double values that exceed the long range, including positive and negative Infinity. It is the
+ * caller's responsibility to handle such values correctly.
*
* @param obj an object
* @return a long
diff --git a/nashorn/test/script/basic/JDK-8010804.js b/nashorn/test/script/basic/JDK-8010804.js
new file mode 100644
index 00000000000..04e216ade24
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8010804.js
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8010804: Review long and integer usage conventions
+ *
+ * @test
+ * @run
+ */
+
+var x = [];
+print(x.length);
+x[4294967294] = 1;
+print(x.length);
+x[4294967295] = 1;
+print(x.length);
+print(x.slice(4294967293).length);
+print(x.slice(4294967294).length);
+print(x.slice(4294967295).length);
+print(x.slice(4294967296).length);
+
+print(x.slice(-4294967293).length);
+print(x.slice(-4294967294).length);
+print(x.slice(-4294967295).length);
+print(x.slice(-4294967296).length);
+
+print(x.slice(0, 4294967293).length);
+print(x.slice(0, 4294967294).length);
+print(x.slice(0, 4294967295).length);
+print(x.slice(0, 4294967296).length);
+
+print(x.slice(0, -4294967293).length);
+print(x.slice(0, -4294967294).length);
+print(x.slice(0, -4294967295).length);
+print(x.slice(0, -4294967296).length);
+
+print(x.slice(9223371036854775807).length);
+print(x.slice(9223372036854775807).length);
+print(x.slice(9223373036854775807).length);
+print(x.slice(9223374036854775807).length);
+
+print(x.slice(-9223371036854775807).length);
+print(x.slice(-9223372036854775807).length);
+print(x.slice(-9223373036854775807).length);
+print(x.slice(-9223374036854775807).length);
+
+print(x.slice(-9223371036854775807, 1).length);
+print(x.slice(-9223372036854775807, 1).length);
+print(x.slice(-9223373036854775807, 1).length);
+print(x.slice(-9223374036854775807, 1).length);
+
+print(x.slice(-9223371036854775807, -1).length);
+print(x.slice(-9223372036854775807, -1).length);
+print(x.slice(-9223373036854775807, -1).length);
+print(x.slice(-9223374036854775807, -1).length);
+
+print(x.slice(Infinity).length);
+print(x.slice(Infinity, Infinity).length);
+print(x.slice(Infinity, -Infinity).length);
+print(x.slice(-Infinity).length);
+print(x.slice(-Infinity, Infinity).length);
+print(x.slice(-Infinity, -Infinity).length);
+
+var d = new Date();
+d.setYear(Infinity);
+print(d);
\ No newline at end of file
diff --git a/nashorn/test/script/basic/JDK-8010804.js.EXPECTED b/nashorn/test/script/basic/JDK-8010804.js.EXPECTED
new file mode 100644
index 00000000000..1f73ec043f2
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8010804.js.EXPECTED
@@ -0,0 +1,42 @@
+0
+4294967295
+4294967295
+2
+1
+0
+0
+4294967293
+4294967294
+4294967295
+4294967295
+4294967293
+4294967294
+4294967295
+4294967295
+2
+1
+0
+0
+0
+0
+0
+0
+4294967295
+4294967295
+4294967295
+4294967295
+1
+1
+1
+1
+4294967294
+4294967294
+4294967294
+4294967294
+0
+0
+0
+4294967295
+4294967295
+0
+Invalid Date
From eccee3e025cfb032d310ad493f4176260cac859f Mon Sep 17 00:00:00 2001
From: Mike Duigou
Date: Wed, 22 May 2013 09:59:37 -0700
Subject: [PATCH 036/101] 8014819: set max size for jtreg testvms
Reviewed-by: alanb, darcy
---
jdk/test/Makefile | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/jdk/test/Makefile b/jdk/test/Makefile
index 51529b7c5f5..de6b4a783ff 100644
--- a/jdk/test/Makefile
+++ b/jdk/test/Makefile
@@ -657,9 +657,12 @@ JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
# Multiple by 4 the timeout numbers
JTREG_TIMEOUT_OPTION = -timeoutFactor:4
JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
-# Boost the max memory for jtreg to avoid gc thrashing
+# Set the max memory for jtreg control vm
JTREG_MEMORY_OPTION = -J-Xmx512m
JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
+# Set the max memory for jtreg target test vms
+JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
+JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
# Make sure jtreg exists
$(JTREG): $(JT_HOME)
From c9d407ad3952bce594f9bf76c7d35aa08897fbed Mon Sep 17 00:00:00 2001
From: Naoto Sato
Date: Wed, 22 May 2013 16:43:04 -0700
Subject: [PATCH 037/101] 7056126: DateFormatSymbols documentation has
incorrect description about DateFormat 7083668: Sample code in
ListResourceBundle is still not correct
Reviewed-by: okutsu
---
jdk/src/share/classes/java/text/DateFormatSymbols.java | 2 +-
jdk/src/share/classes/java/util/ListResourceBundle.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/jdk/src/share/classes/java/text/DateFormatSymbols.java b/jdk/src/share/classes/java/text/DateFormatSymbols.java
index 80e4f03a38a..3357b49d774 100644
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java
+++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java
@@ -59,7 +59,7 @@ import sun.util.locale.provider.TimeZoneNameUtility;
* DateFormatSymbols is a public class for encapsulating
* localizable date-time formatting data, such as the names of the
* months, the names of the days of the week, and the time zone data.
- * DateFormat and SimpleDateFormat both use
+ * SimpleDateFormat uses
* DateFormatSymbols to encapsulate this information.
*
*
diff --git a/jdk/src/share/classes/java/util/ListResourceBundle.java b/jdk/src/share/classes/java/util/ListResourceBundle.java
index 736016f7f84..9aa7fdba550 100644
--- a/jdk/src/share/classes/java/util/ListResourceBundle.java
+++ b/jdk/src/share/classes/java/util/ListResourceBundle.java
@@ -89,7 +89,7 @@ import sun.util.ResourceBundleEnumeration;
*
* public class MyResources_fr extends ListResourceBundle {
* protected Object[][] getContents() {
- * return new Object[][] = {
+ * return new Object[][] {
* // LOCALIZE THIS
* {"s1", "Le disque \"{1}\" {0}."}, // MessageFormat pattern
* {"s2", "1"}, // location of {0} in pattern
From 4ef977fec3abe84db61e6c4475bf8b49e9872718 Mon Sep 17 00:00:00 2001
From: David Holmes
Date: Wed, 22 May 2013 20:21:13 -0400
Subject: [PATCH 038/101] 8014814: (str) StringBuffer "null" is not appended
Reviewed-by: alanb
---
.../share/classes/java/lang/StringBuffer.java | 6 ++---
.../java/lang/StringBuffer/ToStringCache.java | 24 ++++++++++++++++++-
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/jdk/src/share/classes/java/lang/StringBuffer.java b/jdk/src/share/classes/java/lang/StringBuffer.java
index 8ead0721ffd..9bc8f3ba10f 100644
--- a/jdk/src/share/classes/java/lang/StringBuffer.java
+++ b/jdk/src/share/classes/java/lang/StringBuffer.java
@@ -335,10 +335,8 @@ import java.util.Arrays;
* @since 1.5
*/
@Override
- public StringBuffer append(CharSequence s) {
- // Note, synchronization achieved via invocations of other StringBuffer methods after
- // narrowing of s to specific type
- // Ditto for toStringCache clearing
+ public synchronized StringBuffer append(CharSequence s) {
+ toStringCache = null;
super.append(s);
return this;
}
diff --git a/jdk/test/java/lang/StringBuffer/ToStringCache.java b/jdk/test/java/lang/StringBuffer/ToStringCache.java
index 6259e27d0e3..e6c97f0c28a 100644
--- a/jdk/test/java/lang/StringBuffer/ToStringCache.java
+++ b/jdk/test/java/lang/StringBuffer/ToStringCache.java
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 8013395
+ * @bug 8013395 8014814
* @summary Test StringBuffer.toString caching
*/
@@ -199,6 +199,28 @@ public class ToStringCache {
b = sb.toString();
checkUnequal(a, b);
+ // Extra checks that append(null) works correctly
+
+ sb.append((String)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append((StringBuffer)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append((StringBuilder)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
+ sb.append((CharSequence)null);
+ b = sb.toString();
+ checkUnequal(a, b);
+ a = b;
+
// non-mutating methods
// Reset to known value
From 7c644b0a4b947e9819c95e28a330d3523dd9c03c Mon Sep 17 00:00:00 2001
From: Joe Darcy
Date: Wed, 22 May 2013 20:03:45 -0700
Subject: [PATCH 039/101] 8014836: Have GenericDeclaration extend
AnnotatedElement
Reviewed-by: abuckley, jfranck
---
jdk/src/share/classes/java/lang/Class.java | 9 +++++----
.../classes/java/lang/reflect/GenericDeclaration.java | 4 ++--
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java
index 5593f2b4898..c131a9c3071 100644
--- a/jdk/src/share/classes/java/lang/Class.java
+++ b/jdk/src/share/classes/java/lang/Class.java
@@ -28,6 +28,7 @@ package java.lang;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Field;
import java.lang.reflect.Executable;
@@ -115,9 +116,9 @@ import sun.reflect.misc.ReflectUtil;
* @since JDK1.0
*/
public final class Class implements java.io.Serializable,
- java.lang.reflect.GenericDeclaration,
- java.lang.reflect.Type,
- java.lang.reflect.AnnotatedElement {
+ GenericDeclaration,
+ Type,
+ AnnotatedElement {
private static final int ANNOTATION= 0x00002000;
private static final int ENUM = 0x00004000;
private static final int SYNTHETIC = 0x00001000;
@@ -3182,7 +3183,7 @@ public final class Class implements java.io.Serializable,
*/
@Override
public boolean isAnnotationPresent(Class extends Annotation> annotationClass) {
- return AnnotatedElement.super.isAnnotationPresent(annotationClass);
+ return GenericDeclaration.super.isAnnotationPresent(annotationClass);
}
/**
diff --git a/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java b/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java
index 4f06c621f26..042e359ad6f 100644
--- a/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java
+++ b/jdk/src/share/classes/java/lang/reflect/GenericDeclaration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -30,7 +30,7 @@ package java.lang.reflect;
*
* @since 1.5
*/
-public interface GenericDeclaration {
+public interface GenericDeclaration extends AnnotatedElement {
/**
* Returns an array of {@code TypeVariable} objects that
* represent the type variables declared by the generic
From dd837d94dd37125c29d62e073ebd5fc86910b5a5 Mon Sep 17 00:00:00 2001
From: Attila Szegedi
Date: Thu, 23 May 2013 12:01:35 +0200
Subject: [PATCH 040/101] 8015267: Allow conversion of JS arrays to Java
List/Deque
Reviewed-by: lagergren, sundar
---
nashorn/make/build.xml | 16 +-
.../nashorn/internal/objects/NativeJava.java | 45 ++-
.../nashorn/internal/runtime/ListAdapter.java | 337 ++++++++++++++++++
.../internal/runtime/linker/InvokeByName.java | 14 +-
.../runtime/resources/Messages.properties | 2 +-
nashorn/test/script/basic/JDK-8015267.js | 109 ++++++
.../test/script/basic/JDK-8015267.js.EXPECTED | 40 +++
7 files changed, 526 insertions(+), 37 deletions(-)
create mode 100644 nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
create mode 100644 nashorn/test/script/basic/JDK-8015267.js
create mode 100644 nashorn/test/script/basic/JDK-8015267.js.EXPECTED
diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml
index 7c05e789fe9..5324d91f405 100644
--- a/nashorn/make/build.xml
+++ b/nashorn/make/build.xml
@@ -42,8 +42,6 @@
-
-
@@ -80,19 +78,7 @@
-
-
-
-
-
-
+
* var anArray = [1, "13", false]
* var javaIntArray = Java.to(anArray, "int[]")
@@ -250,42 +253,46 @@ public final class NativeJava {
* print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
*
* @param self not used
- * @param objArray the script object. Can be null.
+ * @param obj the script object. Can be null.
* @param objType either a {@link #type(Object, Object) type object} or a String describing the type of the Java
* object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be
* omitted).
* @return a Java object whose value corresponds to the original script object's value. Specifically, for array
* target types, returns a Java array of the same type with contents converted to the array's component type. Does
- * not recursively convert for multidimensional arrays.
- * type. Returns null if scriptObject is null.
+ * not recursively convert for multidimensional arrays. For {@link List} or {@link Deque}, returns a live wrapper
+ * around the object, see {@link ListAdapter} for details. Returns null if obj is null.
* @throws ClassNotFoundException if the class described by objType is not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object to(final Object self, final Object objArray, final Object objType) throws ClassNotFoundException {
- if (objArray == null) {
+ public static Object to(final Object self, final Object obj, final Object objType) throws ClassNotFoundException {
+ if (obj == null) {
return null;
}
- final Class> componentType;
+ Global.checkObject(obj);
+
+ final Class> targetClass;
if(objType == UNDEFINED) {
- componentType = Object.class;
+ targetClass = Object[].class;
} else {
- final StaticClass arrayType;
+ final StaticClass targetType;
if(objType instanceof StaticClass) {
- arrayType = (StaticClass)objType;
+ targetType = (StaticClass)objType;
} else {
- arrayType = type(objType);
+ targetType = type(objType);
}
- final Class> arrayClass = arrayType.getRepresentedClass();
- if(!arrayClass.isArray()) {
- throw typeError("to.expects.array.type", arrayClass.getName());
- }
- componentType = arrayClass.getComponentType();
+ targetClass = targetType.getRepresentedClass();
}
- Global.checkObject(objArray);
+ if(targetClass.isArray()) {
+ return ((ScriptObject)obj).getArray().asArrayOfType(targetClass.getComponentType());
+ }
- return ((ScriptObject)objArray).getArray().asArrayOfType(componentType);
+ if(targetClass == List.class || targetClass == Deque.class) {
+ return new ListAdapter((ScriptObject)obj);
+ }
+
+ throw typeError("unsupported.java.to.type", targetClass.getName());
}
/**
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
new file mode 100644
index 00000000000..cc99cd126bf
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
@@ -0,0 +1,337 @@
+package jdk.nashorn.internal.runtime;
+
+import java.util.AbstractList;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import java.util.RandomAccess;
+import jdk.nashorn.internal.runtime.linker.InvokeByName;
+
+/**
+ * An adapter that can wrap any ECMAScript Array-like object (that adheres to the array rules for the property
+ * {@code length} and having conforming {@code push}, {@code pop}, {@code shift}, {@code unshift}, and {@code splice}
+ * methods) and expose it as both a Java list and double-ended queue. While script arrays aren't necessarily efficient
+ * as dequeues, it's still slightly more efficient to be able to translate dequeue operations into pushes, pops, shifts,
+ * and unshifts, than to blindly translate all list's add/remove operations into splices. Also, it is conceivable that a
+ * custom script object that implements an Array-like API can have a background data representation that is optimized
+ * for dequeue-like access. Note that with ECMAScript arrays, {@code push} and {@pop} operate at the end of the array,
+ * while in Java {@code Deque} they operate on the front of the queue and as such the Java dequeue {@link #push(Object)}
+ * and {@link #pop()} operations will translate to {@code unshift} and {@code shift} script operations respectively,
+ * while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and {@code pop}.
+ */
+public class ListAdapter extends AbstractList
-
+
+
+
+
+
+
Date: Thu, 23 May 2013 15:52:37 +0400
Subject: [PATCH 043/101] 8014924: JToolTip#setTipText() sometimes (very often)
not repaints component
Reviewed-by: serb
---
jdk/src/share/classes/javax/swing/JToolTip.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/jdk/src/share/classes/javax/swing/JToolTip.java b/jdk/src/share/classes/javax/swing/JToolTip.java
index 3879d23139f..ac79d465ef5 100644
--- a/jdk/src/share/classes/javax/swing/JToolTip.java
+++ b/jdk/src/share/classes/javax/swing/JToolTip.java
@@ -31,6 +31,7 @@ import javax.accessibility.*;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
+import java.util.Objects;
/**
@@ -128,6 +129,11 @@ public class JToolTip extends JComponent implements Accessible {
String oldValue = this.tipText;
this.tipText = tipText;
firePropertyChange("tiptext", oldValue, tipText);
+
+ if (!Objects.equals(oldValue, tipText)) {
+ revalidate();
+ repaint();
+ }
}
/**
From 9179358ff4f73978441efdbae6911648ebbc93c9 Mon Sep 17 00:00:00 2001
From: Nils Loodin
Date: Thu, 23 May 2013 15:50:37 +0200
Subject: [PATCH 044/101] 8014048: Online user guide of jconsole points
incorrect link
Reviewed-by: mchung, sla, jbachorik
---
.../classes/sun/tools/jconsole/AboutDialog.java | 14 ++++++++++----
.../tools/jconsole/resources/messages.properties | 2 +-
.../jconsole/resources/messages_ja.properties | 2 +-
.../jconsole/resources/messages_zh_CN.properties | 2 +-
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java b/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java
index ed1d6e4c805..583b392bb7b 100644
--- a/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java
+++ b/jdk/src/share/classes/sun/tools/jconsole/AboutDialog.java
@@ -34,6 +34,7 @@ import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
+import static sun.misc.Version.jdkMinorVersion;
import static java.awt.BorderLayout.*;
import static sun.tools.jconsole.Utilities.*;
@@ -73,7 +74,7 @@ public class AboutDialog extends InternalDialog {
String jConsoleVersion = Version.getVersion();
String vmName = System.getProperty("java.vm.name");
String vmVersion = System.getProperty("java.vm.version");
- String urlStr = Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL;
+ String urlStr = getOnlineDocUrl();
if (isBrowseSupported()) {
urlStr = "" + urlStr + "";
}
@@ -86,8 +87,7 @@ public class AboutDialog extends InternalDialog {
"" +
Resources.format(Messages.HELP_ABOUT_DIALOG_JCONSOLE_VERSION, jConsoleVersion) +
"