< prev index next >

src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java

Print this page
@@ -27,11 +27,10 @@
  import java.nio.ByteBuffer;
  import java.nio.ByteOrder;
  import java.nio.ReadOnlyBufferException;
  import java.util.Arrays;
  import java.util.Objects;
- import java.util.function.BinaryOperator;
  import java.util.function.Function;
  import java.util.function.UnaryOperator;
  
  import jdk.internal.misc.ScopedMemoryAccess;
  import jdk.internal.misc.Unsafe;

@@ -171,10 +170,13 @@
                               FUnOp f);
      @ForceInline
      final
      DoubleVector uOpTemplate(VectorMask<Double> m,
                                       FUnOp f) {
+         if (m == null) {
+             return uOpTemplate(f);
+         }
          double[] vec = vec();
          double[] res = new double[length()];
          boolean[] mbits = ((AbstractMask<Double>)m).getBits();
          for (int i = 0; i < res.length; i++) {
              res[i] = mbits[i] ? f.apply(i, vec[i]) : vec[i];

@@ -214,10 +216,13 @@
      @ForceInline
      final
      DoubleVector bOpTemplate(Vector<Double> o,
                                       VectorMask<Double> m,
                                       FBinOp f) {
+         if (m == null) {
+             return bOpTemplate(o, f);
+         }
          double[] res = new double[length()];
          double[] vec1 = this.vec();
          double[] vec2 = ((DoubleVector)o).vec();
          boolean[] mbits = ((AbstractMask<Double>)m).getBits();
          for (int i = 0; i < res.length; i++) {

@@ -263,10 +268,13 @@
      final
      DoubleVector tOpTemplate(Vector<Double> o1,
                                       Vector<Double> o2,
                                       VectorMask<Double> m,
                                       FTriOp f) {
+         if (m == null) {
+             return tOpTemplate(o1, o2, f);
+         }
          double[] res = new double[length()];
          double[] vec1 = this.vec();
          double[] vec2 = ((DoubleVector)o1).vec();
          double[] vec3 = ((DoubleVector)o2).vec();
          boolean[] mbits = ((AbstractMask<Double>)m).getBits();

@@ -278,11 +286,26 @@
  
      // Reduction operator
  
      /*package-private*/
      abstract
-     double rOp(double v, FBinOp f);
+     double rOp(double v, VectorMask<Double> m, FBinOp f);
+ 
+     @ForceInline
+     final
+     double rOpTemplate(double v, VectorMask<Double> m, FBinOp f) {
+         if (m == null) {
+             return rOpTemplate(v, f);
+         }
+         double[] vec = vec();
+         boolean[] mbits = ((AbstractMask<Double>)m).getBits();
+         for (int i = 0; i < vec.length; i++) {
+             v = mbits[i] ? f.apply(i, v, vec[i]) : v;
+         }
+         return v;
+     }
+ 
      @ForceInline
      final
      double rOpTemplate(double v, FBinOp f) {
          double[] vec = vec();
          for (int i = 0; i < vec.length; i++) {

@@ -538,65 +561,84 @@
                  return blend(broadcast(-1), compare(NE, 0));
              }
          }
          int opc = opCode(op);
          return VectorSupport.unaryOp(
-             opc, getClass(), double.class, length(),
-             this,
-             UN_IMPL.find(op, opc, (opc_) -> {
-               switch (opc_) {
-                 case VECTOR_OP_NEG: return v0 ->
-                         v0.uOp((i, a) -> (double) -a);
-                 case VECTOR_OP_ABS: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.abs(a));
-                 case VECTOR_OP_SIN: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.sin(a));
-                 case VECTOR_OP_COS: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.cos(a));
-                 case VECTOR_OP_TAN: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.tan(a));
-                 case VECTOR_OP_ASIN: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.asin(a));
-                 case VECTOR_OP_ACOS: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.acos(a));
-                 case VECTOR_OP_ATAN: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.atan(a));
-                 case VECTOR_OP_EXP: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.exp(a));
-                 case VECTOR_OP_LOG: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.log(a));
-                 case VECTOR_OP_LOG10: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.log10(a));
-                 case VECTOR_OP_SQRT: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.sqrt(a));
-                 case VECTOR_OP_CBRT: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.cbrt(a));
-                 case VECTOR_OP_SINH: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.sinh(a));
-                 case VECTOR_OP_COSH: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.cosh(a));
-                 case VECTOR_OP_TANH: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.tanh(a));
-                 case VECTOR_OP_EXPM1: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.expm1(a));
-                 case VECTOR_OP_LOG1P: return v0 ->
-                         v0.uOp((i, a) -> (double) Math.log1p(a));
-                 default: return null;
-               }}));
+             opc, getClass(), null, double.class, length(),
+             this, null,
+             UN_IMPL.find(op, opc, DoubleVector::unaryOperations));
      }
-     private static final
-     ImplCache<Unary,UnaryOperator<DoubleVector>> UN_IMPL
-         = new ImplCache<>(Unary.class, DoubleVector.class);
  
      /**
       * {@inheritDoc} <!--workaround-->
       */
