1.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/BoundMethodHandle.java Sun Aug 17 20:09:05 2014 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,491 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package java.lang.invoke;
1.30 -
1.31 -import static java.lang.invoke.LambdaForm.basicTypes;
1.32 -import static java.lang.invoke.MethodHandleStatics.*;
1.33 -
1.34 -import java.lang.invoke.LambdaForm.Name;
1.35 -import java.lang.invoke.LambdaForm.NamedFunction;
1.36 -import java.lang.invoke.MethodHandles.Lookup;
1.37 -import java.util.Arrays;
1.38 -import java.util.HashMap;
1.39 -
1.40 -import sun.invoke.util.ValueConversions;
1.41 -
1.42 -/**
1.43 - * The flavor of method handle which emulates an invoke instruction
1.44 - * on a predetermined argument. The JVM dispatches to the correct method
1.45 - * when the handle is created, not when it is invoked.
1.46 - *
1.47 - * All bound arguments are encapsulated in dedicated species.
1.48 - */
1.49 -/* non-public */ abstract class BoundMethodHandle extends MethodHandle {
1.50 -
1.51 - /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) {
1.52 - super(type, form);
1.53 - }
1.54 -
1.55 - //
1.56 - // BMH API and internals
1.57 - //
1.58 -
1.59 - static MethodHandle bindSingle(MethodType type, LambdaForm form, char xtype, Object x) {
1.60 - // for some type signatures, there exist pre-defined concrete BMH classes
1.61 - try {
1.62 - switch (xtype) {
1.63 - case 'L':
1.64 - if (true) return bindSingle(type, form, x); // Use known fast path.
1.65 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
1.66 - case 'I':
1.67 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
1.68 - case 'J':
1.69 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x);
1.70 - case 'F':
1.71 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x);
1.72 - case 'D':
1.73 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x);
1.74 - default : throw new InternalError("unexpected xtype: " + xtype);
1.75 - }
1.76 - } catch (Throwable t) {
1.77 - throw newInternalError(t);
1.78 - }
1.79 - }
1.80 -
1.81 - static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
1.82 - return new Species_L(type, form, x);
1.83 - }
1.84 -
1.85 - MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) {
1.86 - try {
1.87 - switch (xtype) {
1.88 - case 'L': return cloneExtendL(type, form, x);
1.89 - case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x));
1.90 - case 'J': return cloneExtendJ(type, form, (long) x);
1.91 - case 'F': return cloneExtendF(type, form, (float) x);
1.92 - case 'D': return cloneExtendD(type, form, (double) x);
1.93 - }
1.94 - } catch (Throwable t) {
1.95 - throw newInternalError(t);
1.96 - }
1.97 - throw new InternalError("unexpected type: " + xtype);
1.98 - }
1.99 -
1.100 - @Override
1.101 - MethodHandle bindArgument(int pos, char basicType, Object value) {
1.102 - MethodType type = type().dropParameterTypes(pos, pos+1);
1.103 - LambdaForm form = internalForm().bind(1+pos, speciesData());
1.104 - return cloneExtend(type, form, basicType, value);
1.105 - }
1.106 -
1.107 - @Override
1.108 - MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
1.109 - LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
1.110 - try {
1.111 - return clone(srcType, form);
1.112 - } catch (Throwable t) {
1.113 - throw newInternalError(t);
1.114 - }
1.115 - }
1.116 -
1.117 - @Override
1.118 - MethodHandle permuteArguments(MethodType newType, int[] reorder) {
1.119 - try {
1.120 - return clone(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
1.121 - } catch (Throwable t) {
1.122 - throw newInternalError(t);
1.123 - }
1.124 - }
1.125 -
1.126 - static final String EXTENSION_TYPES = "LIJFD";
1.127 - static final byte INDEX_L = 0, INDEX_I = 1, INDEX_J = 2, INDEX_F = 3, INDEX_D = 4;
1.128 - static byte extensionIndex(char type) {
1.129 - int i = EXTENSION_TYPES.indexOf(type);
1.130 - if (i < 0) throw new InternalError();
1.131 - return (byte) i;
1.132 - }
1.133 -
1.134 - /**
1.135 - * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
1.136 - * static field containing this value, and they must accordingly implement this method.
1.137 - */
1.138 - protected abstract SpeciesData speciesData();
1.139 -
1.140 - @Override
1.141 - final Object internalProperties() {
1.142 - return "/BMH="+internalValues();
1.143 - }
1.144 -
1.145 - @Override
1.146 - final Object internalValues() {
1.147 - Object[] boundValues = new Object[speciesData().fieldCount()];
1.148 - for (int i = 0; i < boundValues.length; ++i) {
1.149 - boundValues[i] = arg(i);
1.150 - }
1.151 - return Arrays.asList(boundValues);
1.152 - }
1.153 -
1.154 - public final Object arg(int i) {
1.155 - try {
1.156 - switch (speciesData().fieldType(i)) {
1.157 - case 'L': return argL(i);
1.158 - case 'I': return argI(i);
1.159 - case 'F': return argF(i);
1.160 - case 'D': return argD(i);
1.161 - case 'J': return argJ(i);
1.162 - }
1.163 - } catch (Throwable ex) {
1.164 - throw newInternalError(ex);
1.165 - }
1.166 - throw new InternalError("unexpected type: " + speciesData().types+"."+i);
1.167 - }
1.168 - public final Object argL(int i) throws Throwable { return speciesData().getters[i].invokeBasic(this); }
1.169 - public final int argI(int i) throws Throwable { return (int) speciesData().getters[i].invokeBasic(this); }
1.170 - public final float argF(int i) throws Throwable { return (float) speciesData().getters[i].invokeBasic(this); }
1.171 - public final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
1.172 - public final long argJ(int i) throws Throwable { return (long) speciesData().getters[i].invokeBasic(this); }
1.173 -
1.174 - //
1.175 - // cloning API
1.176 - //
1.177 -
1.178 - public abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
1.179 - public abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
1.180 - public abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable;
1.181 - public abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable;
1.182 - public abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable;
1.183 - public abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
1.184 -
1.185 - // The following is a grossly irregular hack:
1.186 - @Override MethodHandle reinvokerTarget() {
1.187 - try {
1.188 - return (MethodHandle) argL(0);
1.189 - } catch (Throwable ex) {
1.190 - throw newInternalError(ex);
1.191 - }
1.192 - }
1.193 -
1.194 - //
1.195 - // concrete BMH classes required to close bootstrap loops
1.196 - //
1.197 -
1.198 - private // make it private to force users to access the enclosing class first
1.199 - static final class Species_L extends BoundMethodHandle {
1.200 - final Object argL0;
1.201 - public Species_L(MethodType mt, LambdaForm lf, Object argL0) {
1.202 - super(mt, lf);
1.203 - this.argL0 = argL0;
1.204 - }
1.205 - // The following is a grossly irregular hack:
1.206 - @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
1.207 - @Override
1.208 - public SpeciesData speciesData() {
1.209 - return SPECIES_DATA;
1.210 - }
1.211 - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
1.212 - @Override
1.213 - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
1.214 - return new Species_L(mt, lf, argL0);
1.215 - }
1.216 - @Override
1.217 - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
1.218 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
1.219 - }
1.220 - @Override
1.221 - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
1.222 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
1.223 - }
1.224 - @Override
1.225 - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
1.226 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
1.227 - }
1.228 - @Override
1.229 - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
1.230 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
1.231 - }
1.232 - @Override
1.233 - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
1.234 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
1.235 - }
1.236 - }
1.237 -
1.238 -/*
1.239 - static final class Species_LL extends BoundMethodHandle {
1.240 - final Object argL0;
1.241 - final Object argL1;
1.242 - public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) {
1.243 - super(mt, lf);
1.244 - this.argL0 = argL0;
1.245 - this.argL1 = argL1;
1.246 - }
1.247 - @Override
1.248 - public SpeciesData speciesData() {
1.249 - return SPECIES_DATA;
1.250 - }
1.251 - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class);
1.252 - @Override
1.253 - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
1.254 - return new Species_LL(mt, lf, argL0, argL1);
1.255 - }
1.256 - @Override
1.257 - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
1.258 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
1.259 - }
1.260 - @Override
1.261 - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
1.262 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
1.263 - }
1.264 - @Override
1.265 - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
1.266 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
1.267 - }
1.268 - @Override
1.269 - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
1.270 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
1.271 - }
1.272 - @Override
1.273 - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
1.274 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
1.275 - }
1.276 - }
1.277 -
1.278 - static final class Species_JL extends BoundMethodHandle {
1.279 - final long argJ0;
1.280 - final Object argL1;
1.281 - public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) {
1.282 - super(mt, lf);
1.283 - this.argJ0 = argJ0;
1.284 - this.argL1 = argL1;
1.285 - }
1.286 - @Override
1.287 - public SpeciesData speciesData() {
1.288 - return SPECIES_DATA;
1.289 - }
1.290 - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class);
1.291 - @Override public final long argJ0() { return argJ0; }
1.292 - @Override public final Object argL1() { return argL1; }
1.293 - @Override
1.294 - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
1.295 - return new Species_JL(mt, lf, argJ0, argL1);
1.296 - }
1.297 - @Override
1.298 - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
1.299 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
1.300 - }
1.301 - @Override
1.302 - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
1.303 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
1.304 - }
1.305 - @Override
1.306 - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
1.307 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
1.308 - }
1.309 - @Override
1.310 - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
1.311 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
1.312 - }
1.313 - @Override
1.314 - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
1.315 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
1.316 - }
1.317 - }
1.318 -*/
1.319 -
1.320 - //
1.321 - // BMH species meta-data
1.322 - //
1.323 -
1.324 - /**
1.325 - * Meta-data wrapper for concrete BMH classes.
1.326 - */
1.327 - static class SpeciesData {
1.328 - final String types;
1.329 - final Class<? extends BoundMethodHandle> clazz;
1.330 - // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
1.331 - // Therefore, we need a non-final link in the chain. Use array elements.
1.332 - final MethodHandle[] constructor;
1.333 - final MethodHandle[] getters;
1.334 - final SpeciesData[] extensions;
1.335 -
1.336 - public int fieldCount() {
1.337 - return types.length();
1.338 - }
1.339 - public char fieldType(int i) {
1.340 - return types.charAt(i);
1.341 - }
1.342 -
1.343 - public String toString() {
1.344 - return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]";
1.345 - }
1.346 -
1.347 - /**
1.348 - * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
1.349 - * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
1.350 - * getter.
1.351 - */
1.352 - Name getterName(Name mhName, int i) {
1.353 - MethodHandle mh = getters[i];
1.354 - assert(mh != null) : this+"."+i;
1.355 - return new Name(mh, mhName);
1.356 - }
1.357 -
1.358 - NamedFunction getterFunction(int i) {
1.359 - return new NamedFunction(getters[i]);
1.360 - }
1.361 -
1.362 - static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
1.363 -
1.364 - private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
1.365 - this.types = types;
1.366 - this.clazz = clazz;
1.367 - if (!INIT_DONE) {
1.368 - this.constructor = new MethodHandle[1];
1.369 - this.getters = new MethodHandle[types.length()];
1.370 - } else {
1.371 - throw new IllegalStateException("bound method handle");
1.372 -// this.constructor = Factory.makeCtors(clazz, types, null);
1.373 -// this.getters = Factory.makeGetters(clazz, types, null);
1.374 - }
1.375 - this.extensions = new SpeciesData[EXTENSION_TYPES.length()];
1.376 - }
1.377 -
1.378 - private void initForBootstrap() {
1.379 - assert(!INIT_DONE);
1.380 - if (constructor[0] == null) {
1.381 -// Factory.makeCtors(clazz, types, this.constructor);
1.382 -// Factory.makeGetters(clazz, types, this.getters);
1.383 - }
1.384 - }
1.385 -
1.386 - private SpeciesData(String types) {
1.387 - // Placeholder only.
1.388 - this.types = types;
1.389 - this.clazz = null;
1.390 - this.constructor = null;
1.391 - this.getters = null;
1.392 - this.extensions = null;
1.393 - }
1.394 - private boolean isPlaceholder() { return clazz == null; }
1.395 -
1.396 - private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
1.397 - static { CACHE.put("", EMPTY); } // make bootstrap predictable
1.398 - private static final boolean INIT_DONE; // set after <clinit> finishes...
1.399 -
1.400 - SpeciesData extendWithType(char type) {
1.401 - int i = extensionIndex(type);
1.402 - SpeciesData d = extensions[i];
1.403 - if (d != null) return d;
1.404 - extensions[i] = d = get(types+type);
1.405 - return d;
1.406 - }
1.407 -
1.408 - SpeciesData extendWithIndex(byte index) {
1.409 - SpeciesData d = extensions[index];
1.410 - if (d != null) return d;
1.411 - extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index));
1.412 - return d;
1.413 - }
1.414 -
1.415 - private static SpeciesData get(String types) {
1.416 - // Acquire cache lock for query.
1.417 - SpeciesData d = lookupCache(types);
1.418 - if (!d.isPlaceholder())
1.419 - return d;
1.420 - synchronized (d) {
1.421 - // Use synch. on the placeholder to prevent multiple instantiation of one species.
1.422 - // Creating this class forces a recursive call to getForClass.
1.423 - if (lookupCache(types).isPlaceholder())
1.424 - throw new IllegalStateException("Cannot generate anything");
1.425 - }
1.426 - // Reacquire cache lock.
1.427 - d = lookupCache(types);
1.428 - // Class loading must have upgraded the cache.
1.429 - assert(d != null && !d.isPlaceholder());
1.430 - return d;
1.431 - }
1.432 - static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
1.433 - // clazz is a new class which is initializing its SPECIES_DATA field
1.434 - return updateCache(types, new SpeciesData(types, clazz));
1.435 - }
1.436 - private static synchronized SpeciesData lookupCache(String types) {
1.437 - SpeciesData d = CACHE.get(types);
1.438 - if (d != null) return d;
1.439 - d = new SpeciesData(types);
1.440 - assert(d.isPlaceholder());
1.441 - CACHE.put(types, d);
1.442 - return d;
1.443 - }
1.444 - private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
1.445 - SpeciesData d2;
1.446 - assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
1.447 - assert(!d.isPlaceholder());
1.448 - CACHE.put(types, d);
1.449 - return d;
1.450 - }
1.451 -
1.452 - static {
1.453 - // pre-fill the BMH speciesdata cache with BMH's inner classes
1.454 - final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
1.455 - SpeciesData d0 = BoundMethodHandle.SPECIES_DATA; // trigger class init
1.456 - assert(d0 == null || d0 == lookupCache("")) : d0;
1.457 - try {
1.458 - /*
1.459 - for (Class<?> c : rootCls.getDeclaredClasses()) {
1.460 - if (rootCls.isAssignableFrom(c)) {
1.461 - final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
1.462 - SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
1.463 - assert(d != null) : cbmh.getName();
1.464 - assert(d.clazz == cbmh);
1.465 - assert(d == lookupCache(d.types));
1.466 - }
1.467 - }
1.468 - */
1.469 - } catch (Throwable e) {
1.470 - throw newInternalError(e);
1.471 - }
1.472 -
1.473 - for (SpeciesData d : CACHE.values()) {
1.474 - d.initForBootstrap();
1.475 - }
1.476 - // Note: Do not simplify this, because INIT_DONE must not be
1.477 - // a compile-time constant during bootstrapping.
1.478 - INIT_DONE = Boolean.TRUE;
1.479 - }
1.480 - }
1.481 -
1.482 - static SpeciesData getSpeciesData(String types) {
1.483 - return SpeciesData.get(types);
1.484 - }
1.485 -
1.486 -
1.487 -
1.488 - private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
1.489 -
1.490 - /**
1.491 - * All subclasses must provide such a value describing their type signature.
1.492 - */
1.493 - static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
1.494 -}