changeset 58907:21f94abc4b32 vectorIntrinsics

JDK-8222290: [vector] Implement Species flattening Summary: Change the species hierarchy to make it flatter, remove XxxNnnSpecie and provide Species<Xxx> Reviewed-by: vlivanov Contributed-by: briangoetz, kkharbas, sviswanathan
author kkharbas
date Wed, 10 Apr 2019 12:05:46 -0700
parents 7869415891c8
children c94042f0aff8 d7b52a030a56
files src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Vector.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorIntrinsics.java src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template src/jdk.incubator.vector/share/classes/jdk/incubator/vector/gen-src.sh src/jdk.incubator.vector/share/classes/jdk/incubator/vector/package-info.java test/jdk/jdk/incubator/vector/AddTest.java test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Byte128VectorTests.java test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Byte256VectorTests.java test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Byte512VectorTests.java test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Byte64VectorTests.java test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java test/jdk/jdk/incubator/vector/CovarOverrideTest.java test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Double128VectorTests.java test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Double256VectorTests.java test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Double512VectorTests.java test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Double64VectorTests.java test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Float128VectorTests.java test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Float256VectorTests.java test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Float512VectorTests.java test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Float64VectorTests.java test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Int128VectorTests.java test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Int256VectorTests.java test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Int512VectorTests.java test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Int64VectorTests.java test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java test/jdk/jdk/incubator/vector/IntMaxVectorTests.java test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Long128VectorTests.java test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Long256VectorTests.java test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Long512VectorTests.java test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Long64VectorTests.java test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java test/jdk/jdk/incubator/vector/LongMaxVectorTests.java test/jdk/jdk/incubator/vector/MethodOverideTest.java test/jdk/jdk/incubator/vector/PreferredSpeciesTest.java test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Short128VectorTests.java test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Short256VectorTests.java test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Short512VectorTests.java test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java test/jdk/jdk/incubator/vector/Short64VectorTests.java test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java test/jdk/jdk/incubator/vector/VectorArrays.java test/jdk/jdk/incubator/vector/VectorHash.java test/jdk/jdk/incubator/vector/VectorReshapeTests.java test/jdk/jdk/incubator/vector/VectorRuns.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/crypto/ChaChaBench.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/crypto/Poly1305Bench.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/AbstractVectorBenchmark.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Byte128Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Byte256Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Byte512Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Byte64Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/ByteMaxVector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Double128Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Double256Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Double512Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Double64Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/DoubleMaxVector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Float128Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Float256Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Float512Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Float64Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/FloatMaxVector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Int128Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Int256Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Int512Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Int64Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/IntMaxVector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Long128Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Long256Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Long512Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Long64Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/LongMaxVector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Merge.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/PopulationCount.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Short128Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Short256Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Short512Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/Short64Vector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/ShortMaxVector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/SortVector.java test/jdk/jdk/incubator/vector/benchmark/src/main/java/benchmark/jdk/incubator/vector/SumOfUnsignedBytes.java test/jdk/jdk/incubator/vector/gen-tests.sh test/jdk/jdk/incubator/vector/templates/Perf-header.template test/jdk/jdk/incubator/vector/templates/Unit-header.template test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template
diffstat 150 files changed, 5387 insertions(+), 7583 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte128Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -37,7 +37,7 @@
 
 @SuppressWarnings("cast")
 final class Byte128Vector extends ByteVector {
-    static final Byte128Species SPECIES = new Byte128Species();
+    private static final Species<Byte> SPECIES = ByteVector.SPECIES_128;
 
     static final Byte128Vector ZERO = new Byte128Vector();
 
@@ -154,7 +154,7 @@
         return VectorIntrinsics.cast(
             Byte128Vector.class,
             byte.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -172,37 +172,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -292,55 +292,50 @@
     @ForceInline
     public ByteVector reshape(Species<Byte> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Byte64Vector.Byte64Species)) {
-            Byte64Vector.Byte64Species ts = (Byte64Vector.Byte64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Byte64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte128Vector.class,
                 byte.class, LENGTH,
                 Byte64Vector.class,
                 byte.class, Byte64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Byte128Vector.Byte128Species)) {
-            Byte128Vector.Byte128Species ts = (Byte128Vector.Byte128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Byte128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte128Vector.class,
                 byte.class, LENGTH,
                 Byte128Vector.class,
                 byte.class, Byte128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Byte256Vector.Byte256Species)) {
-            Byte256Vector.Byte256Species ts = (Byte256Vector.Byte256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Byte256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte128Vector.class,
                 byte.class, LENGTH,
                 Byte256Vector.class,
                 byte.class, Byte256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Byte512Vector.Byte512Species)) {
-            Byte512Vector.Byte512Species ts = (Byte512Vector.Byte512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Byte512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte128Vector.class,
                 byte.class, LENGTH,
                 Byte512Vector.class,
                 byte.class, Byte512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof ByteMaxVector.ByteMaxSpecies)) {
-            ByteMaxVector.ByteMaxSpecies ts = (ByteMaxVector.ByteMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == ByteMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte128Vector.class,
                 byte.class, LENGTH,
                 ByteMaxVector.class,
                 byte.class, ByteMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -353,128 +348,128 @@
     @Override
     @ForceInline
     public ByteVector add(byte o) {
-        return add(SPECIES.broadcast(o));
+        return add((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector add(byte o, Mask<Byte> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Byte128Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o, Mask<Byte> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Byte128Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o, Mask<Byte> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Byte128Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector min(byte o) {
-        return min(SPECIES.broadcast(o));
+        return min((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector max(byte o) {
-        return max(SPECIES.broadcast(o));
+        return max((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> equal(byte o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> notEqual(byte o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThan(byte o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThanEq(byte o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThan(byte o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThanEq(byte o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector blend(byte o, Mask<Byte> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
 
     @Override
     @ForceInline
     public ByteVector and(byte o) {
-        return and(SPECIES.broadcast(o));
+        return and((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector and(byte o, Mask<Byte> m) {
-        return and(SPECIES.broadcast(o), m);
+        return and((Byte128Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o) {
-        return or(SPECIES.broadcast(o));
+        return or((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o, Mask<Byte> m) {
-        return or(SPECIES.broadcast(o), m);
+        return or((Byte128Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o) {
-        return xor(SPECIES.broadcast(o));
+        return xor((Byte128Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o, Mask<Byte> m) {
-        return xor(SPECIES.broadcast(o), m);
+        return xor((Byte128Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -729,7 +724,7 @@
     @Override
     @ForceInline
     public byte andAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) -1).blend(this, m).andAll();
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, (byte) -1), m).andAll();
     }
 
     @Override
@@ -771,7 +766,7 @@
     @Override
     @ForceInline
     public byte orAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).orAll();
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).orAll();
     }
 
     @Override
@@ -786,33 +781,33 @@
     @Override
     @ForceInline
     public byte xorAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).xorAll();
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).xorAll();
     }
 
 
     @Override
     @ForceInline
     public byte addAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).addAll();
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public byte mulAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 1).blend(this, m).mulAll();
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, (byte) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public byte minAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MAX_VALUE).blend(this, m).minAll();
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, Byte.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public byte maxAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Byte128Vector)ByteVector.broadcast(SPECIES, Byte.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -1196,7 +1191,7 @@
         }
 
         @Override
-        public Byte128Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1212,6 +1207,31 @@
             return new Byte128Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte128Vector.Byte128Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short128Vector.Short128Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int128Vector.Int128Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long128Vector.Long128Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float128Vector.Float128Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double128Vector.Double128Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1284,7 +1304,7 @@
         }
 
         @Override
-        public Byte128Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1298,6 +1318,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte128Vector.Byte128Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short128Vector.Short128Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int128Vector.Int128Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long128Vector.Long128Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float128Vector.Float128Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double128Vector.Double128Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Byte128Shuffle rearrange(Vector.Shuffle<Byte> o) {
             Byte128Shuffle s = (Byte128Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1311,148 +1356,7 @@
     // Species
 
     @Override
-    public Byte128Species species() {
+    public Species<Byte> species() {
         return SPECIES;
     }
-
-    static final class Byte128Species extends ByteSpecies {
-        static final int BIT_SIZE = Shape.S_128_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Byte.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(byte.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Byte> elementType() {
-            return byte.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Byte128Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Byte128Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Byte.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Byte128Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_128_BIT;
-        }
-
-        @Override
-        Byte128Vector op(FOp f) {
-            byte[] res = new byte[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Byte128Vector(res);
-        }
-
-        @Override
-        Byte128Vector op(Mask<Byte> o, FOp f) {
-            byte[] res = new byte[length()];
-            boolean[] mbits = ((Byte128Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Byte128Vector(res);
-        }
-
-        @Override
-        Byte128Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Byte128Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Byte128Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Byte128Vector.class, byte.class, LENGTH,
-                                                     0, SPECIES,
-                                                     ((bits, s) -> ((Byte128Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte128Vector broadcast(byte e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Byte128Vector.class, byte.class, LENGTH,
-                e, SPECIES,
-                ((bits, s) -> ((Byte128Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte128Vector scalars(byte... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Byte128Vector.class, byte.class, LENGTH,
-                                         es, Unsafe.ARRAY_BYTE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Byte128Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte128Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Byte128Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte128Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Byte128Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte256Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -37,7 +37,7 @@
 
 @SuppressWarnings("cast")
 final class Byte256Vector extends ByteVector {
-    static final Byte256Species SPECIES = new Byte256Species();
+    private static final Species<Byte> SPECIES = ByteVector.SPECIES_256;
 
     static final Byte256Vector ZERO = new Byte256Vector();
 
@@ -154,7 +154,7 @@
         return VectorIntrinsics.cast(
             Byte256Vector.class,
             byte.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -172,37 +172,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -292,55 +292,50 @@
     @ForceInline
     public ByteVector reshape(Species<Byte> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Byte64Vector.Byte64Species)) {
-            Byte64Vector.Byte64Species ts = (Byte64Vector.Byte64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Byte64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte256Vector.class,
                 byte.class, LENGTH,
                 Byte64Vector.class,
                 byte.class, Byte64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Byte128Vector.Byte128Species)) {
-            Byte128Vector.Byte128Species ts = (Byte128Vector.Byte128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Byte128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte256Vector.class,
                 byte.class, LENGTH,
                 Byte128Vector.class,
                 byte.class, Byte128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Byte256Vector.Byte256Species)) {
-            Byte256Vector.Byte256Species ts = (Byte256Vector.Byte256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Byte256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte256Vector.class,
                 byte.class, LENGTH,
                 Byte256Vector.class,
                 byte.class, Byte256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Byte512Vector.Byte512Species)) {
-            Byte512Vector.Byte512Species ts = (Byte512Vector.Byte512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Byte512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte256Vector.class,
                 byte.class, LENGTH,
                 Byte512Vector.class,
                 byte.class, Byte512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof ByteMaxVector.ByteMaxSpecies)) {
-            ByteMaxVector.ByteMaxSpecies ts = (ByteMaxVector.ByteMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == ByteMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte256Vector.class,
                 byte.class, LENGTH,
                 ByteMaxVector.class,
                 byte.class, ByteMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -353,128 +348,128 @@
     @Override
     @ForceInline
     public ByteVector add(byte o) {
-        return add(SPECIES.broadcast(o));
+        return add((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector add(byte o, Mask<Byte> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Byte256Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o, Mask<Byte> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Byte256Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o, Mask<Byte> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Byte256Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector min(byte o) {
-        return min(SPECIES.broadcast(o));
+        return min((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector max(byte o) {
-        return max(SPECIES.broadcast(o));
+        return max((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> equal(byte o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> notEqual(byte o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThan(byte o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThanEq(byte o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThan(byte o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThanEq(byte o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector blend(byte o, Mask<Byte> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
 
     @Override
     @ForceInline
     public ByteVector and(byte o) {
-        return and(SPECIES.broadcast(o));
+        return and((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector and(byte o, Mask<Byte> m) {
-        return and(SPECIES.broadcast(o), m);
+        return and((Byte256Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o) {
-        return or(SPECIES.broadcast(o));
+        return or((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o, Mask<Byte> m) {
-        return or(SPECIES.broadcast(o), m);
+        return or((Byte256Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o) {
-        return xor(SPECIES.broadcast(o));
+        return xor((Byte256Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o, Mask<Byte> m) {
-        return xor(SPECIES.broadcast(o), m);
+        return xor((Byte256Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -729,7 +724,7 @@
     @Override
     @ForceInline
     public byte andAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) -1).blend(this, m).andAll();
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, (byte) -1), m).andAll();
     }
 
     @Override
@@ -771,7 +766,7 @@
     @Override
     @ForceInline
     public byte orAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).orAll();
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).orAll();
     }
 
     @Override
@@ -786,33 +781,33 @@
     @Override
     @ForceInline
     public byte xorAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).xorAll();
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).xorAll();
     }
 
 
     @Override
     @ForceInline
     public byte addAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).addAll();
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public byte mulAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 1).blend(this, m).mulAll();
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, (byte) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public byte minAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MAX_VALUE).blend(this, m).minAll();
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, Byte.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public byte maxAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Byte256Vector)ByteVector.broadcast(SPECIES, Byte.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -1196,7 +1191,7 @@
         }
 
         @Override
-        public Byte256Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1212,6 +1207,31 @@
             return new Byte256Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte256Vector.Byte256Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short256Vector.Short256Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int256Vector.Int256Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long256Vector.Long256Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float256Vector.Float256Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double256Vector.Double256Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1284,7 +1304,7 @@
         }
 
         @Override
-        public Byte256Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1298,6 +1318,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte256Vector.Byte256Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short256Vector.Short256Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int256Vector.Int256Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long256Vector.Long256Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float256Vector.Float256Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double256Vector.Double256Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Byte256Shuffle rearrange(Vector.Shuffle<Byte> o) {
             Byte256Shuffle s = (Byte256Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1311,148 +1356,7 @@
     // Species
 
     @Override
-    public Byte256Species species() {
+    public Species<Byte> species() {
         return SPECIES;
     }
-
-    static final class Byte256Species extends ByteSpecies {
-        static final int BIT_SIZE = Shape.S_256_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Byte.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(byte.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Byte> elementType() {
-            return byte.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Byte256Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Byte256Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Byte.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Byte256Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_256_BIT;
-        }
-
-        @Override
-        Byte256Vector op(FOp f) {
-            byte[] res = new byte[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Byte256Vector(res);
-        }
-
-        @Override
-        Byte256Vector op(Mask<Byte> o, FOp f) {
-            byte[] res = new byte[length()];
-            boolean[] mbits = ((Byte256Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Byte256Vector(res);
-        }
-
-        @Override
-        Byte256Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Byte256Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Byte256Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Byte256Vector.class, byte.class, LENGTH,
-                                                     0, SPECIES,
-                                                     ((bits, s) -> ((Byte256Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte256Vector broadcast(byte e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Byte256Vector.class, byte.class, LENGTH,
-                e, SPECIES,
-                ((bits, s) -> ((Byte256Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte256Vector scalars(byte... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Byte256Vector.class, byte.class, LENGTH,
-                                         es, Unsafe.ARRAY_BYTE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Byte256Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte256Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Byte256Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte256Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Byte256Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte512Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -37,7 +37,7 @@
 
 @SuppressWarnings("cast")
 final class Byte512Vector extends ByteVector {
-    static final Byte512Species SPECIES = new Byte512Species();
+    private static final Species<Byte> SPECIES = ByteVector.SPECIES_512;
 
     static final Byte512Vector ZERO = new Byte512Vector();
 
@@ -154,7 +154,7 @@
         return VectorIntrinsics.cast(
             Byte512Vector.class,
             byte.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -172,37 +172,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -292,55 +292,50 @@
     @ForceInline
     public ByteVector reshape(Species<Byte> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Byte64Vector.Byte64Species)) {
-            Byte64Vector.Byte64Species ts = (Byte64Vector.Byte64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Byte64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte512Vector.class,
                 byte.class, LENGTH,
                 Byte64Vector.class,
                 byte.class, Byte64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Byte128Vector.Byte128Species)) {
-            Byte128Vector.Byte128Species ts = (Byte128Vector.Byte128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Byte128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte512Vector.class,
                 byte.class, LENGTH,
                 Byte128Vector.class,
                 byte.class, Byte128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Byte256Vector.Byte256Species)) {
-            Byte256Vector.Byte256Species ts = (Byte256Vector.Byte256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Byte256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte512Vector.class,
                 byte.class, LENGTH,
                 Byte256Vector.class,
                 byte.class, Byte256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Byte512Vector.Byte512Species)) {
-            Byte512Vector.Byte512Species ts = (Byte512Vector.Byte512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Byte512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte512Vector.class,
                 byte.class, LENGTH,
                 Byte512Vector.class,
                 byte.class, Byte512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof ByteMaxVector.ByteMaxSpecies)) {
-            ByteMaxVector.ByteMaxSpecies ts = (ByteMaxVector.ByteMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == ByteMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte512Vector.class,
                 byte.class, LENGTH,
                 ByteMaxVector.class,
                 byte.class, ByteMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -353,128 +348,128 @@
     @Override
     @ForceInline
     public ByteVector add(byte o) {
-        return add(SPECIES.broadcast(o));
+        return add((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector add(byte o, Mask<Byte> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Byte512Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o, Mask<Byte> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Byte512Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o, Mask<Byte> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Byte512Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector min(byte o) {
-        return min(SPECIES.broadcast(o));
+        return min((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector max(byte o) {
-        return max(SPECIES.broadcast(o));
+        return max((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> equal(byte o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> notEqual(byte o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThan(byte o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThanEq(byte o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThan(byte o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThanEq(byte o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector blend(byte o, Mask<Byte> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
 
     @Override
     @ForceInline
     public ByteVector and(byte o) {
-        return and(SPECIES.broadcast(o));
+        return and((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector and(byte o, Mask<Byte> m) {
-        return and(SPECIES.broadcast(o), m);
+        return and((Byte512Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o) {
-        return or(SPECIES.broadcast(o));
+        return or((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o, Mask<Byte> m) {
-        return or(SPECIES.broadcast(o), m);
+        return or((Byte512Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o) {
-        return xor(SPECIES.broadcast(o));
+        return xor((Byte512Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o, Mask<Byte> m) {
-        return xor(SPECIES.broadcast(o), m);
+        return xor((Byte512Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -729,7 +724,7 @@
     @Override
     @ForceInline
     public byte andAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) -1).blend(this, m).andAll();
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, (byte) -1), m).andAll();
     }
 
     @Override
@@ -771,7 +766,7 @@
     @Override
     @ForceInline
     public byte orAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).orAll();
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).orAll();
     }
 
     @Override
@@ -786,33 +781,33 @@
     @Override
     @ForceInline
     public byte xorAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).xorAll();
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).xorAll();
     }
 
 
     @Override
     @ForceInline
     public byte addAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).addAll();
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public byte mulAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 1).blend(this, m).mulAll();
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, (byte) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public byte minAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MAX_VALUE).blend(this, m).minAll();
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, Byte.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public byte maxAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Byte512Vector)ByteVector.broadcast(SPECIES, Byte.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -1196,7 +1191,7 @@
         }
 
         @Override
-        public Byte512Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1212,6 +1207,31 @@
             return new Byte512Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte512Vector.Byte512Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short512Vector.Short512Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int512Vector.Int512Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long512Vector.Long512Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float512Vector.Float512Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double512Vector.Double512Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1284,7 +1304,7 @@
         }
 
         @Override
-        public Byte512Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1298,6 +1318,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte512Vector.Byte512Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short512Vector.Short512Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int512Vector.Int512Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long512Vector.Long512Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float512Vector.Float512Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double512Vector.Double512Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Byte512Shuffle rearrange(Vector.Shuffle<Byte> o) {
             Byte512Shuffle s = (Byte512Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1311,148 +1356,7 @@
     // Species
 
     @Override
-    public Byte512Species species() {
+    public Species<Byte> species() {
         return SPECIES;
     }
-
-    static final class Byte512Species extends ByteSpecies {
-        static final int BIT_SIZE = Shape.S_512_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Byte.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(byte.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Byte> elementType() {
-            return byte.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Byte512Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Byte512Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Byte.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Byte512Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_512_BIT;
-        }
-
-        @Override
-        Byte512Vector op(FOp f) {
-            byte[] res = new byte[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Byte512Vector(res);
-        }
-
-        @Override
-        Byte512Vector op(Mask<Byte> o, FOp f) {
-            byte[] res = new byte[length()];
-            boolean[] mbits = ((Byte512Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Byte512Vector(res);
-        }
-
-        @Override
-        Byte512Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Byte512Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Byte512Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Byte512Vector.class, byte.class, LENGTH,
-                                                     0, SPECIES,
-                                                     ((bits, s) -> ((Byte512Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte512Vector broadcast(byte e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Byte512Vector.class, byte.class, LENGTH,
-                e, SPECIES,
-                ((bits, s) -> ((Byte512Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte512Vector scalars(byte... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Byte512Vector.class, byte.class, LENGTH,
-                                         es, Unsafe.ARRAY_BYTE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Byte512Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte512Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Byte512Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte512Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Byte512Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Byte64Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -37,7 +37,7 @@
 
 @SuppressWarnings("cast")
 final class Byte64Vector extends ByteVector {
-    static final Byte64Species SPECIES = new Byte64Species();
+    private static final Species<Byte> SPECIES = ByteVector.SPECIES_64;
 
     static final Byte64Vector ZERO = new Byte64Vector();
 
@@ -154,7 +154,7 @@
         return VectorIntrinsics.cast(
             Byte64Vector.class,
             byte.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -172,37 +172,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -292,55 +292,50 @@
     @ForceInline
     public ByteVector reshape(Species<Byte> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Byte64Vector.Byte64Species)) {
-            Byte64Vector.Byte64Species ts = (Byte64Vector.Byte64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Byte64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte64Vector.class,
                 byte.class, LENGTH,
                 Byte64Vector.class,
                 byte.class, Byte64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Byte128Vector.Byte128Species)) {
-            Byte128Vector.Byte128Species ts = (Byte128Vector.Byte128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Byte128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte64Vector.class,
                 byte.class, LENGTH,
                 Byte128Vector.class,
                 byte.class, Byte128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Byte256Vector.Byte256Species)) {
-            Byte256Vector.Byte256Species ts = (Byte256Vector.Byte256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Byte256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte64Vector.class,
                 byte.class, LENGTH,
                 Byte256Vector.class,
                 byte.class, Byte256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Byte512Vector.Byte512Species)) {
-            Byte512Vector.Byte512Species ts = (Byte512Vector.Byte512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Byte512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte64Vector.class,
                 byte.class, LENGTH,
                 Byte512Vector.class,
                 byte.class, Byte512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof ByteMaxVector.ByteMaxSpecies)) {
-            ByteMaxVector.ByteMaxSpecies ts = (ByteMaxVector.ByteMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == ByteMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Byte64Vector.class,
                 byte.class, LENGTH,
                 ByteMaxVector.class,
                 byte.class, ByteMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -353,128 +348,128 @@
     @Override
     @ForceInline
     public ByteVector add(byte o) {
-        return add(SPECIES.broadcast(o));
+        return add((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector add(byte o, Mask<Byte> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Byte64Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o, Mask<Byte> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Byte64Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o, Mask<Byte> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Byte64Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector min(byte o) {
-        return min(SPECIES.broadcast(o));
+        return min((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector max(byte o) {
-        return max(SPECIES.broadcast(o));
+        return max((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> equal(byte o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> notEqual(byte o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThan(byte o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThanEq(byte o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThan(byte o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThanEq(byte o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector blend(byte o, Mask<Byte> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
 
     @Override
     @ForceInline
     public ByteVector and(byte o) {
-        return and(SPECIES.broadcast(o));
+        return and((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector and(byte o, Mask<Byte> m) {
-        return and(SPECIES.broadcast(o), m);
+        return and((Byte64Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o) {
-        return or(SPECIES.broadcast(o));
+        return or((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o, Mask<Byte> m) {
-        return or(SPECIES.broadcast(o), m);
+        return or((Byte64Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o) {
-        return xor(SPECIES.broadcast(o));
+        return xor((Byte64Vector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o, Mask<Byte> m) {
-        return xor(SPECIES.broadcast(o), m);
+        return xor((Byte64Vector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -729,7 +724,7 @@
     @Override
     @ForceInline
     public byte andAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) -1).blend(this, m).andAll();
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, (byte) -1), m).andAll();
     }
 
     @Override
@@ -771,7 +766,7 @@
     @Override
     @ForceInline
     public byte orAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).orAll();
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).orAll();
     }
 
     @Override
@@ -786,33 +781,33 @@
     @Override
     @ForceInline
     public byte xorAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).xorAll();
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).xorAll();
     }
 
 
     @Override
     @ForceInline
     public byte addAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).addAll();
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, (byte) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public byte mulAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 1).blend(this, m).mulAll();
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, (byte) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public byte minAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MAX_VALUE).blend(this, m).minAll();
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, Byte.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public byte maxAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Byte64Vector)ByteVector.broadcast(SPECIES, Byte.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -1196,7 +1191,7 @@
         }
 
         @Override
-        public Byte64Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1212,6 +1207,31 @@
             return new Byte64Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte64Vector.Byte64Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short64Vector.Short64Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int64Vector.Int64Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long64Vector.Long64Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float64Vector.Float64Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double64Vector.Double64Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1284,7 +1304,7 @@
         }
 
         @Override
-        public Byte64Species species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1298,6 +1318,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte64Vector.Byte64Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short64Vector.Short64Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int64Vector.Int64Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long64Vector.Long64Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float64Vector.Float64Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double64Vector.Double64Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Byte64Shuffle rearrange(Vector.Shuffle<Byte> o) {
             Byte64Shuffle s = (Byte64Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1311,148 +1356,7 @@
     // Species
 
     @Override
-    public Byte64Species species() {
+    public Species<Byte> species() {
         return SPECIES;
     }
-
-    static final class Byte64Species extends ByteSpecies {
-        static final int BIT_SIZE = Shape.S_64_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Byte.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(byte.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Byte> elementType() {
-            return byte.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Byte64Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Byte64Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Byte.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Byte64Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_64_BIT;
-        }
-
-        @Override
-        Byte64Vector op(FOp f) {
-            byte[] res = new byte[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Byte64Vector(res);
-        }
-
-        @Override
-        Byte64Vector op(Mask<Byte> o, FOp f) {
-            byte[] res = new byte[length()];
-            boolean[] mbits = ((Byte64Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Byte64Vector(res);
-        }
-
-        @Override
-        Byte64Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Byte64Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Byte64Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Byte64Vector.class, byte.class, LENGTH,
-                                                     0, SPECIES,
-                                                     ((bits, s) -> ((Byte64Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte64Vector broadcast(byte e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Byte64Vector.class, byte.class, LENGTH,
-                e, SPECIES,
-                ((bits, s) -> ((Byte64Species)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public Byte64Vector scalars(byte... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Byte64Vector.class, byte.class, LENGTH,
-                                         es, Unsafe.ARRAY_BYTE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Byte64Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte64Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Byte64Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Byte64Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Byte64Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteMaxVector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -37,7 +37,7 @@
 
 @SuppressWarnings("cast")
 final class ByteMaxVector extends ByteVector {
-    static final ByteMaxSpecies SPECIES = new ByteMaxSpecies();
+    private static final Species<Byte> SPECIES = ByteVector.SPECIES_MAX;
 
     static final ByteMaxVector ZERO = new ByteMaxVector();
 
@@ -154,7 +154,7 @@
         return VectorIntrinsics.cast(
             ByteMaxVector.class,
             byte.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -172,37 +172,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -292,55 +292,50 @@
     @ForceInline
     public ByteVector reshape(Species<Byte> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Byte64Vector.Byte64Species)) {
-            Byte64Vector.Byte64Species ts = (Byte64Vector.Byte64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Byte64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 ByteMaxVector.class,
                 byte.class, LENGTH,
                 Byte64Vector.class,
                 byte.class, Byte64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Byte128Vector.Byte128Species)) {
-            Byte128Vector.Byte128Species ts = (Byte128Vector.Byte128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Byte128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 ByteMaxVector.class,
                 byte.class, LENGTH,
                 Byte128Vector.class,
                 byte.class, Byte128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Byte256Vector.Byte256Species)) {
-            Byte256Vector.Byte256Species ts = (Byte256Vector.Byte256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Byte256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 ByteMaxVector.class,
                 byte.class, LENGTH,
                 Byte256Vector.class,
                 byte.class, Byte256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Byte512Vector.Byte512Species)) {
-            Byte512Vector.Byte512Species ts = (Byte512Vector.Byte512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Byte512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 ByteMaxVector.class,
                 byte.class, LENGTH,
                 Byte512Vector.class,
                 byte.class, Byte512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof ByteMaxVector.ByteMaxSpecies)) {
-            ByteMaxVector.ByteMaxSpecies ts = (ByteMaxVector.ByteMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == ByteMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 ByteMaxVector.class,
                 byte.class, LENGTH,
                 ByteMaxVector.class,
                 byte.class, ByteMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (ByteVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -353,128 +348,128 @@
     @Override
     @ForceInline
     public ByteVector add(byte o) {
-        return add(SPECIES.broadcast(o));
+        return add((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector add(byte o, Mask<Byte> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((ByteMaxVector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector sub(byte o, Mask<Byte> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((ByteMaxVector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector mul(byte o, Mask<Byte> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((ByteMaxVector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector min(byte o) {
-        return min(SPECIES.broadcast(o));
+        return min((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector max(byte o) {
-        return max(SPECIES.broadcast(o));
+        return max((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> equal(byte o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> notEqual(byte o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThan(byte o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> lessThanEq(byte o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThan(byte o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Byte> greaterThanEq(byte o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector blend(byte o, Mask<Byte> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, o), m);
     }
 
 
     @Override
     @ForceInline
     public ByteVector and(byte o) {
-        return and(SPECIES.broadcast(o));
+        return and((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector and(byte o, Mask<Byte> m) {
-        return and(SPECIES.broadcast(o), m);
+        return and((ByteMaxVector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o) {
-        return or(SPECIES.broadcast(o));
+        return or((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector or(byte o, Mask<Byte> m) {
-        return or(SPECIES.broadcast(o), m);
+        return or((ByteMaxVector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o) {
-        return xor(SPECIES.broadcast(o));
+        return xor((ByteMaxVector)ByteVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public ByteVector xor(byte o, Mask<Byte> m) {
-        return xor(SPECIES.broadcast(o), m);
+        return xor((ByteMaxVector)ByteVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -729,7 +724,7 @@
     @Override
     @ForceInline
     public byte andAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) -1).blend(this, m).andAll();
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, (byte) -1), m).andAll();
     }
 
     @Override
@@ -771,7 +766,7 @@
     @Override
     @ForceInline
     public byte orAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).orAll();
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, (byte) 0), m).orAll();
     }
 
     @Override
@@ -786,33 +781,33 @@
     @Override
     @ForceInline
     public byte xorAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).xorAll();
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, (byte) 0), m).xorAll();
     }
 
 
     @Override
     @ForceInline
     public byte addAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 0).blend(this, m).addAll();
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, (byte) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public byte mulAll(Mask<Byte> m) {
-        return SPECIES.broadcast((byte) 1).blend(this, m).mulAll();
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, (byte) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public byte minAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MAX_VALUE).blend(this, m).minAll();
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, Byte.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public byte maxAll(Mask<Byte> m) {
-        return SPECIES.broadcast(Byte.MIN_VALUE).blend(this, m).maxAll();
+        return blend((ByteMaxVector)ByteVector.broadcast(SPECIES, Byte.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -1196,7 +1191,7 @@
         }
 
         @Override
-        public ByteMaxSpecies species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1212,6 +1207,31 @@
             return new ByteMaxVector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new ByteMaxVector.ByteMaxMask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new ShortMaxVector.ShortMaxMask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new IntMaxVector.IntMaxMask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new LongMaxVector.LongMaxMask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new FloatMaxVector.FloatMaxMask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new DoubleMaxVector.DoubleMaxMask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1284,7 +1304,7 @@
         }
 
         @Override
-        public ByteMaxSpecies species() {
+        public Species<Byte> species() {
             return SPECIES;
         }
 
@@ -1298,6 +1318,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new ByteMaxVector.ByteMaxShuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new ShortMaxVector.ShortMaxShuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new IntMaxVector.IntMaxShuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new LongMaxVector.LongMaxShuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new FloatMaxVector.FloatMaxShuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new DoubleMaxVector.DoubleMaxShuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public ByteMaxShuffle rearrange(Vector.Shuffle<Byte> o) {
             ByteMaxShuffle s = (ByteMaxShuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1311,148 +1356,7 @@
     // Species
 
     @Override
-    public ByteMaxSpecies species() {
+    public Species<Byte> species() {
         return SPECIES;
     }
-
-    static final class ByteMaxSpecies extends ByteSpecies {
-        static final int BIT_SIZE = Shape.S_Max_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Byte.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(byte.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Byte> elementType() {
-            return byte.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return ByteMaxVector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return ByteMaxMask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Byte.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return ByteMaxVector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_Max_BIT;
-        }
-
-        @Override
-        ByteMaxVector op(FOp f) {
-            byte[] res = new byte[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new ByteMaxVector(res);
-        }
-
-        @Override
-        ByteMaxVector op(Mask<Byte> o, FOp f) {
-            byte[] res = new byte[length()];
-            boolean[] mbits = ((ByteMaxMask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new ByteMaxVector(res);
-        }
-
-        @Override
-        ByteMaxMask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new ByteMaxMask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public ByteMaxVector zero() {
-            return VectorIntrinsics.broadcastCoerced(ByteMaxVector.class, byte.class, LENGTH,
-                                                     0, SPECIES,
-                                                     ((bits, s) -> ((ByteMaxSpecies)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public ByteMaxVector broadcast(byte e) {
-            return VectorIntrinsics.broadcastCoerced(
-                ByteMaxVector.class, byte.class, LENGTH,
-                e, SPECIES,
-                ((bits, s) -> ((ByteMaxSpecies)s).op(i -> (byte)bits)));
-        }
-
-        @Override
-        @ForceInline
-        public ByteMaxVector scalars(byte... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(ByteMaxVector.class, byte.class, LENGTH,
-                                         es, Unsafe.ARRAY_BYTE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((ByteMaxSpecies)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> ByteMaxMask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new ByteMaxMask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> ByteMaxShuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new ByteMaxShuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -28,6 +28,7 @@
 import java.nio.ByteOrder;
 import java.util.Objects;
 import java.util.function.IntUnaryOperator;
+import java.util.function.Function;
 import java.util.concurrent.ThreadLocalRandom;
 
 import jdk.internal.misc.Unsafe;
@@ -109,8 +110,10 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static ByteVector zero(ByteSpecies species) {
-        return species.zero();
+    public static ByteVector zero(Species<Byte> species) {
+        return VectorIntrinsics.broadcastCoerced((Class<ByteVector>) species.boxType(), byte.class, species.length(),
+                                                 0, species,
+                                                 ((bits, s) -> ((ByteSpecies)s).op(i -> (byte)bits)));
     }
 
     /**
@@ -121,7 +124,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(ByteSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Byte>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
      * }</pre>
@@ -135,7 +138,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static ByteVector fromByteArray(ByteSpecies species, byte[] a, int ix) {
+    public static ByteVector fromByteArray(Species<Byte> species, byte[] a, int ix) {
         Objects.requireNonNull(a);
         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
         return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(),
@@ -157,7 +160,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(ByteSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Byte>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
      * }</pre>
@@ -176,7 +179,7 @@
      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
-    public static ByteVector fromByteArray(ByteSpecies species, byte[] a, int ix, Mask<Byte> m) {
+    public static ByteVector fromByteArray(Species<Byte> species, byte[] a, int ix, Mask<Byte> m) {
         return zero(species).blend(fromByteArray(species, a, ix), m);
     }
 
@@ -196,7 +199,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static ByteVector fromArray(ByteSpecies species, byte[] a, int i){
+    public static ByteVector fromArray(Species<Byte> species, byte[] a, int i){
         Objects.requireNonNull(a);
         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
         return VectorIntrinsics.load((Class<ByteVector>) species.boxType(), byte.class, species.length(),
@@ -225,7 +228,7 @@
      * is set {@code i > a.length - N}
      */
     @ForceInline
-    public static ByteVector fromArray(ByteSpecies species, byte[] a, int i, Mask<Byte> m) {
+    public static ByteVector fromArray(Species<Byte> species, byte[] a, int i, Mask<Byte> m) {
         return zero(species).blend(fromArray(species, a, i), m);
     }
 
@@ -250,8 +253,8 @@
      * or for any vector lane index {@code N} the result of
      * {@code i + indexMap[j + N]} is {@code < 0} or {@code >= a.length}
      */
-    public static ByteVector fromArray(ByteSpecies species, byte[] a, int i, int[] indexMap, int j) {
-        return species.op(n -> a[i + indexMap[j + n]]);
+    public static ByteVector fromArray(Species<Byte> species, byte[] a, int i, int[] indexMap, int j) {
+        return ((ByteSpecies)species).op(n -> a[i + indexMap[j + n]]);
     }
     /**
      * Loads a vector from an array using indexes obtained from an index
@@ -277,8 +280,8 @@
      * {@code N} is set the result of {@code i + indexMap[j + N]} is
      * {@code < 0} or {@code >= a.length}
      */
-    public static ByteVector fromArray(ByteSpecies species, byte[] a, int i, Mask<Byte> m, int[] indexMap, int j) {
-        return species.op(m, n -> a[i + indexMap[j + n]]);
+    public static ByteVector fromArray(Species<Byte> species, byte[] a, int i, Mask<Byte> m, int[] indexMap, int j) {
+        return ((ByteSpecies)species).op(m, n -> a[i + indexMap[j + n]]);
     }
 
     /**
@@ -290,7 +293,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(ByteSpecies, ByteBuffer, int, Mask)} method} as follows:
+     * {@link #fromByteBuffer(Species<Byte>, ByteBuffer, int, Mask)} method} as follows:
      * <pre>{@code
      *   return this.fromByteBuffer(b, i, this.maskAllTrue())
      * }</pre>
@@ -307,7 +310,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static ByteVector fromByteBuffer(ByteSpecies species, ByteBuffer bb, int ix) {
+    public static ByteVector fromByteBuffer(Species<Byte> species, ByteBuffer bb, int ix) {
         if (bb.order() != ByteOrder.nativeOrder()) {
             throw new IllegalArgumentException();
         }
@@ -359,11 +362,85 @@
      * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
-    public static ByteVector fromByteBuffer(ByteSpecies species, ByteBuffer bb, int ix, Mask<Byte> m) {
+    public static ByteVector fromByteBuffer(Species<Byte> species, ByteBuffer bb, int ix, Mask<Byte> m) {
         return zero(species).blend(fromByteBuffer(species, bb, ix), m);
     }
 
     /**
+     * Returns a vector where all lane elements are set to the primitive
+     * value {@code e}.
+     *
+     * @param s species of the desired vector
+     * @param e the value
+     * @return a vector of vector where all lane elements are set to
+     * the primitive value {@code e}
+     */
+    @ForceInline
+    @SuppressWarnings("unchecked")
+    public static ByteVector broadcast(Species<Byte> s, byte e) {
+        return VectorIntrinsics.broadcastCoerced(
+            (Class<ByteVector>) s.boxType(), byte.class, s.length(),
+            e, s,
+            ((bits, sp) -> ((ByteSpecies)sp).op(i -> (byte)bits)));
+    }
+
+    /**
+     * Returns a vector where each lane element is set to a given
+     * primitive value.
+     * <p>
+     * For each vector lane, where {@code N} is the vector lane index, the
+     * the primitive value at index {@code N} is placed into the resulting
+     * vector at lane index {@code N}.
+     *
+     * @param s species of the desired vector
+     * @param es the given primitive values
+     * @return a vector where each lane element is set to a given primitive
+     * value
+     * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
+     */
+    @ForceInline
+    @SuppressWarnings("unchecked")
+    public static ByteVector scalars(Species<Byte> s, byte... es) {
+        Objects.requireNonNull(es);
+        int ix = VectorIntrinsics.checkIndex(0, es.length, s.length());
+        return VectorIntrinsics.load((Class<ByteVector>) s.boxType(), byte.class, s.length(),
+                                     es, Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                                     es, ix, s,
+                                     (c, idx, sp) -> ((ByteSpecies)sp).op(n -> c[idx + n]));
+    }
+
+    /**
+     * Returns a vector where the first lane element is set to the primtive
+     * value {@code e}, all other lane elements are set to the default
+     * value.
+     *
+     * @param s species of the desired vector
+     * @param e the value
+     * @return a vector where the first lane element is set to the primitive
+     * value {@code e}
+     */
+    @ForceInline
+    public static final ByteVector single(Species<Byte> s, byte e) {
+        return zero(s).with(0, e);
+    }
+
+    /**
+     * Returns a vector where each lane element is set to a randomly
+     * generated primitive value.
+     *
+     * The semantics are equivalent to calling
+     * (byte){@link ThreadLocalRandom#nextInt()}
+     *
+     * @param s species of the desired vector
+     * @return a vector where each lane elements is set to a randomly
+     * generated primitive value
+     */
+    public static ByteVector random(Species<Byte> s) {
+        ThreadLocalRandom r = ThreadLocalRandom.current();
+        return ((ByteSpecies)s).op(i -> (byte) r.nextInt());
+    }
+
+    /**
      * Returns a mask where each lane is set or unset according to given
      * {@code boolean} values
      * <p>
@@ -377,7 +454,7 @@
      * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
      */
     @ForceInline
-    public static Mask<Byte> maskFromValues(ByteSpecies species, boolean... bits) {
+    public static Mask<Byte> maskFromValues(Species<Byte> species, boolean... bits) {
         if (species.boxType() == ByteMaxVector.class)
             return new ByteMaxVector.ByteMaxMask(bits);
         switch (species.bitSize()) {
@@ -390,7 +467,7 @@
     }
 
     // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
-    static Mask<Byte> trueMask(ByteSpecies species) {
+    static Mask<Byte> trueMask(Species<Byte> species) {
         if (species.boxType() == ByteMaxVector.class)
             return ByteMaxVector.ByteMaxMask.TRUE_MASK;
         switch (species.bitSize()) {
@@ -402,7 +479,7 @@
         }
     }
 
-    static Mask<Byte> falseMask(ByteSpecies species) {
+    static Mask<Byte> falseMask(Species<Byte> species) {
         if (species.boxType() == ByteMaxVector.class)
             return ByteMaxVector.ByteMaxMask.FALSE_MASK;
         switch (species.bitSize()) {
@@ -430,7 +507,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Byte> maskFromArray(ByteSpecies species, boolean[] bits, int ix) {
+    public static Mask<Byte> maskFromArray(Species<Byte> species, boolean[] bits, int ix) {
         Objects.requireNonNull(bits);
         ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
         return VectorIntrinsics.load((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(),
@@ -447,10 +524,10 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Byte> maskAllTrue(ByteSpecies species) {
+    public static Mask<Byte> maskAllTrue(Species<Byte> species) {
         return VectorIntrinsics.broadcastCoerced((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(),
                                                  (byte)-1,  species,
-                                                 ((z, s) -> trueMask((ByteSpecies)s)));
+                                                 ((z, s) -> trueMask(s)));
     }
 
     /**
@@ -461,10 +538,10 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Byte> maskAllFalse(ByteSpecies species) {
+    public static Mask<Byte> maskAllFalse(Species<Byte> species) {
         return VectorIntrinsics.broadcastCoerced((Class<Mask<Byte>>) species.maskType(), byte.class, species.length(),
                                                  0, species, 
-                                                 ((z, s) -> falseMask((ByteSpecies)s)));
+                                                 ((z, s) -> falseMask(s)));
     }
 
     /**
@@ -492,7 +569,7 @@
      * @return a shuffle of mapped indexes
      */
     @ForceInline
-    public static Shuffle<Byte> shuffle(ByteSpecies species, IntUnaryOperator f) {
+    public static Shuffle<Byte> shuffle(Species<Byte> species, IntUnaryOperator f) {
         if (species.boxType() == ByteMaxVector.class)
             return new ByteMaxVector.ByteMaxShuffle(f);
         switch (species.bitSize()) {
@@ -518,7 +595,7 @@
      * @return a shuffle of lane indexes
      */
     @ForceInline
-    public static Shuffle<Byte> shuffleIota(ByteSpecies species) {
+    public static Shuffle<Byte> shuffleIota(Species<Byte> species) {
         if (species.boxType() == ByteMaxVector.class)
             return new ByteMaxVector.ByteMaxShuffle(AbstractShuffle.IDENTITY);
         switch (species.bitSize()) {
@@ -547,7 +624,7 @@
      * {@code < species.length()}
      */
     @ForceInline
-    public static Shuffle<Byte> shuffleFromValues(ByteSpecies species, int... ixs) {
+    public static Shuffle<Byte> shuffleFromValues(Species<Byte> species, int... ixs) {
         if (species.boxType() == ByteMaxVector.class)
             return new ByteMaxVector.ByteMaxShuffle(ixs);
         switch (species.bitSize()) {
@@ -575,7 +652,7 @@
      * {@code i > a.length - species.length()}
      */
     @ForceInline
-    public static Shuffle<Byte> shuffleFromArray(ByteSpecies species, int[] ixs, int i) {
+    public static Shuffle<Byte> shuffleFromArray(Species<Byte> species, int[] ixs, int i) {
         if (species.boxType() == ByteMaxVector.class)
             return new ByteMaxVector.ByteMaxShuffle(ixs, i);
         switch (species.bitSize()) {
@@ -587,7 +664,6 @@
         }
     }
 
-
     // Ops
 
     @Override
@@ -1468,86 +1544,59 @@
     // Species
 
     @Override
-    public abstract ByteSpecies species();
+    public abstract Species<Byte> species();
 
     /**
      * Class representing {@link ByteVector}'s of the same {@link Vector.Shape Shape}.
      */
-    public static abstract class ByteSpecies extends Vector.Species<Byte> {
+    static final class ByteSpecies extends Vector.AbstractSpecies<Byte> {
+        final Function<byte[], ByteVector> vectorFactory;
+        final Function<boolean[], Vector.Mask<Byte>> maskFactory;
+
+        private ByteSpecies(Vector.Shape shape,
+                          Class<?> boxType,
+                          Class<?> maskType,
+                          Function<byte[], ByteVector> vectorFactory,
+                          Function<boolean[], Vector.Mask<Byte>> maskFactory) {
+            super(shape, byte.class, Byte.SIZE, boxType, maskType);
+            this.vectorFactory = vectorFactory;
+            this.maskFactory = maskFactory;
+        }
+
         interface FOp {
             byte apply(int i);
         }
 
-        abstract ByteVector op(FOp f);
-
-        abstract ByteVector op(Mask<Byte> m, FOp f);
-
         interface FOpm {
             boolean apply(int i);
         }
 
-        abstract Mask<Byte> opm(FOpm f);
-
-
-
-        // Factories
-
-        @Override
-        public abstract ByteVector zero();
-
-        /**
-         * Returns a vector where all lane elements are set to the primitive
-         * value {@code e}.
-         *
-         * @param e the value
-         * @return a vector of vector where all lane elements are set to
-         * the primitive value {@code e}
-         */
-        public abstract ByteVector broadcast(byte e);
-
-        /**
-         * Returns a vector where the first lane element is set to the primtive
-         * value {@code e}, all other lane elements are set to the default
-         * value.
-         *
-         * @param e the value
-         * @return a vector where the first lane element is set to the primitive
-         * value {@code e}
-         */
-        @ForceInline
-        public final ByteVector single(byte e) {
-            return zero().with(0, e);
+        ByteVector op(FOp f) {
+            byte[] res = new byte[length()];
+            for (int i = 0; i < length(); i++) {
+                res[i] = f.apply(i);
+            }
+            return vectorFactory.apply(res);
         }
 
-        /**
-         * Returns a vector where each lane element is set to a randomly
-         * generated primitive value.
-         *
-         * The semantics are equivalent to calling
-         * {@code (byte)ThreadLocalRandom#nextInt()}.
-         *
-         * @return a vector where each lane elements is set to a randomly
-         * generated primitive value
-         */
-        public ByteVector random() {
-            ThreadLocalRandom r = ThreadLocalRandom.current();
-            return op(i -> (byte) r.nextInt());
+        ByteVector op(Vector.Mask<Byte> o, FOp f) {
+            byte[] res = new byte[length()];
+            boolean[] mbits = ((AbstractMask<Byte>)o).getBits();
+            for (int i = 0; i < length(); i++) {
+                if (mbits[i]) {
+                    res[i] = f.apply(i);
+                }
+            }
+            return vectorFactory.apply(res);
         }
 
-        /**
-         * Returns a vector where each lane element is set to a given
-         * primitive value.
-         * <p>
-         * For each vector lane, where {@code N} is the vector lane index, the
-         * the primitive value at index {@code N} is placed into the resulting
-         * vector at lane index {@code N}.
-         *
-         * @param es the given primitive values
-         * @return a vector where each lane element is set to a given primitive
-         * value
-         * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
-         */
-        public abstract ByteVector scalars(byte... es);
+        Vector.Mask<Byte> opm(IntVector.IntSpecies.FOpm f) {
+            boolean[] res = new boolean[length()];
+            for (int i = 0; i < length(); i++) {
+                res[i] = (boolean)f.apply(i);
+            }
+            return maskFactory.apply(res);
+        }
     }
 
     /**
@@ -1560,8 +1609,7 @@
      *
      * @return the preferred species for an element type of {@code byte}
      */
-    @SuppressWarnings("unchecked")
-    public static ByteSpecies preferredSpecies() {
+    private static ByteSpecies preferredSpecies() {
         return (ByteSpecies) Species.ofPreferred(byte.class);
     }
 
@@ -1572,16 +1620,41 @@
      * @return a species for an element type of {@code byte} and shape
      * @throws IllegalArgumentException if no such species exists for the shape
      */
-    @SuppressWarnings("unchecked")
-    public static ByteSpecies species(Vector.Shape s) {
+    static ByteSpecies species(Vector.Shape s) {
         Objects.requireNonNull(s);
         switch (s) {
-            case S_64_BIT: return Byte64Vector.SPECIES;
-            case S_128_BIT: return Byte128Vector.SPECIES;
-            case S_256_BIT: return Byte256Vector.SPECIES;
-            case S_512_BIT: return Byte512Vector.SPECIES;
-            case S_Max_BIT: return ByteMaxVector.SPECIES;
+            case S_64_BIT: return (ByteSpecies) SPECIES_64;
+            case S_128_BIT: return (ByteSpecies) SPECIES_128;
+            case S_256_BIT: return (ByteSpecies) SPECIES_256;
+            case S_512_BIT: return (ByteSpecies) SPECIES_512;
+            case S_Max_BIT: return (ByteSpecies) SPECIES_MAX;
             default: throw new IllegalArgumentException("Bad shape: " + s);
         }
     }
+
+    /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_64_BIT Shape.S_64_BIT}. */
+    public static final Species<Byte> SPECIES_64 = new ByteSpecies(Shape.S_64_BIT, Byte64Vector.class, Byte64Vector.Byte64Mask.class,
+                                                                     Byte64Vector::new, Byte64Vector.Byte64Mask::new);
+
+    /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_128_BIT Shape.S_128_BIT}. */
+    public static final Species<Byte> SPECIES_128 = new ByteSpecies(Shape.S_128_BIT, Byte128Vector.class, Byte128Vector.Byte128Mask.class,
+                                                                      Byte128Vector::new, Byte128Vector.Byte128Mask::new);
+
+    /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_256_BIT Shape.S_256_BIT}. */
+    public static final Species<Byte> SPECIES_256 = new ByteSpecies(Shape.S_256_BIT, Byte256Vector.class, Byte256Vector.Byte256Mask.class,
+                                                                      Byte256Vector::new, Byte256Vector.Byte256Mask::new);
+
+    /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_512_BIT Shape.S_512_BIT}. */
+    public static final Species<Byte> SPECIES_512 = new ByteSpecies(Shape.S_512_BIT, Byte512Vector.class, Byte512Vector.Byte512Mask.class,
+                                                                      Byte512Vector::new, Byte512Vector.Byte512Mask::new);
+
+    /** Species representing {@link ByteVector}s of {@link Vector.Shape#S_Max_BIT Shape.S_Max_BIT}. */
+    public static final Species<Byte> SPECIES_MAX = new ByteSpecies(Shape.S_Max_BIT, ByteMaxVector.class, ByteMaxVector.ByteMaxMask.class,
+                                                                      ByteMaxVector::new, ByteMaxVector.ByteMaxMask::new);
+
+    /**
+     * Preferred species for {@link ByteVector}s.
+     * A preferred species is a species of maximal bit size for the platform.
+     */
+    public static final Species<Byte> SPECIES_PREFERRED = (Species<Byte>) preferredSpecies();
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class Double128Vector extends DoubleVector {
-    static final Double128Species SPECIES = new Double128Species();
+    private static final Species<Double> SPECIES = DoubleVector.SPECIES_128;
 
     static final Double128Vector ZERO = new Double128Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final double[] vec; // Don't access directly, use getElements() instead.
 
     private double[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             Double128Vector.class,
             double.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public DoubleVector reshape(Species<Double> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Double64Vector.Double64Species)) {
-            Double64Vector.Double64Species ts = (Double64Vector.Double64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Double64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double128Vector.class,
                 double.class, LENGTH,
                 Double64Vector.class,
                 double.class, Double64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Double128Vector.Double128Species)) {
-            Double128Vector.Double128Species ts = (Double128Vector.Double128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Double128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double128Vector.class,
                 double.class, LENGTH,
                 Double128Vector.class,
                 double.class, Double128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Double256Vector.Double256Species)) {
-            Double256Vector.Double256Species ts = (Double256Vector.Double256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Double256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double128Vector.class,
                 double.class, LENGTH,
                 Double256Vector.class,
                 double.class, Double256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Double512Vector.Double512Species)) {
-            Double512Vector.Double512Species ts = (Double512Vector.Double512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Double512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double128Vector.class,
                 double.class, LENGTH,
                 Double512Vector.class,
                 double.class, Double512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof DoubleMaxVector.DoubleMaxSpecies)) {
-            DoubleMaxVector.DoubleMaxSpecies ts = (DoubleMaxVector.DoubleMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == DoubleMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double128Vector.class,
                 double.class, LENGTH,
                 DoubleMaxVector.class,
                 double.class, DoubleMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public DoubleVector add(double o) {
-        return add(SPECIES.broadcast(o));
+        return add((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector add(double o, Mask<Double> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o, Mask<Double> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o, Mask<Double> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector min(double o) {
-        return min(SPECIES.broadcast(o));
+        return min((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector max(double o) {
-        return max(SPECIES.broadcast(o));
+        return max((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> equal(double o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> notEqual(double o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThan(double o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThanEq(double o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThan(double o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThanEq(double o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector blend(double o, Mask<Double> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o) {
-        return div(SPECIES.broadcast(o));
+        return div((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o, Mask<Double> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public DoubleVector atan2(double o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector atan2(double o, Mask<Double> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o, Mask<Double> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Double128Vector)DoubleVector.broadcast(SPECIES, o1), (Double128Vector)DoubleVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2, Mask<Double> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Double128Vector)DoubleVector.broadcast(SPECIES, o1), (Double128Vector)DoubleVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Double128Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o, Mask<Double> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Double128Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public double addAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 0).blend(this, m).addAll();
+        return blend((Double128Vector)DoubleVector.broadcast(SPECIES, (double) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public double mulAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 1).blend(this, m).mulAll();
+        return blend((Double128Vector)DoubleVector.broadcast(SPECIES, (double) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public double minAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MAX_VALUE).blend(this, m).minAll();
+        return blend((Double128Vector)DoubleVector.broadcast(SPECIES, Double.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public double maxAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Double128Vector)DoubleVector.broadcast(SPECIES, Double.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public Double128Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new Double128Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte128Vector.Byte128Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short128Vector.Short128Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int128Vector.Int128Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long128Vector.Long128Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float128Vector.Float128Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double128Vector.Double128Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public Double128Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte128Vector.Byte128Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short128Vector.Short128Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int128Vector.Int128Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long128Vector.Long128Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float128Vector.Float128Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double128Vector.Double128Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Double128Shuffle rearrange(Vector.Shuffle<Double> o) {
             Double128Shuffle s = (Double128Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public Double128Species species() {
+    public Species<Double> species() {
         return SPECIES;
     }
-
-    static final class Double128Species extends DoubleSpecies {
-        static final int BIT_SIZE = Shape.S_128_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Double.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(double.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Double> elementType() {
-            return double.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Double128Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Double128Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Double.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Double128Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_128_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Double128Vector op(FOp f) {
-            double[] res = new double[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Double128Vector(res);
-        }
-
-        @Override
-        Double128Vector op(Mask<Double> o, FOp f) {
-            double[] res = new double[length()];
-            boolean[] mbits = ((Double128Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Double128Vector(res);
-        }
-
-        @Override
-        Double128Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Double128Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Double128Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Double128Vector.class, double.class, LENGTH,
-                                                     Double.doubleToLongBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Double128Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double128Vector broadcast(double e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Double128Vector.class, double.class, LENGTH,
-                Double.doubleToLongBits(e), SPECIES,
-                ((bits, s) -> ((Double128Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double128Vector scalars(double... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Double128Vector.class, double.class, LENGTH,
-                                         es, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Double128Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double128Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Double128Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double128Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Double128Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class Double256Vector extends DoubleVector {
-    static final Double256Species SPECIES = new Double256Species();
+    private static final Species<Double> SPECIES = DoubleVector.SPECIES_256;
 
     static final Double256Vector ZERO = new Double256Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final double[] vec; // Don't access directly, use getElements() instead.
 
     private double[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             Double256Vector.class,
             double.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public DoubleVector reshape(Species<Double> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Double64Vector.Double64Species)) {
-            Double64Vector.Double64Species ts = (Double64Vector.Double64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Double64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double256Vector.class,
                 double.class, LENGTH,
                 Double64Vector.class,
                 double.class, Double64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Double128Vector.Double128Species)) {
-            Double128Vector.Double128Species ts = (Double128Vector.Double128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Double128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double256Vector.class,
                 double.class, LENGTH,
                 Double128Vector.class,
                 double.class, Double128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Double256Vector.Double256Species)) {
-            Double256Vector.Double256Species ts = (Double256Vector.Double256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Double256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double256Vector.class,
                 double.class, LENGTH,
                 Double256Vector.class,
                 double.class, Double256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Double512Vector.Double512Species)) {
-            Double512Vector.Double512Species ts = (Double512Vector.Double512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Double512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double256Vector.class,
                 double.class, LENGTH,
                 Double512Vector.class,
                 double.class, Double512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof DoubleMaxVector.DoubleMaxSpecies)) {
-            DoubleMaxVector.DoubleMaxSpecies ts = (DoubleMaxVector.DoubleMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == DoubleMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double256Vector.class,
                 double.class, LENGTH,
                 DoubleMaxVector.class,
                 double.class, DoubleMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public DoubleVector add(double o) {
-        return add(SPECIES.broadcast(o));
+        return add((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector add(double o, Mask<Double> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o, Mask<Double> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o, Mask<Double> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector min(double o) {
-        return min(SPECIES.broadcast(o));
+        return min((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector max(double o) {
-        return max(SPECIES.broadcast(o));
+        return max((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> equal(double o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> notEqual(double o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThan(double o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThanEq(double o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThan(double o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThanEq(double o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector blend(double o, Mask<Double> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o) {
-        return div(SPECIES.broadcast(o));
+        return div((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o, Mask<Double> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public DoubleVector atan2(double o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector atan2(double o, Mask<Double> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o, Mask<Double> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Double256Vector)DoubleVector.broadcast(SPECIES, o1), (Double256Vector)DoubleVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2, Mask<Double> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Double256Vector)DoubleVector.broadcast(SPECIES, o1), (Double256Vector)DoubleVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Double256Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o, Mask<Double> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Double256Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public double addAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 0).blend(this, m).addAll();
+        return blend((Double256Vector)DoubleVector.broadcast(SPECIES, (double) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public double mulAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 1).blend(this, m).mulAll();
+        return blend((Double256Vector)DoubleVector.broadcast(SPECIES, (double) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public double minAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MAX_VALUE).blend(this, m).minAll();
+        return blend((Double256Vector)DoubleVector.broadcast(SPECIES, Double.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public double maxAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Double256Vector)DoubleVector.broadcast(SPECIES, Double.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public Double256Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new Double256Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte256Vector.Byte256Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short256Vector.Short256Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int256Vector.Int256Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long256Vector.Long256Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float256Vector.Float256Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double256Vector.Double256Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public Double256Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte256Vector.Byte256Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short256Vector.Short256Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int256Vector.Int256Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long256Vector.Long256Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float256Vector.Float256Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double256Vector.Double256Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Double256Shuffle rearrange(Vector.Shuffle<Double> o) {
             Double256Shuffle s = (Double256Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public Double256Species species() {
+    public Species<Double> species() {
         return SPECIES;
     }
-
-    static final class Double256Species extends DoubleSpecies {
-        static final int BIT_SIZE = Shape.S_256_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Double.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(double.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Double> elementType() {
-            return double.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Double256Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Double256Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Double.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Double256Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_256_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Double256Vector op(FOp f) {
-            double[] res = new double[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Double256Vector(res);
-        }
-
-        @Override
-        Double256Vector op(Mask<Double> o, FOp f) {
-            double[] res = new double[length()];
-            boolean[] mbits = ((Double256Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Double256Vector(res);
-        }
-
-        @Override
-        Double256Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Double256Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Double256Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Double256Vector.class, double.class, LENGTH,
-                                                     Double.doubleToLongBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Double256Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double256Vector broadcast(double e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Double256Vector.class, double.class, LENGTH,
-                Double.doubleToLongBits(e), SPECIES,
-                ((bits, s) -> ((Double256Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double256Vector scalars(double... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Double256Vector.class, double.class, LENGTH,
-                                         es, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Double256Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double256Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Double256Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double256Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Double256Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class Double512Vector extends DoubleVector {
-    static final Double512Species SPECIES = new Double512Species();
+    private static final Species<Double> SPECIES = DoubleVector.SPECIES_512;
 
     static final Double512Vector ZERO = new Double512Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final double[] vec; // Don't access directly, use getElements() instead.
 
     private double[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             Double512Vector.class,
             double.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public DoubleVector reshape(Species<Double> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Double64Vector.Double64Species)) {
-            Double64Vector.Double64Species ts = (Double64Vector.Double64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Double64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double512Vector.class,
                 double.class, LENGTH,
                 Double64Vector.class,
                 double.class, Double64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Double128Vector.Double128Species)) {
-            Double128Vector.Double128Species ts = (Double128Vector.Double128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Double128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double512Vector.class,
                 double.class, LENGTH,
                 Double128Vector.class,
                 double.class, Double128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Double256Vector.Double256Species)) {
-            Double256Vector.Double256Species ts = (Double256Vector.Double256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Double256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double512Vector.class,
                 double.class, LENGTH,
                 Double256Vector.class,
                 double.class, Double256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Double512Vector.Double512Species)) {
-            Double512Vector.Double512Species ts = (Double512Vector.Double512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Double512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double512Vector.class,
                 double.class, LENGTH,
                 Double512Vector.class,
                 double.class, Double512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof DoubleMaxVector.DoubleMaxSpecies)) {
-            DoubleMaxVector.DoubleMaxSpecies ts = (DoubleMaxVector.DoubleMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == DoubleMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double512Vector.class,
                 double.class, LENGTH,
                 DoubleMaxVector.class,
                 double.class, DoubleMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public DoubleVector add(double o) {
-        return add(SPECIES.broadcast(o));
+        return add((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector add(double o, Mask<Double> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o, Mask<Double> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o, Mask<Double> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector min(double o) {
-        return min(SPECIES.broadcast(o));
+        return min((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector max(double o) {
-        return max(SPECIES.broadcast(o));
+        return max((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> equal(double o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> notEqual(double o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThan(double o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThanEq(double o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThan(double o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThanEq(double o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector blend(double o, Mask<Double> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o) {
-        return div(SPECIES.broadcast(o));
+        return div((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o, Mask<Double> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public DoubleVector atan2(double o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector atan2(double o, Mask<Double> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o, Mask<Double> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Double512Vector)DoubleVector.broadcast(SPECIES, o1), (Double512Vector)DoubleVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2, Mask<Double> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Double512Vector)DoubleVector.broadcast(SPECIES, o1), (Double512Vector)DoubleVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Double512Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o, Mask<Double> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Double512Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public double addAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 0).blend(this, m).addAll();
+        return blend((Double512Vector)DoubleVector.broadcast(SPECIES, (double) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public double mulAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 1).blend(this, m).mulAll();
+        return blend((Double512Vector)DoubleVector.broadcast(SPECIES, (double) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public double minAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MAX_VALUE).blend(this, m).minAll();
+        return blend((Double512Vector)DoubleVector.broadcast(SPECIES, Double.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public double maxAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Double512Vector)DoubleVector.broadcast(SPECIES, Double.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public Double512Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new Double512Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte512Vector.Byte512Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short512Vector.Short512Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int512Vector.Int512Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long512Vector.Long512Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float512Vector.Float512Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double512Vector.Double512Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public Double512Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte512Vector.Byte512Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short512Vector.Short512Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int512Vector.Int512Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long512Vector.Long512Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float512Vector.Float512Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double512Vector.Double512Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Double512Shuffle rearrange(Vector.Shuffle<Double> o) {
             Double512Shuffle s = (Double512Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public Double512Species species() {
+    public Species<Double> species() {
         return SPECIES;
     }
-
-    static final class Double512Species extends DoubleSpecies {
-        static final int BIT_SIZE = Shape.S_512_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Double.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(double.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Double> elementType() {
-            return double.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Double512Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Double512Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Double.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Double512Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_512_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Double512Vector op(FOp f) {
-            double[] res = new double[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Double512Vector(res);
-        }
-
-        @Override
-        Double512Vector op(Mask<Double> o, FOp f) {
-            double[] res = new double[length()];
-            boolean[] mbits = ((Double512Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Double512Vector(res);
-        }
-
-        @Override
-        Double512Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Double512Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Double512Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Double512Vector.class, double.class, LENGTH,
-                                                     Double.doubleToLongBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Double512Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double512Vector broadcast(double e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Double512Vector.class, double.class, LENGTH,
-                Double.doubleToLongBits(e), SPECIES,
-                ((bits, s) -> ((Double512Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double512Vector scalars(double... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Double512Vector.class, double.class, LENGTH,
-                                         es, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Double512Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double512Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Double512Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double512Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Double512Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,17 +38,19 @@
 
 @SuppressWarnings("cast")
 final class Double64Vector extends DoubleVector {
-    static final Double64Species SPECIES = new Double64Species();
+    private static final Species<Double> SPECIES = DoubleVector.SPECIES_64;
 
     static final Double64Vector ZERO = new Double64Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, Shape.S_64_BIT);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.S_64_BIT);
     }
+
     private final double[] vec; // Don't access directly, use getElements() instead.
 
     private double[] getElements() {
@@ -160,7 +162,7 @@
         return VectorIntrinsics.cast(
             Double64Vector.class,
             double.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -178,37 +180,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -298,55 +300,50 @@
     @ForceInline
     public DoubleVector reshape(Species<Double> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Double64Vector.Double64Species)) {
-            Double64Vector.Double64Species ts = (Double64Vector.Double64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Double64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double64Vector.class,
                 double.class, LENGTH,
                 Double64Vector.class,
                 double.class, Double64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Double128Vector.Double128Species)) {
-            Double128Vector.Double128Species ts = (Double128Vector.Double128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Double128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double64Vector.class,
                 double.class, LENGTH,
                 Double128Vector.class,
                 double.class, Double128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Double256Vector.Double256Species)) {
-            Double256Vector.Double256Species ts = (Double256Vector.Double256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Double256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double64Vector.class,
                 double.class, LENGTH,
                 Double256Vector.class,
                 double.class, Double256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Double512Vector.Double512Species)) {
-            Double512Vector.Double512Species ts = (Double512Vector.Double512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Double512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double64Vector.class,
                 double.class, LENGTH,
                 Double512Vector.class,
                 double.class, Double512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof DoubleMaxVector.DoubleMaxSpecies)) {
-            DoubleMaxVector.DoubleMaxSpecies ts = (DoubleMaxVector.DoubleMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == DoubleMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Double64Vector.class,
                 double.class, LENGTH,
                 DoubleMaxVector.class,
                 double.class, DoubleMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -359,103 +356,103 @@
     @Override
     @ForceInline
     public DoubleVector add(double o) {
-        return add(SPECIES.broadcast(o));
+        return add((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector add(double o, Mask<Double> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o, Mask<Double> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o, Mask<Double> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector min(double o) {
-        return min(SPECIES.broadcast(o));
+        return min((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector max(double o) {
-        return max(SPECIES.broadcast(o));
+        return max((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> equal(double o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> notEqual(double o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThan(double o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThanEq(double o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThan(double o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThanEq(double o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector blend(double o, Mask<Double> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o) {
-        return div(SPECIES.broadcast(o));
+        return div((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o, Mask<Double> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -467,49 +464,49 @@
     @Override
     @ForceInline
     public DoubleVector atan2(double o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector atan2(double o, Mask<Double> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o, Mask<Double> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Double64Vector)DoubleVector.broadcast(SPECIES, o1), (Double64Vector)DoubleVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2, Mask<Double> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Double64Vector)DoubleVector.broadcast(SPECIES, o1), (Double64Vector)DoubleVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Double64Vector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o, Mask<Double> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Double64Vector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -895,26 +892,26 @@
     @Override
     @ForceInline
     public double addAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 0).blend(this, m).addAll();
+        return blend((Double64Vector)DoubleVector.broadcast(SPECIES, (double) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public double mulAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 1).blend(this, m).mulAll();
+        return blend((Double64Vector)DoubleVector.broadcast(SPECIES, (double) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public double minAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MAX_VALUE).blend(this, m).minAll();
+        return blend((Double64Vector)DoubleVector.broadcast(SPECIES, Double.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public double maxAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Double64Vector)DoubleVector.broadcast(SPECIES, Double.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -1321,7 +1318,7 @@
         }
 
         @Override
-        public Double64Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1337,6 +1334,31 @@
             return new Double64Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte64Vector.Byte64Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short64Vector.Short64Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int64Vector.Int64Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long64Vector.Long64Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float64Vector.Float64Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double64Vector.Double64Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1409,7 +1431,7 @@
         }
 
         @Override
-        public Double64Species species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1423,6 +1445,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte64Vector.Byte64Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short64Vector.Short64Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int64Vector.Int64Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long64Vector.Long64Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float64Vector.Float64Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double64Vector.Double64Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Double64Shuffle rearrange(Vector.Shuffle<Double> o) {
             Double64Shuffle s = (Double64Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1436,153 +1483,7 @@
     // Species
 
     @Override
-    public Double64Species species() {
+    public Species<Double> species() {
         return SPECIES;
     }
-
-    static final class Double64Species extends DoubleSpecies {
-        static final int BIT_SIZE = Shape.S_64_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Double.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(double.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Double> elementType() {
-            return double.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Double64Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Double64Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Double.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Double64Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_64_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Double64Vector op(FOp f) {
-            double[] res = new double[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Double64Vector(res);
-        }
-
-        @Override
-        Double64Vector op(Mask<Double> o, FOp f) {
-            double[] res = new double[length()];
-            boolean[] mbits = ((Double64Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Double64Vector(res);
-        }
-
-        @Override
-        Double64Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Double64Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Double64Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Double64Vector.class, double.class, LENGTH,
-                                                     Double.doubleToLongBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Double64Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double64Vector broadcast(double e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Double64Vector.class, double.class, LENGTH,
-                Double.doubleToLongBits(e), SPECIES,
-                ((bits, s) -> ((Double64Species)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Double64Vector scalars(double... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Double64Vector.class, double.class, LENGTH,
-                                         es, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Double64Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double64Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Double64Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Double64Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Double64Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class DoubleMaxVector extends DoubleVector {
-    static final DoubleMaxSpecies SPECIES = new DoubleMaxSpecies();
+    private static final Species<Double> SPECIES = DoubleVector.SPECIES_MAX;
 
     static final DoubleMaxVector ZERO = new DoubleMaxVector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final double[] vec; // Don't access directly, use getElements() instead.
 
     private double[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             DoubleMaxVector.class,
             double.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public DoubleVector reshape(Species<Double> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Double64Vector.Double64Species)) {
-            Double64Vector.Double64Species ts = (Double64Vector.Double64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Double64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 DoubleMaxVector.class,
                 double.class, LENGTH,
                 Double64Vector.class,
                 double.class, Double64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Double128Vector.Double128Species)) {
-            Double128Vector.Double128Species ts = (Double128Vector.Double128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Double128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 DoubleMaxVector.class,
                 double.class, LENGTH,
                 Double128Vector.class,
                 double.class, Double128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Double256Vector.Double256Species)) {
-            Double256Vector.Double256Species ts = (Double256Vector.Double256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Double256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 DoubleMaxVector.class,
                 double.class, LENGTH,
                 Double256Vector.class,
                 double.class, Double256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Double512Vector.Double512Species)) {
-            Double512Vector.Double512Species ts = (Double512Vector.Double512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Double512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 DoubleMaxVector.class,
                 double.class, LENGTH,
                 Double512Vector.class,
                 double.class, Double512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof DoubleMaxVector.DoubleMaxSpecies)) {
-            DoubleMaxVector.DoubleMaxSpecies ts = (DoubleMaxVector.DoubleMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == DoubleMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 DoubleMaxVector.class,
                 double.class, LENGTH,
                 DoubleMaxVector.class,
                 double.class, DoubleMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (DoubleVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public DoubleVector add(double o) {
-        return add(SPECIES.broadcast(o));
+        return add((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector add(double o, Mask<Double> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector sub(double o, Mask<Double> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector mul(double o, Mask<Double> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector min(double o) {
-        return min(SPECIES.broadcast(o));
+        return min((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector max(double o) {
-        return max(SPECIES.broadcast(o));
+        return max((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> equal(double o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> notEqual(double o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThan(double o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> lessThanEq(double o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThan(double o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Double> greaterThanEq(double o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector blend(double o, Mask<Double> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o) {
-        return div(SPECIES.broadcast(o));
+        return div((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector div(double o, Mask<Double> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public DoubleVector atan2(double o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector atan2(double o, Mask<Double> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector pow(double o, Mask<Double> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o1), (DoubleMaxVector)DoubleVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public DoubleVector fma(double o1, double o2, Mask<Double> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o1), (DoubleMaxVector)DoubleVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public DoubleVector hypot(double o, Mask<Double> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((DoubleMaxVector)DoubleVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public double addAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 0).blend(this, m).addAll();
+        return blend((DoubleMaxVector)DoubleVector.broadcast(SPECIES, (double) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public double mulAll(Mask<Double> m) {
-        return SPECIES.broadcast((double) 1).blend(this, m).mulAll();
+        return blend((DoubleMaxVector)DoubleVector.broadcast(SPECIES, (double) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public double minAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MAX_VALUE).blend(this, m).minAll();
+        return blend((DoubleMaxVector)DoubleVector.broadcast(SPECIES, Double.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public double maxAll(Mask<Double> m) {
-        return SPECIES.broadcast(Double.MIN_VALUE).blend(this, m).maxAll();
+        return blend((DoubleMaxVector)DoubleVector.broadcast(SPECIES, Double.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public DoubleMaxSpecies species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new DoubleMaxVector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new ByteMaxVector.ByteMaxMask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new ShortMaxVector.ShortMaxMask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new IntMaxVector.IntMaxMask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new LongMaxVector.LongMaxMask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new FloatMaxVector.FloatMaxMask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new DoubleMaxVector.DoubleMaxMask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public DoubleMaxSpecies species() {
+        public Species<Double> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new ByteMaxVector.ByteMaxShuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new ShortMaxVector.ShortMaxShuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new IntMaxVector.IntMaxShuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new LongMaxVector.LongMaxShuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new FloatMaxVector.FloatMaxShuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new DoubleMaxVector.DoubleMaxShuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public DoubleMaxShuffle rearrange(Vector.Shuffle<Double> o) {
             DoubleMaxShuffle s = (DoubleMaxShuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public DoubleMaxSpecies species() {
+    public Species<Double> species() {
         return SPECIES;
     }
-
-    static final class DoubleMaxSpecies extends DoubleSpecies {
-        static final int BIT_SIZE = Shape.S_Max_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Double.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(double.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Double> elementType() {
-            return double.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return DoubleMaxVector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return DoubleMaxMask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Double.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return DoubleMaxVector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_Max_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        DoubleMaxVector op(FOp f) {
-            double[] res = new double[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new DoubleMaxVector(res);
-        }
-
-        @Override
-        DoubleMaxVector op(Mask<Double> o, FOp f) {
-            double[] res = new double[length()];
-            boolean[] mbits = ((DoubleMaxMask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new DoubleMaxVector(res);
-        }
-
-        @Override
-        DoubleMaxMask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new DoubleMaxMask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public DoubleMaxVector zero() {
-            return VectorIntrinsics.broadcastCoerced(DoubleMaxVector.class, double.class, LENGTH,
-                                                     Double.doubleToLongBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((DoubleMaxSpecies)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public DoubleMaxVector broadcast(double e) {
-            return VectorIntrinsics.broadcastCoerced(
-                DoubleMaxVector.class, double.class, LENGTH,
-                Double.doubleToLongBits(e), SPECIES,
-                ((bits, s) -> ((DoubleMaxSpecies)s).op(i -> Double.longBitsToDouble((long)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public DoubleMaxVector scalars(double... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(DoubleMaxVector.class, double.class, LENGTH,
-                                         es, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((DoubleMaxSpecies)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> DoubleMaxMask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new DoubleMaxMask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> DoubleMaxShuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new DoubleMaxShuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -29,6 +29,7 @@
 import java.nio.ByteOrder;
 import java.util.Objects;
 import java.util.function.IntUnaryOperator;
+import java.util.function.Function;
 import java.util.concurrent.ThreadLocalRandom;
 
 import jdk.internal.misc.Unsafe;
@@ -110,8 +111,10 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static DoubleVector zero(DoubleSpecies species) {
-        return species.zero();
+    public static DoubleVector zero(Species<Double> species) {
+        return VectorIntrinsics.broadcastCoerced((Class<DoubleVector>) species.boxType(), double.class, species.length(),
+                                                 Double.doubleToLongBits(0.0f), species,
+                                                 ((bits, s) -> ((DoubleSpecies)s).op(i -> Double.longBitsToDouble((long)bits))));
     }
 
     /**
@@ -122,7 +125,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(DoubleSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Double>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
      * }</pre>
@@ -136,7 +139,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static DoubleVector fromByteArray(DoubleSpecies species, byte[] a, int ix) {
+    public static DoubleVector fromByteArray(Species<Double> species, byte[] a, int ix) {
         Objects.requireNonNull(a);
         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
         return VectorIntrinsics.load((Class<DoubleVector>) species.boxType(), double.class, species.length(),
@@ -158,7 +161,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(DoubleSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Double>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
      * }</pre>
@@ -177,7 +180,7 @@
      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
-    public static DoubleVector fromByteArray(DoubleSpecies species, byte[] a, int ix, Mask<Double> m) {
+    public static DoubleVector fromByteArray(Species<Double> species, byte[] a, int ix, Mask<Double> m) {
         return zero(species).blend(fromByteArray(species, a, ix), m);
     }
 
@@ -197,7 +200,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i){
+    public static DoubleVector fromArray(Species<Double> species, double[] a, int i){
         Objects.requireNonNull(a);
         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
         return VectorIntrinsics.load((Class<DoubleVector>) species.boxType(), double.class, species.length(),
@@ -226,7 +229,7 @@
      * is set {@code i > a.length - N}
      */
     @ForceInline
-    public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i, Mask<Double> m) {
+    public static DoubleVector fromArray(Species<Double> species, double[] a, int i, Mask<Double> m) {
         return zero(species).blend(fromArray(species, a, i), m);
     }
 
@@ -253,7 +256,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i, int[] indexMap, int j) {
+    public static DoubleVector fromArray(Species<Double> species, double[] a, int i, int[] indexMap, int j) {
         Objects.requireNonNull(a);
         Objects.requireNonNull(indexMap);
 
@@ -261,15 +264,16 @@
           return DoubleVector.fromArray(species, a, i + indexMap[j]);
         }
 
-        // Index vector: vix[0:n] = k -> i + indexMap[j + i]
-        IntVector vix = IntVector.fromArray(species.indexSpecies(), indexMap, j).add(i);
+        // Index vector: vix[0:n] = k -> i + indexMap[j + k]
+        IntVector vix = IntVector.fromArray(IntVector.species(species.indexShape()), indexMap, j).add(i);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
         return VectorIntrinsics.loadWithMap((Class<DoubleVector>) species.boxType(), double.class, species.length(),
-                                            species.indexSpecies().vectorType(), a, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, vix,
+                                            IntVector.species(species.indexShape()).boxType(), a, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, vix,
                                             a, i, indexMap, j, species,
-                                           (c, idx, iMap, idy, s) -> ((DoubleSpecies)s).op(n -> c[idx + iMap[idy+n]]));
+                                            (double[] c, int idx, int[] iMap, int idy, Species<Double> s) ->
+                                                ((DoubleSpecies)s).op(n -> c[idx + iMap[idy+n]]));
         }
 
     /**
@@ -298,7 +302,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static DoubleVector fromArray(DoubleSpecies species, double[] a, int i, Mask<Double> m, int[] indexMap, int j) {
+    public static DoubleVector fromArray(Species<Double> species, double[] a, int i, Mask<Double> m, int[] indexMap, int j) {
         // @@@ This can result in out of bounds errors for unset mask lanes
         return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
     }
@@ -313,7 +317,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(DoubleSpecies, ByteBuffer, int, Mask)} method} as follows:
+     * {@link #fromByteBuffer(Species<Double>, ByteBuffer, int, Mask)} method} as follows:
      * <pre>{@code
      *   return this.fromByteBuffer(b, i, this.maskAllTrue())
      * }</pre>
@@ -330,7 +334,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static DoubleVector fromByteBuffer(DoubleSpecies species, ByteBuffer bb, int ix) {
+    public static DoubleVector fromByteBuffer(Species<Double> species, ByteBuffer bb, int ix) {
         if (bb.order() != ByteOrder.nativeOrder()) {
             throw new IllegalArgumentException();
         }
@@ -382,11 +386,85 @@
      * {@code i >= b.limit() - (N * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
-    public static DoubleVector fromByteBuffer(DoubleSpecies species, ByteBuffer bb, int ix, Mask<Double> m) {
+    public static DoubleVector fromByteBuffer(Species<Double> species, ByteBuffer bb, int ix, Mask<Double> m) {
         return zero(species).blend(fromByteBuffer(species, bb, ix), m);
     }
 
     /**
+     * Returns a vector where all lane elements are set to the primitive
+     * value {@code e}.
+     *
+     * @param s species of the desired vector
+     * @param e the value
+     * @return a vector of vector where all lane elements are set to
+     * the primitive value {@code e}
+     */
+    @ForceInline
+    @SuppressWarnings("unchecked")
+    public static DoubleVector broadcast(Species<Double> s, double e) {
+        return VectorIntrinsics.broadcastCoerced(
+            (Class<DoubleVector>) s.boxType(), double.class, s.length(),
+            Double.doubleToLongBits(e), s,
+            ((bits, sp) -> ((DoubleSpecies)sp).op(i -> Double.longBitsToDouble((long)bits))));
+    }
+
+    /**
+     * Returns a vector where each lane element is set to a given
+     * primitive value.
+     * <p>
+     * For each vector lane, where {@code N} is the vector lane index, the
+     * the primitive value at index {@code N} is placed into the resulting
+     * vector at lane index {@code N}.
+     *
+     * @param s species of the desired vector
+     * @param es the given primitive values
+     * @return a vector where each lane element is set to a given primitive
+     * value
+     * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
+     */
+    @ForceInline
+    @SuppressWarnings("unchecked")
+    public static DoubleVector scalars(Species<Double> s, double... es) {
+        Objects.requireNonNull(es);
+        int ix = VectorIntrinsics.checkIndex(0, es.length, s.length());
+        return VectorIntrinsics.load((Class<DoubleVector>) s.boxType(), double.class, s.length(),
+                                     es, Unsafe.ARRAY_DOUBLE_BASE_OFFSET,
+                                     es, ix, s,
+                                     (c, idx, sp) -> ((DoubleSpecies)sp).op(n -> c[idx + n]));
+    }
+
+    /**
+     * Returns a vector where the first lane element is set to the primtive
+     * value {@code e}, all other lane elements are set to the default
+     * value.
+     *
+     * @param s species of the desired vector
+     * @param e the value
+     * @return a vector where the first lane element is set to the primitive
+     * value {@code e}
+     */
+    @ForceInline
+    public static final DoubleVector single(Species<Double> s, double e) {
+        return zero(s).with(0, e);
+    }
+
+    /**
+     * Returns a vector where each lane element is set to a randomly
+     * generated primitive value.
+     *
+     * The semantics are equivalent to calling
+     * {@link ThreadLocalRandom#nextDouble()}
+     *
+     * @param s species of the desired vector
+     * @return a vector where each lane elements is set to a randomly
+     * generated primitive value
+     */
+    public static DoubleVector random(Species<Double> s) {
+        ThreadLocalRandom r = ThreadLocalRandom.current();
+        return ((DoubleSpecies)s).op(i -> r.nextDouble());
+    }
+
+    /**
      * Returns a mask where each lane is set or unset according to given
      * {@code boolean} values
      * <p>
@@ -400,7 +478,7 @@
      * @throws IndexOutOfBoundsException if {@code bits.length < species.length()}
      */
     @ForceInline
-    public static Mask<Double> maskFromValues(DoubleSpecies species, boolean... bits) {
+    public static Mask<Double> maskFromValues(Species<Double> species, boolean... bits) {
         if (species.boxType() == DoubleMaxVector.class)
             return new DoubleMaxVector.DoubleMaxMask(bits);
         switch (species.bitSize()) {
@@ -413,7 +491,7 @@
     }
 
     // @@@ This is a bad implementation -- makes lambdas capturing -- fix this
-    static Mask<Double> trueMask(DoubleSpecies species) {
+    static Mask<Double> trueMask(Species<Double> species) {
         if (species.boxType() == DoubleMaxVector.class)
             return DoubleMaxVector.DoubleMaxMask.TRUE_MASK;
         switch (species.bitSize()) {
@@ -425,7 +503,7 @@
         }
     }
 
-    static Mask<Double> falseMask(DoubleSpecies species) {
+    static Mask<Double> falseMask(Species<Double> species) {
         if (species.boxType() == DoubleMaxVector.class)
             return DoubleMaxVector.DoubleMaxMask.FALSE_MASK;
         switch (species.bitSize()) {
@@ -453,7 +531,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Double> maskFromArray(DoubleSpecies species, boolean[] bits, int ix) {
+    public static Mask<Double> maskFromArray(Species<Double> species, boolean[] bits, int ix) {
         Objects.requireNonNull(bits);
         ix = VectorIntrinsics.checkIndex(ix, bits.length, species.length());
         return VectorIntrinsics.load((Class<Mask<Double>>) species.maskType(), long.class, species.length(),
@@ -470,10 +548,10 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Double> maskAllTrue(DoubleSpecies species) {
+    public static Mask<Double> maskAllTrue(Species<Double> species) {
         return VectorIntrinsics.broadcastCoerced((Class<Mask<Double>>) species.maskType(), long.class, species.length(),
                                                  (long)-1,  species,
-                                                 ((z, s) -> trueMask((DoubleSpecies)s)));
+                                                 ((z, s) -> trueMask(s)));
     }
 
     /**
@@ -484,10 +562,10 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static Mask<Double> maskAllFalse(DoubleSpecies species) {
+    public static Mask<Double> maskAllFalse(Species<Double> species) {
         return VectorIntrinsics.broadcastCoerced((Class<Mask<Double>>) species.maskType(), long.class, species.length(),
                                                  0, species, 
-                                                 ((z, s) -> falseMask((DoubleSpecies)s)));
+                                                 ((z, s) -> falseMask(s)));
     }
 
     /**
@@ -515,7 +593,7 @@
      * @return a shuffle of mapped indexes
      */
     @ForceInline
-    public static Shuffle<Double> shuffle(DoubleSpecies species, IntUnaryOperator f) {
+    public static Shuffle<Double> shuffle(Species<Double> species, IntUnaryOperator f) {
         if (species.boxType() == DoubleMaxVector.class)
             return new DoubleMaxVector.DoubleMaxShuffle(f);
         switch (species.bitSize()) {
@@ -541,7 +619,7 @@
      * @return a shuffle of lane indexes
      */
     @ForceInline
-    public static Shuffle<Double> shuffleIota(DoubleSpecies species) {
+    public static Shuffle<Double> shuffleIota(Species<Double> species) {
         if (species.boxType() == DoubleMaxVector.class)
             return new DoubleMaxVector.DoubleMaxShuffle(AbstractShuffle.IDENTITY);
         switch (species.bitSize()) {
@@ -570,7 +648,7 @@
      * {@code < species.length()}
      */
     @ForceInline
-    public static Shuffle<Double> shuffleFromValues(DoubleSpecies species, int... ixs) {
+    public static Shuffle<Double> shuffleFromValues(Species<Double> species, int... ixs) {
         if (species.boxType() == DoubleMaxVector.class)
             return new DoubleMaxVector.DoubleMaxShuffle(ixs);
         switch (species.bitSize()) {
@@ -598,7 +676,7 @@
      * {@code i > a.length - species.length()}
      */
     @ForceInline
-    public static Shuffle<Double> shuffleFromArray(DoubleSpecies species, int[] ixs, int i) {
+    public static Shuffle<Double> shuffleFromArray(Species<Double> species, int[] ixs, int i) {
         if (species.boxType() == DoubleMaxVector.class)
             return new DoubleMaxVector.DoubleMaxShuffle(ixs, i);
         switch (species.bitSize()) {
@@ -610,7 +688,6 @@
         }
     }
 
-
     // Ops
 
     @Override
@@ -2022,87 +2099,59 @@
     // Species
 
     @Override
-    public abstract DoubleSpecies species();
+    public abstract Species<Double> species();
 
     /**
      * Class representing {@link DoubleVector}'s of the same {@link Vector.Shape Shape}.
      */
-    public static abstract class DoubleSpecies extends Vector.Species<Double> {
+    static final class DoubleSpecies extends Vector.AbstractSpecies<Double> {
+        final Function<double[], DoubleVector> vectorFactory;
+        final Function<boolean[], Vector.Mask<Double>> maskFactory;
+
+        private DoubleSpecies(Vector.Shape shape,
+                          Class<?> boxType,
+                          Class<?> maskType,
+                          Function<double[], DoubleVector> vectorFactory,
+                          Function<boolean[], Vector.Mask<Double>> maskFactory) {
+            super(shape, double.class, Double.SIZE, boxType, maskType);
+            this.vectorFactory = vectorFactory;
+            this.maskFactory = maskFactory;
+        }
+
         interface FOp {
             double apply(int i);
         }
 
-        abstract DoubleVector op(FOp f);
-
-        abstract DoubleVector op(Mask<Double> m, FOp f);
-
         interface FOpm {
             boolean apply(int i);
         }
 
-        abstract Mask<Double> opm(FOpm f);
-
-        abstract IntVector.IntSpecies indexSpecies();
-
-
-        // Factories
-
-        @Override
-        public abstract DoubleVector zero();
-
-        /**
-         * Returns a vector where all lane elements are set to the primitive
-         * value {@code e}.
-         *
-         * @param e the value
-         * @return a vector of vector where all lane elements are set to
-         * the primitive value {@code e}
-         */
-        public abstract DoubleVector broadcast(double e);
-
-        /**
-         * Returns a vector where the first lane element is set to the primtive
-         * value {@code e}, all other lane elements are set to the default
-         * value.
-         *
-         * @param e the value
-         * @return a vector where the first lane element is set to the primitive
-         * value {@code e}
-         */
-        @ForceInline
-        public final DoubleVector single(double e) {
-            return zero().with(0, e);
+        DoubleVector op(FOp f) {
+            double[] res = new double[length()];
+            for (int i = 0; i < length(); i++) {
+                res[i] = f.apply(i);
+            }
+            return vectorFactory.apply(res);
         }
 
-        /**
-         * Returns a vector where each lane element is set to a randomly
-         * generated primitive value.
-         *
-         * The semantics are equivalent to calling
-         * {@code ThreadLocalRandom#nextDouble}.
-         *
-         * @return a vector where each lane elements is set to a randomly
-         * generated primitive value
-         */
-        public DoubleVector random() {
-            ThreadLocalRandom r = ThreadLocalRandom.current();
-            return op(i -> r.nextDouble());
+        DoubleVector op(Vector.Mask<Double> o, FOp f) {
+            double[] res = new double[length()];
+            boolean[] mbits = ((AbstractMask<Double>)o).getBits();
+            for (int i = 0; i < length(); i++) {
+                if (mbits[i]) {
+                    res[i] = f.apply(i);
+                }
+            }
+            return vectorFactory.apply(res);
         }
 
-        /**
-         * Returns a vector where each lane element is set to a given
-         * primitive value.
-         * <p>
-         * For each vector lane, where {@code N} is the vector lane index, the
-         * the primitive value at index {@code N} is placed into the resulting
-         * vector at lane index {@code N}.
-         *
-         * @param es the given primitive values
-         * @return a vector where each lane element is set to a given primitive
-         * value
-         * @throws IndexOutOfBoundsException if {@code es.length < this.length()}
-         */
-        public abstract DoubleVector scalars(double... es);
+        Vector.Mask<Double> opm(IntVector.IntSpecies.FOpm f) {
+            boolean[] res = new boolean[length()];
+            for (int i = 0; i < length(); i++) {
+                res[i] = (boolean)f.apply(i);
+            }
+            return maskFactory.apply(res);
+        }
     }
 
     /**
@@ -2115,8 +2164,7 @@
      *
      * @return the preferred species for an element type of {@code double}
      */
-    @SuppressWarnings("unchecked")
-    public static DoubleSpecies preferredSpecies() {
+    private static DoubleSpecies preferredSpecies() {
         return (DoubleSpecies) Species.ofPreferred(double.class);
     }
 
@@ -2127,16 +2175,41 @@
      * @return a species for an element type of {@code double} and shape
      * @throws IllegalArgumentException if no such species exists for the shape
      */
-    @SuppressWarnings("unchecked")
-    public static DoubleSpecies species(Vector.Shape s) {
+    static DoubleSpecies species(Vector.Shape s) {
         Objects.requireNonNull(s);
         switch (s) {
-            case S_64_BIT: return Double64Vector.SPECIES;
-            case S_128_BIT: return Double128Vector.SPECIES;
-            case S_256_BIT: return Double256Vector.SPECIES;
-            case S_512_BIT: return Double512Vector.SPECIES;
-            case S_Max_BIT: return DoubleMaxVector.SPECIES;
+            case S_64_BIT: return (DoubleSpecies) SPECIES_64;
+            case S_128_BIT: return (DoubleSpecies) SPECIES_128;
+            case S_256_BIT: return (DoubleSpecies) SPECIES_256;
+            case S_512_BIT: return (DoubleSpecies) SPECIES_512;
+            case S_Max_BIT: return (DoubleSpecies) SPECIES_MAX;
             default: throw new IllegalArgumentException("Bad shape: " + s);
         }
     }
+
+    /** Species representing {@link DoubleVector}s of {@link Vector.Shape#S_64_BIT Shape.S_64_BIT}. */
+    public static final Species<Double> SPECIES_64 = new DoubleSpecies(Shape.S_64_BIT, Double64Vector.class, Double64Vector.Double64Mask.class,
+                                                                     Double64Vector::new, Double64Vector.Double64Mask::new);
+
+    /** Species representing {@link DoubleVector}s of {@link Vector.Shape#S_128_BIT Shape.S_128_BIT}. */
+    public static final Species<Double> SPECIES_128 = new DoubleSpecies(Shape.S_128_BIT, Double128Vector.class, Double128Vector.Double128Mask.class,
+                                                                      Double128Vector::new, Double128Vector.Double128Mask::new);
+
+    /** Species representing {@link DoubleVector}s of {@link Vector.Shape#S_256_BIT Shape.S_256_BIT}. */
+    public static final Species<Double> SPECIES_256 = new DoubleSpecies(Shape.S_256_BIT, Double256Vector.class, Double256Vector.Double256Mask.class,
+                                                                      Double256Vector::new, Double256Vector.Double256Mask::new);
+
+    /** Species representing {@link DoubleVector}s of {@link Vector.Shape#S_512_BIT Shape.S_512_BIT}. */
+    public static final Species<Double> SPECIES_512 = new DoubleSpecies(Shape.S_512_BIT, Double512Vector.class, Double512Vector.Double512Mask.class,
+                                                                      Double512Vector::new, Double512Vector.Double512Mask::new);
+
+    /** Species representing {@link DoubleVector}s of {@link Vector.Shape#S_Max_BIT Shape.S_Max_BIT}. */
+    public static final Species<Double> SPECIES_MAX = new DoubleSpecies(Shape.S_Max_BIT, DoubleMaxVector.class, DoubleMaxVector.DoubleMaxMask.class,
+                                                                      DoubleMaxVector::new, DoubleMaxVector.DoubleMaxMask::new);
+
+    /**
+     * Preferred species for {@link DoubleVector}s.
+     * A preferred species is a species of maximal bit size for the platform.
+     */
+    public static final Species<Double> SPECIES_PREFERRED = (Species<Double>) preferredSpecies();
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class Float128Vector extends FloatVector {
-    static final Float128Species SPECIES = new Float128Species();
+    private static final Species<Float> SPECIES = FloatVector.SPECIES_128;
 
     static final Float128Vector ZERO = new Float128Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final float[] vec; // Don't access directly, use getElements() instead.
 
     private float[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             Float128Vector.class,
             float.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public FloatVector reshape(Species<Float> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Float64Vector.Float64Species)) {
-            Float64Vector.Float64Species ts = (Float64Vector.Float64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Float64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float128Vector.class,
                 float.class, LENGTH,
                 Float64Vector.class,
                 float.class, Float64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Float128Vector.Float128Species)) {
-            Float128Vector.Float128Species ts = (Float128Vector.Float128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Float128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float128Vector.class,
                 float.class, LENGTH,
                 Float128Vector.class,
                 float.class, Float128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Float256Vector.Float256Species)) {
-            Float256Vector.Float256Species ts = (Float256Vector.Float256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Float256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float128Vector.class,
                 float.class, LENGTH,
                 Float256Vector.class,
                 float.class, Float256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Float512Vector.Float512Species)) {
-            Float512Vector.Float512Species ts = (Float512Vector.Float512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Float512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float128Vector.class,
                 float.class, LENGTH,
                 Float512Vector.class,
                 float.class, Float512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof FloatMaxVector.FloatMaxSpecies)) {
-            FloatMaxVector.FloatMaxSpecies ts = (FloatMaxVector.FloatMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == FloatMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float128Vector.class,
                 float.class, LENGTH,
                 FloatMaxVector.class,
                 float.class, FloatMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public FloatVector add(float o) {
-        return add(SPECIES.broadcast(o));
+        return add((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector add(float o, Mask<Float> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o, Mask<Float> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o, Mask<Float> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector min(float o) {
-        return min(SPECIES.broadcast(o));
+        return min((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector max(float o) {
-        return max(SPECIES.broadcast(o));
+        return max((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> equal(float o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> notEqual(float o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThan(float o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThanEq(float o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThan(float o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThanEq(float o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector blend(float o, Mask<Float> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o) {
-        return div(SPECIES.broadcast(o));
+        return div((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o, Mask<Float> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public FloatVector atan2(float o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector atan2(float o, Mask<Float> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o, Mask<Float> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Float128Vector)FloatVector.broadcast(SPECIES, o1), (Float128Vector)FloatVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2, Mask<Float> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Float128Vector)FloatVector.broadcast(SPECIES, o1), (Float128Vector)FloatVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Float128Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o, Mask<Float> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Float128Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public float addAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 0).blend(this, m).addAll();
+        return blend((Float128Vector)FloatVector.broadcast(SPECIES, (float) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public float mulAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 1).blend(this, m).mulAll();
+        return blend((Float128Vector)FloatVector.broadcast(SPECIES, (float) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public float minAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MAX_VALUE).blend(this, m).minAll();
+        return blend((Float128Vector)FloatVector.broadcast(SPECIES, Float.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public float maxAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Float128Vector)FloatVector.broadcast(SPECIES, Float.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public Float128Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new Float128Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte128Vector.Byte128Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short128Vector.Short128Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int128Vector.Int128Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long128Vector.Long128Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float128Vector.Float128Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double128Vector.Double128Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public Float128Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte128Vector.Byte128Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short128Vector.Short128Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int128Vector.Int128Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long128Vector.Long128Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float128Vector.Float128Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double128Vector.Double128Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Float128Shuffle rearrange(Vector.Shuffle<Float> o) {
             Float128Shuffle s = (Float128Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public Float128Species species() {
+    public Species<Float> species() {
         return SPECIES;
     }
-
-    static final class Float128Species extends FloatSpecies {
-        static final int BIT_SIZE = Shape.S_128_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Float.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(float.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Float> elementType() {
-            return float.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Float128Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Float128Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Float.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Float128Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_128_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Float128Vector op(FOp f) {
-            float[] res = new float[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Float128Vector(res);
-        }
-
-        @Override
-        Float128Vector op(Mask<Float> o, FOp f) {
-            float[] res = new float[length()];
-            boolean[] mbits = ((Float128Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Float128Vector(res);
-        }
-
-        @Override
-        Float128Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Float128Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Float128Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Float128Vector.class, float.class, LENGTH,
-                                                     Float.floatToIntBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Float128Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float128Vector broadcast(float e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Float128Vector.class, float.class, LENGTH,
-                Float.floatToIntBits(e), SPECIES,
-                ((bits, s) -> ((Float128Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float128Vector scalars(float... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Float128Vector.class, float.class, LENGTH,
-                                         es, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Float128Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float128Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Float128Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float128Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Float128Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class Float256Vector extends FloatVector {
-    static final Float256Species SPECIES = new Float256Species();
+    private static final Species<Float> SPECIES = FloatVector.SPECIES_256;
 
     static final Float256Vector ZERO = new Float256Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final float[] vec; // Don't access directly, use getElements() instead.
 
     private float[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             Float256Vector.class,
             float.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public FloatVector reshape(Species<Float> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Float64Vector.Float64Species)) {
-            Float64Vector.Float64Species ts = (Float64Vector.Float64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Float64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float256Vector.class,
                 float.class, LENGTH,
                 Float64Vector.class,
                 float.class, Float64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Float128Vector.Float128Species)) {
-            Float128Vector.Float128Species ts = (Float128Vector.Float128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Float128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float256Vector.class,
                 float.class, LENGTH,
                 Float128Vector.class,
                 float.class, Float128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Float256Vector.Float256Species)) {
-            Float256Vector.Float256Species ts = (Float256Vector.Float256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Float256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float256Vector.class,
                 float.class, LENGTH,
                 Float256Vector.class,
                 float.class, Float256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Float512Vector.Float512Species)) {
-            Float512Vector.Float512Species ts = (Float512Vector.Float512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Float512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float256Vector.class,
                 float.class, LENGTH,
                 Float512Vector.class,
                 float.class, Float512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof FloatMaxVector.FloatMaxSpecies)) {
-            FloatMaxVector.FloatMaxSpecies ts = (FloatMaxVector.FloatMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == FloatMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float256Vector.class,
                 float.class, LENGTH,
                 FloatMaxVector.class,
                 float.class, FloatMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public FloatVector add(float o) {
-        return add(SPECIES.broadcast(o));
+        return add((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector add(float o, Mask<Float> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o, Mask<Float> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o, Mask<Float> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector min(float o) {
-        return min(SPECIES.broadcast(o));
+        return min((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector max(float o) {
-        return max(SPECIES.broadcast(o));
+        return max((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> equal(float o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> notEqual(float o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThan(float o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThanEq(float o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThan(float o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThanEq(float o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector blend(float o, Mask<Float> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o) {
-        return div(SPECIES.broadcast(o));
+        return div((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o, Mask<Float> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public FloatVector atan2(float o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector atan2(float o, Mask<Float> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o, Mask<Float> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Float256Vector)FloatVector.broadcast(SPECIES, o1), (Float256Vector)FloatVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2, Mask<Float> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Float256Vector)FloatVector.broadcast(SPECIES, o1), (Float256Vector)FloatVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Float256Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o, Mask<Float> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Float256Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public float addAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 0).blend(this, m).addAll();
+        return blend((Float256Vector)FloatVector.broadcast(SPECIES, (float) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public float mulAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 1).blend(this, m).mulAll();
+        return blend((Float256Vector)FloatVector.broadcast(SPECIES, (float) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public float minAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MAX_VALUE).blend(this, m).minAll();
+        return blend((Float256Vector)FloatVector.broadcast(SPECIES, Float.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public float maxAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Float256Vector)FloatVector.broadcast(SPECIES, Float.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public Float256Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new Float256Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte256Vector.Byte256Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short256Vector.Short256Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int256Vector.Int256Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long256Vector.Long256Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float256Vector.Float256Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double256Vector.Double256Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public Float256Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte256Vector.Byte256Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short256Vector.Short256Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int256Vector.Int256Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long256Vector.Long256Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float256Vector.Float256Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double256Vector.Double256Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Float256Shuffle rearrange(Vector.Shuffle<Float> o) {
             Float256Shuffle s = (Float256Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public Float256Species species() {
+    public Species<Float> species() {
         return SPECIES;
     }
-
-    static final class Float256Species extends FloatSpecies {
-        static final int BIT_SIZE = Shape.S_256_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Float.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(float.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Float> elementType() {
-            return float.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Float256Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Float256Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Float.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Float256Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_256_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Float256Vector op(FOp f) {
-            float[] res = new float[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Float256Vector(res);
-        }
-
-        @Override
-        Float256Vector op(Mask<Float> o, FOp f) {
-            float[] res = new float[length()];
-            boolean[] mbits = ((Float256Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Float256Vector(res);
-        }
-
-        @Override
-        Float256Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Float256Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Float256Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Float256Vector.class, float.class, LENGTH,
-                                                     Float.floatToIntBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Float256Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float256Vector broadcast(float e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Float256Vector.class, float.class, LENGTH,
-                Float.floatToIntBits(e), SPECIES,
-                ((bits, s) -> ((Float256Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float256Vector scalars(float... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Float256Vector.class, float.class, LENGTH,
-                                         es, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Float256Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float256Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Float256Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float256Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Float256Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class Float512Vector extends FloatVector {
-    static final Float512Species SPECIES = new Float512Species();
+    private static final Species<Float> SPECIES = FloatVector.SPECIES_512;
 
     static final Float512Vector ZERO = new Float512Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final float[] vec; // Don't access directly, use getElements() instead.
 
     private float[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             Float512Vector.class,
             float.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public FloatVector reshape(Species<Float> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Float64Vector.Float64Species)) {
-            Float64Vector.Float64Species ts = (Float64Vector.Float64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Float64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float512Vector.class,
                 float.class, LENGTH,
                 Float64Vector.class,
                 float.class, Float64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Float128Vector.Float128Species)) {
-            Float128Vector.Float128Species ts = (Float128Vector.Float128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Float128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float512Vector.class,
                 float.class, LENGTH,
                 Float128Vector.class,
                 float.class, Float128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Float256Vector.Float256Species)) {
-            Float256Vector.Float256Species ts = (Float256Vector.Float256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Float256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float512Vector.class,
                 float.class, LENGTH,
                 Float256Vector.class,
                 float.class, Float256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Float512Vector.Float512Species)) {
-            Float512Vector.Float512Species ts = (Float512Vector.Float512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Float512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float512Vector.class,
                 float.class, LENGTH,
                 Float512Vector.class,
                 float.class, Float512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof FloatMaxVector.FloatMaxSpecies)) {
-            FloatMaxVector.FloatMaxSpecies ts = (FloatMaxVector.FloatMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == FloatMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float512Vector.class,
                 float.class, LENGTH,
                 FloatMaxVector.class,
                 float.class, FloatMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public FloatVector add(float o) {
-        return add(SPECIES.broadcast(o));
+        return add((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector add(float o, Mask<Float> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o, Mask<Float> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o, Mask<Float> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector min(float o) {
-        return min(SPECIES.broadcast(o));
+        return min((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector max(float o) {
-        return max(SPECIES.broadcast(o));
+        return max((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> equal(float o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> notEqual(float o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThan(float o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThanEq(float o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThan(float o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThanEq(float o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector blend(float o, Mask<Float> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o) {
-        return div(SPECIES.broadcast(o));
+        return div((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o, Mask<Float> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public FloatVector atan2(float o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector atan2(float o, Mask<Float> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o, Mask<Float> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Float512Vector)FloatVector.broadcast(SPECIES, o1), (Float512Vector)FloatVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2, Mask<Float> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Float512Vector)FloatVector.broadcast(SPECIES, o1), (Float512Vector)FloatVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Float512Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o, Mask<Float> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Float512Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public float addAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 0).blend(this, m).addAll();
+        return blend((Float512Vector)FloatVector.broadcast(SPECIES, (float) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public float mulAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 1).blend(this, m).mulAll();
+        return blend((Float512Vector)FloatVector.broadcast(SPECIES, (float) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public float minAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MAX_VALUE).blend(this, m).minAll();
+        return blend((Float512Vector)FloatVector.broadcast(SPECIES, Float.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public float maxAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Float512Vector)FloatVector.broadcast(SPECIES, Float.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public Float512Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new Float512Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte512Vector.Byte512Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short512Vector.Short512Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int512Vector.Int512Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long512Vector.Long512Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float512Vector.Float512Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double512Vector.Double512Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public Float512Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte512Vector.Byte512Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short512Vector.Short512Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int512Vector.Int512Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long512Vector.Long512Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float512Vector.Float512Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double512Vector.Double512Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Float512Shuffle rearrange(Vector.Shuffle<Float> o) {
             Float512Shuffle s = (Float512Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public Float512Species species() {
+    public Species<Float> species() {
         return SPECIES;
     }
-
-    static final class Float512Species extends FloatSpecies {
-        static final int BIT_SIZE = Shape.S_512_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Float.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(float.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Float> elementType() {
-            return float.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Float512Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Float512Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Float.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Float512Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_512_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Float512Vector op(FOp f) {
-            float[] res = new float[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Float512Vector(res);
-        }
-
-        @Override
-        Float512Vector op(Mask<Float> o, FOp f) {
-            float[] res = new float[length()];
-            boolean[] mbits = ((Float512Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Float512Vector(res);
-        }
-
-        @Override
-        Float512Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Float512Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Float512Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Float512Vector.class, float.class, LENGTH,
-                                                     Float.floatToIntBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Float512Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float512Vector broadcast(float e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Float512Vector.class, float.class, LENGTH,
-                Float.floatToIntBits(e), SPECIES,
-                ((bits, s) -> ((Float512Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float512Vector scalars(float... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Float512Vector.class, float.class, LENGTH,
-                                         es, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Float512Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float512Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Float512Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float512Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Float512Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class Float64Vector extends FloatVector {
-    static final Float64Species SPECIES = new Float64Species();
+    private static final Species<Float> SPECIES = FloatVector.SPECIES_64;
 
     static final Float64Vector ZERO = new Float64Vector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final float[] vec; // Don't access directly, use getElements() instead.
 
     private float[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             Float64Vector.class,
             float.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public FloatVector reshape(Species<Float> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Float64Vector.Float64Species)) {
-            Float64Vector.Float64Species ts = (Float64Vector.Float64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Float64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float64Vector.class,
                 float.class, LENGTH,
                 Float64Vector.class,
                 float.class, Float64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Float128Vector.Float128Species)) {
-            Float128Vector.Float128Species ts = (Float128Vector.Float128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Float128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float64Vector.class,
                 float.class, LENGTH,
                 Float128Vector.class,
                 float.class, Float128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Float256Vector.Float256Species)) {
-            Float256Vector.Float256Species ts = (Float256Vector.Float256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Float256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float64Vector.class,
                 float.class, LENGTH,
                 Float256Vector.class,
                 float.class, Float256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Float512Vector.Float512Species)) {
-            Float512Vector.Float512Species ts = (Float512Vector.Float512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Float512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float64Vector.class,
                 float.class, LENGTH,
                 Float512Vector.class,
                 float.class, Float512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof FloatMaxVector.FloatMaxSpecies)) {
-            FloatMaxVector.FloatMaxSpecies ts = (FloatMaxVector.FloatMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == FloatMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 Float64Vector.class,
                 float.class, LENGTH,
                 FloatMaxVector.class,
                 float.class, FloatMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public FloatVector add(float o) {
-        return add(SPECIES.broadcast(o));
+        return add((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector add(float o, Mask<Float> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o, Mask<Float> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o, Mask<Float> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector min(float o) {
-        return min(SPECIES.broadcast(o));
+        return min((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector max(float o) {
-        return max(SPECIES.broadcast(o));
+        return max((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> equal(float o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> notEqual(float o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThan(float o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThanEq(float o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThan(float o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThanEq(float o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector blend(float o, Mask<Float> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o) {
-        return div(SPECIES.broadcast(o));
+        return div((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o, Mask<Float> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public FloatVector atan2(float o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector atan2(float o, Mask<Float> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o, Mask<Float> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((Float64Vector)FloatVector.broadcast(SPECIES, o1), (Float64Vector)FloatVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2, Mask<Float> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((Float64Vector)FloatVector.broadcast(SPECIES, o1), (Float64Vector)FloatVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((Float64Vector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o, Mask<Float> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((Float64Vector)FloatVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public float addAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 0).blend(this, m).addAll();
+        return blend((Float64Vector)FloatVector.broadcast(SPECIES, (float) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public float mulAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 1).blend(this, m).mulAll();
+        return blend((Float64Vector)FloatVector.broadcast(SPECIES, (float) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public float minAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MAX_VALUE).blend(this, m).minAll();
+        return blend((Float64Vector)FloatVector.broadcast(SPECIES, Float.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public float maxAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MIN_VALUE).blend(this, m).maxAll();
+        return blend((Float64Vector)FloatVector.broadcast(SPECIES, Float.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public Float64Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new Float64Vector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new Byte64Vector.Byte64Mask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new Short64Vector.Short64Mask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new Int64Vector.Int64Mask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new Long64Vector.Long64Mask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new Float64Vector.Float64Mask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new Double64Vector.Double64Mask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public Float64Species species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new Byte64Vector.Byte64Shuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new Short64Vector.Short64Shuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new Int64Vector.Int64Shuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new Long64Vector.Long64Shuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new Float64Vector.Float64Shuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new Double64Vector.Double64Shuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public Float64Shuffle rearrange(Vector.Shuffle<Float> o) {
             Float64Shuffle s = (Float64Shuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public Float64Species species() {
+    public Species<Float> species() {
         return SPECIES;
     }
-
-    static final class Float64Species extends FloatSpecies {
-        static final int BIT_SIZE = Shape.S_64_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Float.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(float.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Float> elementType() {
-            return float.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return Float64Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return Float64Mask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Float.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return Float64Vector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_64_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        Float64Vector op(FOp f) {
-            float[] res = new float[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new Float64Vector(res);
-        }
-
-        @Override
-        Float64Vector op(Mask<Float> o, FOp f) {
-            float[] res = new float[length()];
-            boolean[] mbits = ((Float64Mask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new Float64Vector(res);
-        }
-
-        @Override
-        Float64Mask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new Float64Mask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public Float64Vector zero() {
-            return VectorIntrinsics.broadcastCoerced(Float64Vector.class, float.class, LENGTH,
-                                                     Float.floatToIntBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((Float64Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float64Vector broadcast(float e) {
-            return VectorIntrinsics.broadcastCoerced(
-                Float64Vector.class, float.class, LENGTH,
-                Float.floatToIntBits(e), SPECIES,
-                ((bits, s) -> ((Float64Species)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public Float64Vector scalars(float... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(Float64Vector.class, float.class, LENGTH,
-                                         es, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((Float64Species)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float64Mask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new Float64Mask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> Float64Shuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new Float64Shuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -38,19 +38,20 @@
 
 @SuppressWarnings("cast")
 final class FloatMaxVector extends FloatVector {
-    static final FloatMaxSpecies SPECIES = new FloatMaxSpecies();
+    private static final Species<Float> SPECIES = FloatVector.SPECIES_MAX;
 
     static final FloatMaxVector ZERO = new FloatMaxVector();
 
     static final int LENGTH = SPECIES.length();
 
     // Index vector species
-    private static final IntVector.IntSpecies INDEX_SPEC;
+    private static final IntVector.IntSpecies INDEX_SPECIES;
+
     static {
         int bitSize = Vector.bitSizeForVectorLength(int.class, LENGTH);
-        Vector.Shape shape = Shape.forBitSize(bitSize);
-        INDEX_SPEC = (IntVector.IntSpecies) Species.of(int.class, shape);
+        INDEX_SPECIES = (IntVector.IntSpecies) IntVector.species(Shape.forBitSize(bitSize));
     }
+
     private final float[] vec; // Don't access directly, use getElements() instead.
 
     private float[] getElements() {
@@ -162,7 +163,7 @@
         return VectorIntrinsics.cast(
             FloatMaxVector.class,
             float.class, LENGTH,
-            s.vectorType(),
+            s.boxType(),
             s.elementType(), LENGTH,
             this, s,
             (species, vector) -> vector.castDefault(species)
@@ -180,37 +181,37 @@
             for (int i = 0; i < limit; i++) {
                 a[i] = (byte) this.get(i);
             }
-            return (Vector) ByteVector.fromArray((ByteVector.ByteSpecies) s, a, 0);
+            return (Vector) ByteVector.fromArray((Species<Byte>) s, a, 0);
         } else if (stype == short.class) {
             short[] a = new short[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (short) this.get(i);
             }
-            return (Vector) ShortVector.fromArray((ShortVector.ShortSpecies) s, a, 0);
+            return (Vector) ShortVector.fromArray((Species<Short>) s, a, 0);
         } else if (stype == int.class) {
             int[] a = new int[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (int) this.get(i);
             }
-            return (Vector) IntVector.fromArray((IntVector.IntSpecies) s, a, 0);
+            return (Vector) IntVector.fromArray((Species<Integer>) s, a, 0);
         } else if (stype == long.class) {
             long[] a = new long[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (long) this.get(i);
             }
-            return (Vector) LongVector.fromArray((LongVector.LongSpecies) s, a, 0);
+            return (Vector) LongVector.fromArray((Species<Long>) s, a, 0);
         } else if (stype == float.class) {
             float[] a = new float[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (float) this.get(i);
             }
-            return (Vector) FloatVector.fromArray((FloatVector.FloatSpecies) s, a, 0);
+            return (Vector) FloatVector.fromArray((Species<Float>) s, a, 0);
         } else if (stype == double.class) {
             double[] a = new double[limit];
             for (int i = 0; i < limit; i++) {
                 a[i] = (double) this.get(i);
             }
-            return (Vector) DoubleVector.fromArray((DoubleVector.DoubleSpecies) s, a, 0);
+            return (Vector) DoubleVector.fromArray((Species<Double>) s, a, 0);
         } else {
             throw new UnsupportedOperationException("Bad lane type for casting.");
         }
@@ -300,55 +301,50 @@
     @ForceInline
     public FloatVector reshape(Species<Float> s) {
         Objects.requireNonNull(s);
-        if (s.bitSize() == 64 && (s instanceof Float64Vector.Float64Species)) {
-            Float64Vector.Float64Species ts = (Float64Vector.Float64Species)s;
+        if (s.bitSize() == 64 && (s.boxType() == Float64Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 FloatMaxVector.class,
                 float.class, LENGTH,
                 Float64Vector.class,
                 float.class, Float64Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 128 && (s instanceof Float128Vector.Float128Species)) {
-            Float128Vector.Float128Species ts = (Float128Vector.Float128Species)s;
+        } else if (s.bitSize() == 128 && (s.boxType() == Float128Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 FloatMaxVector.class,
                 float.class, LENGTH,
                 Float128Vector.class,
                 float.class, Float128Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 256 && (s instanceof Float256Vector.Float256Species)) {
-            Float256Vector.Float256Species ts = (Float256Vector.Float256Species)s;
+        } else if (s.bitSize() == 256 && (s.boxType() == Float256Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 FloatMaxVector.class,
                 float.class, LENGTH,
                 Float256Vector.class,
                 float.class, Float256Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
-        } else if (s.bitSize() == 512 && (s instanceof Float512Vector.Float512Species)) {
-            Float512Vector.Float512Species ts = (Float512Vector.Float512Species)s;
+        } else if (s.bitSize() == 512 && (s.boxType() == Float512Vector.class)) {
             return VectorIntrinsics.reinterpret(
                 FloatMaxVector.class,
                 float.class, LENGTH,
                 Float512Vector.class,
                 float.class, Float512Vector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else if ((s.bitSize() > 0) && (s.bitSize() <= 2048)
-                && (s.bitSize() % 128 == 0) && (s instanceof FloatMaxVector.FloatMaxSpecies)) {
-            FloatMaxVector.FloatMaxSpecies ts = (FloatMaxVector.FloatMaxSpecies)s;
+                && (s.bitSize() % 128 == 0) && (s.boxType() == FloatMaxVector.class)) {
             return VectorIntrinsics.reinterpret(
                 FloatMaxVector.class,
                 float.class, LENGTH,
                 FloatMaxVector.class,
                 float.class, FloatMaxVector.LENGTH,
-                this, ts,
+                this, s,
                 (species, vector) -> (FloatVector) vector.defaultReinterpret(species)
             );
         } else {
@@ -361,103 +357,103 @@
     @Override
     @ForceInline
     public FloatVector add(float o) {
-        return add(SPECIES.broadcast(o));
+        return add((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector add(float o, Mask<Float> m) {
-        return add(SPECIES.broadcast(o), m);
+        return add((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o) {
-        return sub(SPECIES.broadcast(o));
+        return sub((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector sub(float o, Mask<Float> m) {
-        return sub(SPECIES.broadcast(o), m);
+        return sub((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o) {
-        return mul(SPECIES.broadcast(o));
+        return mul((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector mul(float o, Mask<Float> m) {
-        return mul(SPECIES.broadcast(o), m);
+        return mul((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector min(float o) {
-        return min(SPECIES.broadcast(o));
+        return min((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector max(float o) {
-        return max(SPECIES.broadcast(o));
+        return max((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> equal(float o) {
-        return equal(SPECIES.broadcast(o));
+        return equal((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> notEqual(float o) {
-        return notEqual(SPECIES.broadcast(o));
+        return notEqual((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThan(float o) {
-        return lessThan(SPECIES.broadcast(o));
+        return lessThan((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> lessThanEq(float o) {
-        return lessThanEq(SPECIES.broadcast(o));
+        return lessThanEq((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThan(float o) {
-        return greaterThan(SPECIES.broadcast(o));
+        return greaterThan((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public Mask<Float> greaterThanEq(float o) {
-        return greaterThanEq(SPECIES.broadcast(o));
+        return greaterThanEq((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector blend(float o, Mask<Float> m) {
-        return blend(SPECIES.broadcast(o), m);
+        return blend((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o) {
-        return div(SPECIES.broadcast(o));
+        return div((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector div(float o, Mask<Float> m) {
-        return div(SPECIES.broadcast(o), m);
+        return div((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
@@ -469,49 +465,49 @@
     @Override
     @ForceInline
     public FloatVector atan2(float o) {
-        return atan2(SPECIES.broadcast(o));
+        return atan2((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector atan2(float o, Mask<Float> m) {
-        return atan2(SPECIES.broadcast(o), m);
+        return atan2((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o) {
-        return pow(SPECIES.broadcast(o));
+        return pow((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector pow(float o, Mask<Float> m) {
-        return pow(SPECIES.broadcast(o), m);
+        return pow((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2));
+        return fma((FloatMaxVector)FloatVector.broadcast(SPECIES, o1), (FloatMaxVector)FloatVector.broadcast(SPECIES, o2));
     }
 
     @Override
     @ForceInline
     public FloatVector fma(float o1, float o2, Mask<Float> m) {
-        return fma(SPECIES.broadcast(o1), SPECIES.broadcast(o2), m);
+        return fma((FloatMaxVector)FloatVector.broadcast(SPECIES, o1), (FloatMaxVector)FloatVector.broadcast(SPECIES, o2), m);
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o) {
-        return hypot(SPECIES.broadcast(o));
+        return hypot((FloatMaxVector)FloatVector.broadcast(SPECIES, o));
     }
 
     @Override
     @ForceInline
     public FloatVector hypot(float o, Mask<Float> m) {
-        return hypot(SPECIES.broadcast(o), m);
+        return hypot((FloatMaxVector)FloatVector.broadcast(SPECIES, o), m);
     }
 
 
@@ -897,26 +893,26 @@
     @Override
     @ForceInline
     public float addAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 0).blend(this, m).addAll();
+        return blend((FloatMaxVector)FloatVector.broadcast(SPECIES, (float) 0), m).addAll();
     }
 
 
     @Override
     @ForceInline
     public float mulAll(Mask<Float> m) {
-        return SPECIES.broadcast((float) 1).blend(this, m).mulAll();
+        return blend((FloatMaxVector)FloatVector.broadcast(SPECIES, (float) 1), m).mulAll();
     }
 
     @Override
     @ForceInline
     public float minAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MAX_VALUE).blend(this, m).minAll();
+        return blend((FloatMaxVector)FloatVector.broadcast(SPECIES, Float.MAX_VALUE), m).minAll();
     }
 
     @Override
     @ForceInline
     public float maxAll(Mask<Float> m) {
-        return SPECIES.broadcast(Float.MIN_VALUE).blend(this, m).maxAll();
+        return blend((FloatMaxVector)FloatVector.broadcast(SPECIES, Float.MIN_VALUE), m).maxAll();
     }
 
     @Override
@@ -961,7 +957,7 @@
         Objects.requireNonNull(b);
 
         // Index vector: vix[0:n] = i -> ix + indexMap[iy + i]
-        IntVector vix = IntVector.fromArray(INDEX_SPEC, b, iy).add(ix);
+        IntVector vix = IntVector.fromArray(INDEX_SPECIES, b, iy).add(ix);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
@@ -1335,7 +1331,7 @@
         }
 
         @Override
-        public FloatMaxSpecies species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1351,6 +1347,31 @@
             return new FloatMaxVector(res);
         }
 
+        @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <E> Mask<E> cast(Species<E> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Mask length and species length differ");
+            Class<?> stype = species.elementType();
+            boolean [] maskArray = toArray();
+            if (stype == byte.class) {
+                return (Mask <E>) new ByteMaxVector.ByteMaxMask(maskArray);
+            } else if (stype == short.class) {
+                return (Mask <E>) new ShortMaxVector.ShortMaxMask(maskArray);
+            } else if (stype == int.class) {
+                return (Mask <E>) new IntMaxVector.IntMaxMask(maskArray);
+            } else if (stype == long.class) {
+                return (Mask <E>) new LongMaxVector.LongMaxMask(maskArray);
+            } else if (stype == float.class) {
+                return (Mask <E>) new FloatMaxVector.FloatMaxMask(maskArray);
+            } else if (stype == double.class) {
+                return (Mask <E>) new DoubleMaxVector.DoubleMaxMask(maskArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
         // Unary operations
 
         @Override
@@ -1423,7 +1444,7 @@
         }
 
         @Override
-        public FloatMaxSpecies species() {
+        public Species<Float> species() {
             return SPECIES;
         }
 
@@ -1437,6 +1458,31 @@
         }
 
         @Override
+        @ForceInline
+        @SuppressWarnings("unchecked")
+        public <F> Shuffle<F> cast(Species<F> species) {
+            if (length() != species.length())
+                throw new IllegalArgumentException("Shuffle length and species length differ");
+            Class<?> stype = species.elementType();
+            int [] shuffleArray = toArray();
+            if (stype == byte.class) {
+                return (Shuffle<F>) new ByteMaxVector.ByteMaxShuffle(shuffleArray);
+            } else if (stype == short.class) {
+                return (Shuffle<F>) new ShortMaxVector.ShortMaxShuffle(shuffleArray);
+            } else if (stype == int.class) {
+                return (Shuffle<F>) new IntMaxVector.IntMaxShuffle(shuffleArray);
+            } else if (stype == long.class) {
+                return (Shuffle<F>) new LongMaxVector.LongMaxShuffle(shuffleArray);
+            } else if (stype == float.class) {
+                return (Shuffle<F>) new FloatMaxVector.FloatMaxShuffle(shuffleArray);
+            } else if (stype == double.class) {
+                return (Shuffle<F>) new DoubleMaxVector.DoubleMaxShuffle(shuffleArray);
+            } else {
+                throw new UnsupportedOperationException("Bad lane type for casting.");
+            }
+        }
+
+        @Override
         public FloatMaxShuffle rearrange(Vector.Shuffle<Float> o) {
             FloatMaxShuffle s = (FloatMaxShuffle) o;
             byte[] r = new byte[reorder.length];
@@ -1450,153 +1496,7 @@
     // Species
 
     @Override
-    public FloatMaxSpecies species() {
+    public Species<Float> species() {
         return SPECIES;
     }
-
-    static final class FloatMaxSpecies extends FloatSpecies {
-        static final int BIT_SIZE = Shape.S_Max_BIT.bitSize();
-
-        static final int LENGTH = BIT_SIZE / Float.SIZE;
-
-        @Override
-        public String toString() {
-           StringBuilder sb = new StringBuilder("Shape[");
-           sb.append(bitSize()).append(" bits, ");
-           sb.append(length()).append(" ").append(float.class.getSimpleName()).append("s x ");
-           sb.append(elementSize()).append(" bits");
-           sb.append("]");
-           return sb.toString();
-        }
-
-        @Override
-        @ForceInline
-        public int bitSize() {
-            return BIT_SIZE;
-        }
-
-        @Override
-        @ForceInline
-        public int length() {
-            return LENGTH;
-        }
-
-        @Override
-        @ForceInline
-        public Class<Float> elementType() {
-            return float.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> boxType() {
-            return FloatMaxVector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Class<?> maskType() {
-            return FloatMaxMask.class;
-        }
-
-        @Override
-        @ForceInline
-        public int elementSize() {
-            return Float.SIZE;
-        }
-
-        @Override
-        @ForceInline
-        @SuppressWarnings("unchecked")
-        Class<?> vectorType() {
-            return FloatMaxVector.class;
-        }
-
-        @Override
-        @ForceInline
-        public Shape shape() {
-            return Shape.S_Max_BIT;
-        }
-
-       @Override
-       IntVector.IntSpecies indexSpecies() {
-          return INDEX_SPEC;
-       }
-
-        @Override
-        FloatMaxVector op(FOp f) {
-            float[] res = new float[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = f.apply(i);
-            }
-            return new FloatMaxVector(res);
-        }
-
-        @Override
-        FloatMaxVector op(Mask<Float> o, FOp f) {
-            float[] res = new float[length()];
-            boolean[] mbits = ((FloatMaxMask)o).getBits();
-            for (int i = 0; i < length(); i++) {
-                if (mbits[i]) {
-                    res[i] = f.apply(i);
-                }
-            }
-            return new FloatMaxVector(res);
-        }
-
-        @Override
-        FloatMaxMask opm(FOpm f) {
-            boolean[] res = new boolean[length()];
-            for (int i = 0; i < length(); i++) {
-                res[i] = (boolean)f.apply(i);
-            }
-            return new FloatMaxMask(res);
-        }
-
-        // Factories
-
-        @Override
-        @ForceInline
-        public FloatMaxVector zero() {
-            return VectorIntrinsics.broadcastCoerced(FloatMaxVector.class, float.class, LENGTH,
-                                                     Float.floatToIntBits(0.0f), SPECIES, 
-                                                     ((bits, s) -> ((FloatMaxSpecies)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public FloatMaxVector broadcast(float e) {
-            return VectorIntrinsics.broadcastCoerced(
-                FloatMaxVector.class, float.class, LENGTH,
-                Float.floatToIntBits(e), SPECIES,
-                ((bits, s) -> ((FloatMaxSpecies)s).op(i -> Float.intBitsToFloat((int)bits))));
-        }
-
-        @Override
-        @ForceInline
-        public FloatMaxVector scalars(float... es) {
-            Objects.requireNonNull(es);
-            int ix = VectorIntrinsics.checkIndex(0, es.length, LENGTH);
-            return VectorIntrinsics.load(FloatMaxVector.class, float.class, LENGTH,
-                                         es, Unsafe.ARRAY_FLOAT_BASE_OFFSET,
-                                         es, ix, SPECIES,
-                                         (c, idx, s) -> ((FloatMaxSpecies)s).op(n -> c[idx + n]));
-        }
-
-        @Override
-        @ForceInline
-        public <E> FloatMaxMask cast(Mask<E> m) {
-            if (m.length() != LENGTH)
-                throw new IllegalArgumentException("Mask length this species length differ");
-            return new FloatMaxMask(m.toArray());
-        }
-
-        @Override
-        @ForceInline
-        public <E> FloatMaxShuffle cast(Shuffle<E> s) {
-            if (s.length() != LENGTH)
-                throw new IllegalArgumentException("Shuffle length this species length differ");
-            return new FloatMaxShuffle(s.toArray());
-        }
-    }
 }
--- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java	Wed Apr 03 13:12:05 2019 -0700
+++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java	Wed Apr 10 12:05:46 2019 -0700
@@ -29,6 +29,7 @@
 import java.nio.ByteOrder;
 import java.util.Objects;
 import java.util.function.IntUnaryOperator;
+import java.util.function.Function;
 import java.util.concurrent.ThreadLocalRandom;
 
 import jdk.internal.misc.Unsafe;
@@ -110,8 +111,10 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector zero(FloatSpecies species) {
-        return species.zero();
+    public static FloatVector zero(Species<Float> species) {
+        return VectorIntrinsics.broadcastCoerced((Class<FloatVector>) species.boxType(), float.class, species.length(),
+                                                 Float.floatToIntBits(0.0f), species,
+                                                 ((bits, s) -> ((FloatSpecies)s).op(i -> Float.intBitsToFloat((int)bits))));
     }
 
     /**
@@ -122,7 +125,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(FloatSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Float>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, this.maskAllTrue());
      * }</pre>
@@ -136,7 +139,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromByteArray(FloatSpecies species, byte[] a, int ix) {
+    public static FloatVector fromByteArray(Species<Float> species, byte[] a, int ix) {
         Objects.requireNonNull(a);
         ix = VectorIntrinsics.checkIndex(ix, a.length, species.bitSize() / Byte.SIZE);
         return VectorIntrinsics.load((Class<FloatVector>) species.boxType(), float.class, species.length(),
@@ -158,7 +161,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(FloatSpecies, ByteBuffer, int, Mask) method} as follows:
+     * {@link #fromByteBuffer(Species<Float>, ByteBuffer, int, Mask) method} as follows:
      * <pre>{@code
      * return this.fromByteBuffer(ByteBuffer.wrap(a), i, m);
      * }</pre>
@@ -177,7 +180,7 @@
      * {@code i >= a.length - (N * this.elementSize() / Byte.SIZE)}
      */
     @ForceInline
-    public static FloatVector fromByteArray(FloatSpecies species, byte[] a, int ix, Mask<Float> m) {
+    public static FloatVector fromByteArray(Species<Float> species, byte[] a, int ix, Mask<Float> m) {
         return zero(species).blend(fromByteArray(species, a, ix), m);
     }
 
@@ -197,7 +200,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i){
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i){
         Objects.requireNonNull(a);
         i = VectorIntrinsics.checkIndex(i, a.length, species.length());
         return VectorIntrinsics.load((Class<FloatVector>) species.boxType(), float.class, species.length(),
@@ -226,7 +229,7 @@
      * is set {@code i > a.length - N}
      */
     @ForceInline
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i, Mask<Float> m) {
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i, Mask<Float> m) {
         return zero(species).blend(fromArray(species, a, i), m);
     }
 
@@ -253,20 +256,21 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i, int[] indexMap, int j) {
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i, int[] indexMap, int j) {
         Objects.requireNonNull(a);
         Objects.requireNonNull(indexMap);
 
 
-        // Index vector: vix[0:n] = k -> i + indexMap[j + i]
-        IntVector vix = IntVector.fromArray(species.indexSpecies(), indexMap, j).add(i);
+        // Index vector: vix[0:n] = k -> i + indexMap[j + k]
+        IntVector vix = IntVector.fromArray(IntVector.species(species.indexShape()), indexMap, j).add(i);
 
         vix = VectorIntrinsics.checkIndex(vix, a.length);
 
         return VectorIntrinsics.loadWithMap((Class<FloatVector>) species.boxType(), float.class, species.length(),
-                                            species.indexSpecies().vectorType(), a, Unsafe.ARRAY_FLOAT_BASE_OFFSET, vix,
+                                            IntVector.species(species.indexShape()).boxType(), a, Unsafe.ARRAY_FLOAT_BASE_OFFSET, vix,
                                             a, i, indexMap, j, species,
-                                           (c, idx, iMap, idy, s) -> ((FloatSpecies)s).op(n -> c[idx + iMap[idy+n]]));
+                                            (float[] c, int idx, int[] iMap, int idy, Species<Float> s) ->
+                                                ((FloatSpecies)s).op(n -> c[idx + iMap[idy+n]]));
         }
 
     /**
@@ -295,7 +299,7 @@
      */
     @ForceInline
     @SuppressWarnings("unchecked")
-    public static FloatVector fromArray(FloatSpecies species, float[] a, int i, Mask<Float> m, int[] indexMap, int j) {
+    public static FloatVector fromArray(Species<Float> species, float[] a, int i, Mask<Float> m, int[] indexMap, int j) {
         // @@@ This can result in out of bounds errors for unset mask lanes
         return zero(species).blend(fromArray(species, a, i, indexMap, j), m);
     }
@@ -310,7 +314,7 @@
      * <p>
      * This method behaves as if it returns the result of calling the
      * byte buffer, offset, and mask accepting
-     * {@link #fromByteBuffer(FloatSpecies, ByteBuffer, int, Mask)} method} as follows:
+