-     @ForceInline
-     public final
+     @Override
+     public abstract
      DoubleVector lanewise(VectorOperators.Unary op,
-                                   VectorMask<Double> m) {
-         return blend(lanewise(op), m);
+                                   VectorMask<Double> m);
+     @ForceInline
+     final
+     DoubleVector lanewiseTemplate(VectorOperators.Unary op,
+                                           Class<? extends VectorMask<Double>> maskClass,
+                                           VectorMask<Double> m) {
+         m.check(maskClass, this);
+         if (opKind(op, VO_SPECIAL)) {
+             if (op == ZOMO) {
+                 return blend(broadcast(-1), compare(NE, 0, m));
+             }
+         }
+         int opc = opCode(op);
+         return VectorSupport.unaryOp(
+             opc, getClass(), maskClass, double.class, length(),
+             this, m,
+             UN_IMPL.find(op, opc, DoubleVector::unaryOperations));
+     }
+ 
+     private static final
+     ImplCache<Unary, UnaryOperation<DoubleVector, VectorMask<Double>>>
+         UN_IMPL = new ImplCache<>(Unary.class, DoubleVector.class);
+ 
+     private static UnaryOperation<DoubleVector, VectorMask<Double>> unaryOperations(int opc_) {
+         switch (opc_) {
+             case VECTOR_OP_NEG: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) -a);
+             case VECTOR_OP_ABS: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.abs(a));
+             case VECTOR_OP_SIN: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.sin(a));
+             case VECTOR_OP_COS: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.cos(a));
+             case VECTOR_OP_TAN: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.tan(a));
+             case VECTOR_OP_ASIN: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.asin(a));
+             case VECTOR_OP_ACOS: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.acos(a));
+             case VECTOR_OP_ATAN: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.atan(a));
+             case VECTOR_OP_EXP: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.exp(a));
+             case VECTOR_OP_LOG: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.log(a));
+             case VECTOR_OP_LOG10: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.log10(a));
+             case VECTOR_OP_SQRT: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.sqrt(a));
+             case VECTOR_OP_CBRT: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.cbrt(a));
+             case VECTOR_OP_SINH: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.sinh(a));
+             case VECTOR_OP_COSH: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.cosh(a));
+             case VECTOR_OP_TANH: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.tanh(a));
+             case VECTOR_OP_EXPM1: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.expm1(a));
+             case VECTOR_OP_LOG1P: return (v0, m) ->
+                     v0.uOp(m, (i, a) -> (double) Math.log1p(a));
+             default: return null;
+         }
      }
  
      // Binary lanewise support
  
      /**

@@ -612,10 +654,11 @@
      final
      DoubleVector lanewiseTemplate(VectorOperators.Binary op,
                                            Vector<Double> v) {
          DoubleVector that = (DoubleVector) v;
          that.check(this);
+ 
          if (opKind(op, VO_SPECIAL )) {
              if (op == FIRST_NONZERO) {
                  // FIXME: Support this in the JIT.
                  VectorMask<Long> thisNZ
                      = this.viewAsIntegralLanes().compare(NE, (long) 0);

@@ -625,52 +668,79 @@
                  return this.viewAsIntegralLanes()
                      .lanewise(op, that.viewAsIntegralLanes())
                      .viewAsFloatingLanes();
              }
          }
+ 
          int opc = opCode(op);
          return VectorSupport.binaryOp(
-             opc, getClass(), double.class, length(),
-             this, that,
-             BIN_IMPL.find(op, opc, (opc_) -> {
-               switch (opc_) {
-                 case VECTOR_OP_ADD: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double)(a + b));
-                 case VECTOR_OP_SUB: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double)(a - b));
-                 case VECTOR_OP_MUL: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double)(a * b));
-                 case VECTOR_OP_DIV: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double)(a / b));
-                 case VECTOR_OP_MAX: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double)Math.max(a, b));
-                 case VECTOR_OP_MIN: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double)Math.min(a, b));
-                 case VECTOR_OP_ATAN2: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double) Math.atan2(a, b));
-                 case VECTOR_OP_POW: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double) Math.pow(a, b));
-                 case VECTOR_OP_HYPOT: return (v0, v1) ->
-                         v0.bOp(v1, (i, a, b) -> (double) Math.hypot(a, b));
-                 default: return null;
-                 }}));
+             opc, getClass(), null, double.class, length(),
+             this, that, null,
+             BIN_IMPL.find(op, opc, DoubleVector::binaryOperations));
      }
-     private static final
-     ImplCache<Binary,BinaryOperator<DoubleVector>> BIN_IMPL
-         = new ImplCache<>(Binary.class, DoubleVector.class);
  
      /**
       * {@inheritDoc} <!--workaround-->
       * @see #lanewise(VectorOperators.Binary,double,VectorMask)
       */
-     @ForceInline
-     public final
+     @Override
+     public abstract
      DoubleVector lanewise(VectorOperators.Binary op,
                                    Vector<Double> v,
-                                   VectorMask<Double> m) {
-         return blend(lanewise(op, v), m);
+                                   VectorMask<Double> m);
+     @ForceInline
+     final
+     DoubleVector lanewiseTemplate(VectorOperators.Binary op,
+                                           Class<? extends VectorMask<Double>> maskClass,
+                                           Vector<Double> v, VectorMask<Double> m) {
+         DoubleVector that = (DoubleVector) v;
+         that.check(this);
+         m.check(maskClass, this);
+ 
+         if (opKind(op, VO_SPECIAL )) {
+             if (op == FIRST_NONZERO) {
+                 return blend(lanewise(op, v), m);
+             }
+         }
+ 
+         int opc = opCode(op);
+         return VectorSupport.binaryOp(
+             opc, getClass(), maskClass, double.class, length(),
+             this, that, m,
+             BIN_IMPL.find(op, opc, DoubleVector::binaryOperations));
      }
+ 
+     private static final
+     ImplCache<Binary, BinaryOperation<DoubleVector, VectorMask<Double>>>
+         BIN_IMPL = new ImplCache<>(Binary.class, DoubleVector.class);
+ 
+     private static BinaryOperation<DoubleVector, VectorMask<Double>> binaryOperations(int opc_) {
+         switch (opc_) {
+             case VECTOR_OP_ADD: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double)(a + b));
+             case VECTOR_OP_SUB: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double)(a - b));
+             case VECTOR_OP_MUL: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double)(a * b));
+             case VECTOR_OP_DIV: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double)(a / b));
+             case VECTOR_OP_MAX: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double)Math.max(a, b));
+             case VECTOR_OP_MIN: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double)Math.min(a, b));
+             case VECTOR_OP_OR: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> fromBits(toBits(a) | toBits(b)));
+             case VECTOR_OP_ATAN2: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double) Math.atan2(a, b));
+             case VECTOR_OP_POW: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double) Math.pow(a, b));
+             case VECTOR_OP_HYPOT: return (v0, v1, vm) ->
+                     v0.bOp(v1, vm, (i, a, b) -> (double) Math.hypot(a, b));
+             default: return null;
+         }
+     }
+ 
      // FIXME: Maybe all of the public final methods in this file (the
      // simple ones that just call lanewise) should be pushed down to
      // the X-VectorBits template.  They can't optimize properly at
      // this level, and must rely on inlining.  Does it work?
      // (If it works, of course keep the code here.)

@@ -723,11 +793,11 @@
      @ForceInline
      public final
      DoubleVector lanewise(VectorOperators.Binary op,
                                    double e,
                                    VectorMask<Double> m) {
-         return blend(lanewise(op, e), m);
+         return lanewise(op, broadcast(e), m);
      }
  
      /**
       * {@inheritDoc} <!--workaround-->
       * @apiNote

@@ -741,12 +811,11 @@
      @ForceInline
      public final
      DoubleVector lanewise(VectorOperators.Binary op,
                                    long e) {
          double e1 = (double) e;
-         if ((long)e1 != e
-             ) {
+         if ((long)e1 != e) {
              vspecies().checkValue(e);  // for exception
          }
          return lanewise(op, e1);
      }
  

@@ -762,11 +831,15 @@
       */
      @ForceInline
      public final
      DoubleVector lanewise(VectorOperators.Binary op,
                                    long e, VectorMask<Double> m) {
-         return blend(lanewise(op, e), m);
+         double e1 = (double) e;
+         if ((long)e1 != e) {
+             vspecies().checkValue(e);  // for exception
+         }
+         return lanewise(op, e1, m);
      }
  
  
      // Ternary lanewise support
  

@@ -804,36 +877,60 @@
          // "Totherest Governor," replied Mr Riderhood...
          that.check(this);
          tother.check(this);
          int opc = opCode(op);
          return VectorSupport.ternaryOp(
-             opc, getClass(), double.class, length(),
-             this, that, tother,
-             TERN_IMPL.find(op, opc, (opc_) -> {
-               switch (opc_) {
-                 case VECTOR_OP_FMA: return (v0, v1_, v2_) ->
-                         v0.tOp(v1_, v2_, (i, a, b, c) -> Math.fma(a, b, c));
-                 default: return null;
-                 }}));
+             opc, getClass(), null, double.class, length(),
+             this, that, tother, null,
+             TERN_IMPL.find(op, opc, DoubleVector::ternaryOperations));
      }
-     private static final
-     ImplCache<Ternary,TernaryOperation<DoubleVector>> TERN_IMPL
-         = new ImplCache<>(Ternary.class, DoubleVector.class);
  
      /**
       * {@inheritDoc} <!--workaround-->
       * @see #lanewise(VectorOperators.Ternary,double,double,VectorMask)
       * @see #lanewise(VectorOperators.Ternary,Vector,double,VectorMask)
       * @see #lanewise(VectorOperators.Ternary,double,Vector,VectorMask)
       */
-     @ForceInline
-     public final
+     @Override
+     public abstract
      DoubleVector lanewise(VectorOperators.Ternary op,
                                    Vector<Double> v1,
                                    Vector<Double> v2,
-                                   VectorMask<Double> m) {
-         return blend(lanewise(op, v1, v2), m);
+                                   VectorMask<Double> m);
+     @ForceInline
+     final
+     DoubleVector lanewiseTemplate(VectorOperators.Ternary op,
+                                           Class<? extends VectorMask<Double>> maskClass,
+                                           Vector<Double> v1,
+                                           Vector<Double> v2,
+                                           VectorMask<Double> m) {
+         DoubleVector that = (DoubleVector) v1;
+         DoubleVector tother = (DoubleVector) v2;
+         // It's a word: https://www.dictionary.com/browse/tother
+         // See also Chapter 11 of Dickens, Our Mutual Friend:
+         // "Totherest Governor," replied Mr Riderhood...
+         that.check(this);
+         tother.check(this);
+         m.check(maskClass, this);
+ 
+         int opc = opCode(op);
+         return VectorSupport.ternaryOp(
+             opc, getClass(), maskClass, double.class, length(),
+             this, that, tother, m,
+             TERN_IMPL.find(op, opc, DoubleVector::ternaryOperations));
+     }
+ 
+     private static final
+     ImplCache<Ternary, TernaryOperation<DoubleVector, VectorMask<Double>>>
+         TERN_IMPL = new ImplCache<>(Ternary.class, DoubleVector.class);
+ 
+     private static TernaryOperation<DoubleVector, VectorMask<Double>> ternaryOperations(int opc_) {
+         switch (opc_) {
+             case VECTOR_OP_FMA: return (v0, v1_, v2_, m) ->
+                     v0.tOp(v1_, v2_, m, (i, a, b, c) -> Math.fma(a, b, c));
+             default: return null;
+         }
      }
  
      /**
       * Combines the lane values of this vector
       * with the values of two broadcast scalars.

@@ -886,11 +983,11 @@
      public final
      DoubleVector lanewise(VectorOperators.Ternary op, //(op,e1,e2,m)
                                    double e1,
                                    double e2,
                                    VectorMask<Double> m) {
-         return blend(lanewise(op, e1, e2), m);
+         return lanewise(op, broadcast(e1), broadcast(e2), m);
      }
  
      /**
       * Combines the lane values of this vector
       * with the values of another vector and a broadcast scalar.

@@ -944,11 +1041,11 @@
      public final
      DoubleVector lanewise(VectorOperators.Ternary op, //(op,v1,e2,m)
                                    Vector<Double> v1,
                                    double e2,
                                    VectorMask<Double> m) {
-         return blend(lanewise(op, v1, e2), m);
+         return lanewise(op, v1, broadcast(e2), m);
      }
  
      /**
       * Combines the lane values of this vector
       * with the values of another vector and a broadcast scalar.

@@ -1001,11 +1098,11 @@
      public final
      DoubleVector lanewise(VectorOperators.Ternary op, //(op,e1,v2,m)
                                    double e1,
                                    Vector<Double> v2,
                                    VectorMask<Double> m) {
-         return blend(lanewise(op, e1, v2), m);
+         return lanewise(op, broadcast(e1), v2, m);
      }
  
      // (Thus endeth the Great and Mighty Ternary Ogdoad.)
      // https://en.wikipedia.org/wiki/Ogdoad
  

@@ -1645,28 +1742,48 @@
      /*package-private*/
      @ForceInline
      final
      <M extends VectorMask<Double>>
      M compareTemplate(Class<M> maskType, Comparison op, Vector<Double> v) {
-         Objects.requireNonNull(v);
-         DoubleSpecies vsp = vspecies();
          DoubleVector that = (DoubleVector) v;
          that.check(this);
          int opc = opCode(op);
          return VectorSupport.compare(
              opc, getClass(), maskType, double.class, length(),
-             this, that,
-             (cond, v0, v1) -> {
+             this, that, null,
+             (cond, v0, v1, m1) -> {
                  AbstractMask<Double> m
                      = v0.bTest(cond, v1, (cond_, i, a, b)
                                 -> compareWithOp(cond, a, b));
                  @SuppressWarnings("unchecked")
                  M m2 = (M) m;
                  return m2;
              });
      }
  
+     /*package-private*/
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     M compareTemplate(Class<M> maskType, Comparison op, Vector<Double> v, M m) {
+         DoubleVector that = (DoubleVector) v;
+         that.check(this);
+         m.check(maskType, this);
+         int opc = opCode(op);
+         return VectorSupport.compare(
+             opc, getClass(), maskType, double.class, length(),
+             this, that, m,
+             (cond, v0, v1, m1) -> {
+                 AbstractMask<Double> cmpM
+                     = v0.bTest(cond, v1, (cond_, i, a, b)
+                                -> compareWithOp(cond, a, b));
+                 @SuppressWarnings("unchecked")
+                 M m2 = (M) cmpM.and(m1);
+                 return m2;
+             });
+     }
+ 
      @ForceInline
      private static boolean compareWithOp(int cond, double a, double b) {
          return switch (cond) {
              case BT_eq -> a == b;
              case BT_ne -> a != b;

@@ -1676,22 +1793,10 @@
              case BT_ge -> a >= b;
              default -> throw new AssertionError();
          };
      }
  
-     /**
-      * {@inheritDoc} <!--workaround-->
-      */
-     @Override
-     @ForceInline
-     public final
-     VectorMask<Double> compare(VectorOperators.Comparison op,
-                                   Vector<Double> v,
-                                   VectorMask<Double> m) {
-         return compare(op, v).and(m);
-     }
- 
      /**
       * Tests this vector by comparing it with an input scalar,
       * according to the given comparison operation.
       *
       * This is a lane-wise binary test operation which applies

@@ -1746,11 +1851,11 @@
       */
      @ForceInline
      public final VectorMask<Double> compare(VectorOperators.Comparison op,
                                                 double e,
                                                 VectorMask<Double> m) {
-         return compare(op, e).and(m);
+         return compare(op, broadcast(e), m);
      }
  
      /**
       * {@inheritDoc} <!--workaround-->
       */

@@ -1997,13 +2102,13 @@
      final
      <S extends VectorShuffle<Double>>
      DoubleVector rearrangeTemplate(Class<S> shuffletype, S shuffle) {
          shuffle.checkIndexes();
          return VectorSupport.rearrangeOp(
-             getClass(), shuffletype, double.class, length(),
-             this, shuffle,
-             (v1, s_) -> v1.uOp((i, a) -> {
+             getClass(), shuffletype, null, double.class, length(),
+             this, shuffle, null,
+             (v1, s_, m_) -> v1.uOp((i, a) -> {
                  int ei = s_.laneSource(i);
                  return v1.lane(ei);
              }));
      }
  

@@ -2016,28 +2121,29 @@
                                     VectorMask<Double> m);
  
      /*package-private*/
      @ForceInline
      final
-     <S extends VectorShuffle<Double>>
+     <S extends VectorShuffle<Double>, M extends VectorMask<Double>>
      DoubleVector rearrangeTemplate(Class<S> shuffletype,
+                                            Class<M> masktype,
                                             S shuffle,
-                                            VectorMask<Double> m) {
-         DoubleVector unmasked =
-             VectorSupport.rearrangeOp(
-                 getClass(), shuffletype, double.class, length(),
-                 this, shuffle,
-                 (v1, s_) -> v1.uOp((i, a) -> {
-                     int ei = s_.laneSource(i);
-                     return ei < 0 ? 0 : v1.lane(ei);
-                 }));
+                                            M m) {
+ 
+         m.check(masktype, this);
          VectorMask<Double> valid = shuffle.laneIsValid();
          if (m.andNot(valid).anyTrue()) {
              shuffle.checkIndexes();
              throw new AssertionError();
          }
-         return broadcast((double)0).blend(unmasked, m);
+         return VectorSupport.rearrangeOp(
+                    getClass(), shuffletype, masktype, double.class, length(),
+                    this, shuffle, m,
+                    (v1, s_, m_) -> v1.uOp((i, a) -> {
+                         int ei = s_.laneSource(i);
+                         return ei < 0  || !m_.laneIsSet(i) ? 0 : v1.lane(ei);
+                    }));
      }
  
      /**
       * {@inheritDoc} <!--workaround-->
       */

@@ -2056,21 +2162,21 @@
          VectorMask<Double> valid = shuffle.laneIsValid();
          @SuppressWarnings("unchecked")
          S ws = (S) shuffle.wrapIndexes();
          DoubleVector r0 =
              VectorSupport.rearrangeOp(
-                 getClass(), shuffletype, double.class, length(),
-                 this, ws,
-                 (v0, s_) -> v0.uOp((i, a) -> {
+                 getClass(), shuffletype, null, double.class, length(),
+                 this, ws, null,
+                 (v0, s_, m_) -> v0.uOp((i, a) -> {
                      int ei = s_.laneSource(i);
                      return v0.lane(ei);
                  }));
          DoubleVector r1 =
              VectorSupport.rearrangeOp(
-                 getClass(), shuffletype, double.class, length(),
-                 v, ws,
-                 (v1, s_) -> v1.uOp((i, a) -> {
+                 getClass(), shuffletype, null, double.class, length(),
+                 v, ws, null,
+                 (v1, s_, m_) -> v1.uOp((i, a) -> {
                      int ei = s_.laneSource(i);
                      return v1.lane(ei);
                  }));
          return r1.blend(r0, valid);
      }

@@ -2307,13 +2413,22 @@
  
      /*package-private*/
      @ForceInline
      final
      double reduceLanesTemplate(VectorOperators.Associative op,
+                                Class<? extends VectorMask<Double>> maskClass,
                                 VectorMask<Double> m) {
-         DoubleVector v = reduceIdentityVector(op).blend(this, m);
-         return v.reduceLanesTemplate(op);
+         m.check(maskClass, this);
+         if (op == FIRST_NONZERO) {
+             DoubleVector v = reduceIdentityVector(op).blend(this, m);
+             return v.reduceLanesTemplate(op);
+         }
+         int opc = opCode(op);
+         return fromBits(VectorSupport.reductionCoerced(
+             opc, getClass(), maskClass, double.class, length(),
+             this, m,
+             REDUCE_IMPL.find(op, opc, DoubleVector::reductionOperations)));
      }
  
      /*package-private*/
      @ForceInline
      final

@@ -2324,28 +2439,32 @@
                  = this.viewAsIntegralLanes().compare(NE, (long) 0);
              return this.lane(thisNZ.firstTrue());
          }
          int opc = opCode(op);
          return fromBits(VectorSupport.reductionCoerced(
-             opc, getClass(), double.class, length(),
-             this,
-             REDUCE_IMPL.find(op, opc, (opc_) -> {
-               switch (opc_) {
-               case VECTOR_OP_ADD: return v ->
-                       toBits(v.rOp((double)0, (i, a, b) -> (double)(a + b)));
-               case VECTOR_OP_MUL: return v ->
-                       toBits(v.rOp((double)1, (i, a, b) -> (double)(a * b)));
-               case VECTOR_OP_MIN: return v ->
-                       toBits(v.rOp(MAX_OR_INF, (i, a, b) -> (double) Math.min(a, b)));
-               case VECTOR_OP_MAX: return v ->
-                       toBits(v.rOp(MIN_OR_INF, (i, a, b) -> (double) Math.max(a, b)));
-               default: return null;
-               }})));
+             opc, getClass(), null, double.class, length(),
+             this, null,
+             REDUCE_IMPL.find(op, opc, DoubleVector::reductionOperations)));
      }
+ 
      private static final
-     ImplCache<Associative,Function<DoubleVector,Long>> REDUCE_IMPL
-         = new ImplCache<>(Associative.class, DoubleVector.class);
+     ImplCache<Associative, ReductionOperation<DoubleVector, VectorMask<Double>>>
+         REDUCE_IMPL = new ImplCache<>(Associative.class, DoubleVector.class);
+ 
+     private static ReductionOperation<DoubleVector, VectorMask<Double>> reductionOperations(int opc_) {
+         switch (opc_) {
+             case VECTOR_OP_ADD: return (v, m) ->
+                     toBits(v.rOp((double)0, m, (i, a, b) -> (double)(a + b)));
+             case VECTOR_OP_MUL: return (v, m) ->
+                     toBits(v.rOp((double)1, m, (i, a, b) -> (double)(a * b)));
+             case VECTOR_OP_MIN: return (v, m) ->
+                     toBits(v.rOp(MAX_OR_INF, m, (i, a, b) -> (double) Math.min(a, b)));
+             case VECTOR_OP_MAX: return (v, m) ->
+                     toBits(v.rOp(MIN_OR_INF, m, (i, a, b) -> (double) Math.max(a, b)));
+             default: return null;
+         }
+     }
  
      private
      @ForceInline
      DoubleVector reduceIdentityVector(VectorOperators.Associative op) {
          int opc = opCode(op);

@@ -2547,13 +2666,11 @@
                                         byte[] a, int offset,
                                         ByteOrder bo,
                                         VectorMask<Double> m) {
          DoubleSpecies vsp = (DoubleSpecies) species;
          if (offset >= 0 && offset <= (a.length - species.vectorByteSize())) {
-             DoubleVector zero = vsp.zero();
-             DoubleVector v = zero.fromByteArray0(a, offset);
-             return zero.blend(v.maybeSwap(bo), m);
+             return vsp.dummyVector().fromByteArray0(a, offset, m).maybeSwap(bo);
          }
  
          // FIXME: optimize
          checkMaskFromIndexSize(offset, vsp, m, 8, a.length);
          ByteBuffer wb = wrapper(a, bo);

@@ -2611,12 +2728,11 @@
      DoubleVector fromArray(VectorSpecies<Double> species,
                                     double[] a, int offset,
                                     VectorMask<Double> m) {
          DoubleSpecies vsp = (DoubleSpecies) species;
          if (offset >= 0 && offset <= (a.length - species.length())) {
-             DoubleVector zero = vsp.zero();
-             return zero.blend(zero.fromArray0(a, offset), m);
+             return vsp.dummyVector().fromArray0(a, offset, m);
          }
  
          // FIXME: optimize
          checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
          return vsp.vOp(m, i -> a[offset + i]);

@@ -2688,17 +2804,17 @@
          }
  
          vix = VectorIntrinsics.checkIndex(vix, a.length);
  
          return VectorSupport.loadWithMap(
-             vectorType, double.class, vsp.laneCount(),
-             IntVector.species(vsp.indexShape()).vectorType(),
-             a, ARRAY_BASE, vix,
+             vectorType, null, double.class, vsp.laneCount(),
+             isp.vectorType(),
+             a, ARRAY_BASE, vix, null,
              a, offset, indexMap, mapOffset, vsp,
-             (double[] c, int idx, int[] iMap, int idy, DoubleSpecies s) ->
+             (c, idx, iMap, idy, s, vm) ->
              s.vOp(n -> c[idx + iMap[idy+n]]));
-         }
+     }
  
      /**
       * Gathers a new vector composed of elements from an array of type
       * {@code double[]},
       * under the control of a mask, and

@@ -2742,13 +2858,12 @@
                                     VectorMask<Double> m) {
          if (m.allTrue()) {
              return fromArray(species, a, offset, indexMap, mapOffset);
          }
          else {
-             // FIXME: Cannot vectorize yet, if there's a mask.
              DoubleSpecies vsp = (DoubleSpecies) species;
-             return vsp.vOp(m, n -> a[offset + indexMap[mapOffset + n]]);
+             return vsp.dummyVector().fromArray0(a, offset, indexMap, mapOffset, m);
          }
      }
  
  
  

@@ -2838,13 +2953,11 @@
                                          ByteBuffer bb, int offset,
                                          ByteOrder bo,
                                          VectorMask<Double> m) {
          DoubleSpecies vsp = (DoubleSpecies) species;
          if (offset >= 0 && offset <= (bb.limit() - species.vectorByteSize())) {
-             DoubleVector zero = vsp.zero();
-             DoubleVector v = zero.fromByteBuffer0(bb, offset);
-             return zero.blend(v.maybeSwap(bo), m);
+             return vsp.dummyVector().fromByteBuffer0(bb, offset, m).maybeSwap(bo);
          }
  
          // FIXME: optimize
          checkMaskFromIndexSize(offset, vsp, m, 8, bb.limit());
          ByteBuffer wb = wrapper(bb, bo);

@@ -2912,14 +3025,13 @@
      void intoArray(double[] a, int offset,
                     VectorMask<Double> m) {
          if (m.allTrue()) {
              intoArray(a, offset);
          } else {
-             // FIXME: optimize
              DoubleSpecies vsp = vspecies();
              checkMaskFromIndexSize(offset, vsp, m, 1, a.length);
-             stOp(a, offset, m, (arr, off, i, v) -> arr[off+i] = v);
+             intoArray0(a, offset, m);
          }
      }
  
      /**
       * Scatters this vector into an array of type {@code double[]}

@@ -2978,16 +3090,16 @@
  
  
          vix = VectorIntrinsics.checkIndex(vix, a.length);
  
          VectorSupport.storeWithMap(
-             vsp.vectorType(), vsp.elementType(), vsp.laneCount(),
+             vsp.vectorType(), null, vsp.elementType(), vsp.laneCount(),
              isp.vectorType(),
              a, arrayAddress(a, 0), vix,
-             this,
+             this, null,
              a, offset, indexMap, mapOffset,
-             (arr, off, v, map, mo)
+             (arr, off, v, map, mo, vm)
              -> v.stOp(arr, off,
                        (arr_, off_, i, e) -> {
                            int j = map[mo + i];
                            arr[off + j] = e;
                        }));

@@ -3030,16 +3142,11 @@
                     VectorMask<Double> m) {
          if (m.allTrue()) {
              intoArray(a, offset, indexMap, mapOffset);
          }
          else {
-             // FIXME: Cannot vectorize yet, if there's a mask.
-             stOp(a, offset, m,
-                  (arr, off, i, e) -> {
-                      int j = indexMap[mapOffset + i];
-                      arr[off + j] = e;
-                  });
+             intoArray0(a, offset, indexMap, mapOffset, m);
          }
      }
  
  
  

@@ -3065,16 +3172,13 @@
                         ByteOrder bo,
                         VectorMask<Double> m) {
          if (m.allTrue()) {
              intoByteArray(a, offset, bo);
          } else {
-             // FIXME: optimize
              DoubleSpecies vsp = vspecies();
              checkMaskFromIndexSize(offset, vsp, m, 8, a.length);
-             ByteBuffer wb = wrapper(a, bo);
-             this.stOp(wb, offset, m,
-                     (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
+             maybeSwap(bo).intoByteArray0(a, offset, m);
          }
      }
  
      /**
       * {@inheritDoc} <!--workaround-->

@@ -3082,11 +3186,11 @@
      @Override
      @ForceInline
      public final
      void intoByteBuffer(ByteBuffer bb, int offset,
                          ByteOrder bo) {
-         if (bb.isReadOnly()) {
+         if (ScopedMemoryAccess.isReadOnly(bb)) {
              throw new ReadOnlyBufferException();
          }
          offset = checkFromIndexSize(offset, byteSize(), bb.limit());
          maybeSwap(bo).intoByteBuffer0(bb, offset);
      }

@@ -3101,19 +3205,16 @@
                          ByteOrder bo,
                          VectorMask<Double> m) {
          if (m.allTrue()) {
              intoByteBuffer(bb, offset, bo);
          } else {
-             // FIXME: optimize
              if (bb.isReadOnly()) {
                  throw new ReadOnlyBufferException();
              }
              DoubleSpecies vsp = vspecies();
              checkMaskFromIndexSize(offset, vsp, m, 8, bb.limit());
-             ByteBuffer wb = wrapper(bb, bo);
-             this.stOp(wb, offset, m,
-                     (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
+             maybeSwap(bo).intoByteBuffer0(bb, offset, m);
          }
      }
  
      // ================================================
  

@@ -3147,10 +3248,79 @@
              a, offset, vsp,
              (arr, off, s) -> s.ldOp(arr, off,
                                      (arr_, off_, i) -> arr_[off_ + i]));
      }
  
+     /*package-private*/
+     abstract
+     DoubleVector fromArray0(double[] a, int offset, VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     DoubleVector fromArray0Template(Class<M> maskClass, double[] a, int offset, M m) {
+         m.check(species());
+         DoubleSpecies vsp = vspecies();
+         return VectorSupport.loadMasked(
+             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
+             a, arrayAddress(a, offset), m,
+             a, offset, vsp,
+             (arr, off, s, vm) -> s.ldOp(arr, off, vm,
+                                         (arr_, off_, i) -> arr_[off_ + i]));
+     }
+ 
+     /*package-private*/
+     abstract
+     DoubleVector fromArray0(double[] a, int offset,
+                                     int[] indexMap, int mapOffset,
+                                     VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     DoubleVector fromArray0Template(Class<M> maskClass, double[] a, int offset,
+                                             int[] indexMap, int mapOffset, M m) {
+         DoubleSpecies vsp = vspecies();
+         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
+         Objects.requireNonNull(a);
+         Objects.requireNonNull(indexMap);
+         m.check(vsp);
+         Class<? extends DoubleVector> vectorType = vsp.vectorType();
+ 
+         if (vsp.laneCount() == 1) {
+           return DoubleVector.fromArray(vsp, a, offset + indexMap[mapOffset], m);
+         }
+ 
+         // Index vector: vix[0:n] = k -> offset + indexMap[mapOffset + k]
+         IntVector vix;
+         if (isp.laneCount() != vsp.laneCount()) {
+             // For DoubleMaxVector,  if vector length is non-power-of-two or
+             // 2048 bits, indexShape of Double species is S_MAX_BIT.
+             // Assume that vector length is 2048, then the lane count of Double
+             // vector is 32. When converting Double species to int species,
+             // indexShape is still S_MAX_BIT, but the lane count of int vector
+             // is 64. So when loading index vector (IntVector), only lower half
+             // of index data is needed.
+             vix = IntVector
+                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
+                 .add(offset);
+         } else {
+             vix = IntVector
+                 .fromArray(isp, indexMap, mapOffset)
+                 .add(offset);
+         }
+ 
+         // FIXME: Check index under mask controlling.
+         vix = VectorIntrinsics.checkIndex(vix, a.length);
+ 
+         return VectorSupport.loadWithMap(
+             vectorType, maskClass, double.class, vsp.laneCount(),
+             isp.vectorType(),
+             a, ARRAY_BASE, vix, m,
+             a, offset, indexMap, mapOffset, vsp,
+             (c, idx, iMap, idy, s, vm) ->
+             s.vOp(vm, n -> c[idx + iMap[idy+n]]));
+     }
+ 
  
  
      @Override
      abstract
      DoubleVector fromByteArray0(byte[] a, int offset);

@@ -3167,10 +3337,29 @@
                  return s.ldOp(wb, off,
                          (wb_, o, i) -> wb_.getDouble(o + i * 8));
              });
      }
  
+     abstract
+     DoubleVector fromByteArray0(byte[] a, int offset, VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     DoubleVector fromByteArray0Template(Class<M> maskClass, byte[] a, int offset, M m) {
+         DoubleSpecies vsp = vspecies();
+         m.check(vsp);
+         return VectorSupport.loadMasked(
+             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
+             a, byteArrayAddress(a, offset), m,
+             a, offset, vsp,
+             (arr, off, s, vm) -> {
+                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
+                 return s.ldOp(wb, off, vm,
+                         (wb_, o, i) -> wb_.getDouble(o + i * 8));
+             });
+     }
+ 
      abstract
      DoubleVector fromByteBuffer0(ByteBuffer bb, int offset);
      @ForceInline
      final
      DoubleVector fromByteBuffer0Template(ByteBuffer bb, int offset) {

@@ -3183,10 +3372,28 @@
                      return s.ldOp(wb, off,
                              (wb_, o, i) -> wb_.getDouble(o + i * 8));
                  });
      }
  
+     abstract
+     DoubleVector fromByteBuffer0(ByteBuffer bb, int offset, VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     DoubleVector fromByteBuffer0Template(Class<M> maskClass, ByteBuffer bb, int offset, M m) {
+         DoubleSpecies vsp = vspecies();
+         m.check(vsp);
+         return ScopedMemoryAccess.loadFromByteBufferMasked(
+                 vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
+                 bb, offset, m, vsp,
+                 (buf, off, s, vm) -> {
+                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
+                     return s.ldOp(wb, off, vm,
+                             (wb_, o, i) -> wb_.getDouble(o + i * 8));
+                 });
+     }
+ 
      // Unchecked storing operations in native byte order.
      // Caller is responsible for applying index checks, masking, and
      // byte swapping.
  
      abstract

@@ -3202,10 +3409,81 @@
              (arr, off, v)
              -> v.stOp(arr, off,
                        (arr_, off_, i, e) -> arr_[off_+i] = e));
      }
  
+     abstract
+     void intoArray0(double[] a, int offset, VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     void intoArray0Template(Class<M> maskClass, double[] a, int offset, M m) {
+         m.check(species());
+         DoubleSpecies vsp = vspecies();
+         VectorSupport.storeMasked(
+             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
+             a, arrayAddress(a, offset),
+             this, m, a, offset,
+             (arr, off, v, vm)
+             -> v.stOp(arr, off, vm,
+                       (arr_, off_, i, e) -> arr_[off_ + i] = e));
+     }
+ 
+     abstract
+     void intoArray0(double[] a, int offset,
+                     int[] indexMap, int mapOffset,
+                     VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     void intoArray0Template(Class<M> maskClass, double[] a, int offset,
+                             int[] indexMap, int mapOffset, M m) {
+         m.check(species());
+         DoubleSpecies vsp = vspecies();
+         IntVector.IntSpecies isp = IntVector.species(vsp.indexShape());
+         if (vsp.laneCount() == 1) {
+             intoArray(a, offset + indexMap[mapOffset], m);
+             return;
+         }
+ 
+         // Index vector: vix[0:n] = i -> offset + indexMap[mo + i]
+         IntVector vix;
+         if (isp.laneCount() != vsp.laneCount()) {
+             // For DoubleMaxVector,  if vector length  is 2048 bits, indexShape
+             // of Double species is S_MAX_BIT. and the lane count of Double
+             // vector is 32. When converting Double species to int species,
+             // indexShape is still S_MAX_BIT, but the lane count of int vector
+             // is 64. So when loading index vector (IntVector), only lower half
+             // of index data is needed.
+             vix = IntVector
+                 .fromArray(isp, indexMap, mapOffset, IntMaxVector.IntMaxMask.LOWER_HALF_TRUE_MASK)
+                 .add(offset);
+         } else {
+             vix = IntVector
+                 .fromArray(isp, indexMap, mapOffset)
+                 .add(offset);
+         }
+ 
+ 
+         // FIXME: Check index under mask controlling.
+         vix = VectorIntrinsics.checkIndex(vix, a.length);
+ 
+         VectorSupport.storeWithMap(
+             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
+             isp.vectorType(),
+             a, arrayAddress(a, 0), vix,
+             this, m,
+             a, offset, indexMap, mapOffset,
+             (arr, off, v, map, mo, vm)
+             -> v.stOp(arr, off, vm,
+                       (arr_, off_, i, e) -> {
+                           int j = map[mo + i];
+                           arr[off + j] = e;
+                       }));
+     }
+ 
+ 
      abstract
      void intoByteArray0(byte[] a, int offset);
      @ForceInline
      final
      void intoByteArray0Template(byte[] a, int offset) {

@@ -3219,10 +3497,29 @@
                  v.stOp(wb, off,
                          (tb_, o, i, e) -> tb_.putDouble(o + i * 8, e));
              });
      }
  
+     abstract
+     void intoByteArray0(byte[] a, int offset, VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     void intoByteArray0Template(Class<M> maskClass, byte[] a, int offset, M m) {
+         DoubleSpecies vsp = vspecies();
+         m.check(vsp);
+         VectorSupport.storeMasked(
+             vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
+             a, byteArrayAddress(a, offset),
+             this, m, a, offset,
+             (arr, off, v, vm) -> {
+                 ByteBuffer wb = wrapper(arr, NATIVE_ENDIAN);
+                 v.stOp(wb, off, vm,
+                         (tb_, o, i, e) -> tb_.putDouble(o + i * 8, e));
+             });
+     }
+ 
      @ForceInline
      final
      void intoByteBuffer0(ByteBuffer bb, int offset) {
          DoubleSpecies vsp = vspecies();
          ScopedMemoryAccess.storeIntoByteBuffer(

@@ -3233,10 +3530,29 @@
                      v.stOp(wb, off,
                              (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
                  });
      }
  
+     abstract
+     void intoByteBuffer0(ByteBuffer bb, int offset, VectorMask<Double> m);
+     @ForceInline
+     final
+     <M extends VectorMask<Double>>
+     void intoByteBuffer0Template(Class<M> maskClass, ByteBuffer bb, int offset, M m) {
+         DoubleSpecies vsp = vspecies();
+         m.check(vsp);
+         ScopedMemoryAccess.storeIntoByteBufferMasked(
+                 vsp.vectorType(), maskClass, vsp.elementType(), vsp.laneCount(),
+                 this, m, bb, offset,
+                 (buf, off, v, vm) -> {
+                     ByteBuffer wb = wrapper(buf, NATIVE_ENDIAN);
+                     v.stOp(wb, off, vm,
+                             (wb_, o, i, e) -> wb_.putDouble(o + i * 8, e));
+                 });
+     }
+ 
+ 
      // End of low-level memory operations.
  
      private static
      void checkMaskFromIndexSize(int offset,
                                  DoubleSpecies vsp,

@@ -3550,11 +3866,11 @@
          }
  
          /*package-private*/
          @ForceInline
          <M> DoubleVector ldOp(M memory, int offset,
-                                       AbstractMask<Double> m,
+                                       VectorMask<Double> m,
                                        FLdOp<M> f) {
              return dummyVector().ldOp(memory, offset, m, f);
          }
  
          /*package-private*/
< prev index next >