1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package java.lang.invoke; 25 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.List; 29 30 import static java.lang.invoke.MethodHandleNatives.Constants.*; 31 32 /** 33 * Helper class, injected into java.lang.invoke, 34 * that bridges to the private ClassSpecializer mechanism. 35 */ 36 37 public interface ClassSpecializerHelper { 38 interface Frob { 39 Kind kind(); 40 int label(); 41 List<Object> asList(); 42 } 43 abstract class FrobImpl implements Frob { 44 private final int label; 45 public FrobImpl(int label) { 46 this.label = label; 47 } 48 public int label() { return label; } 49 @Override public abstract Kind kind(); 50 51 public String toString() { 52 final StringBuilder buf = new StringBuilder(); 53 buf.append("Frob[label=").append(label); 54 final Kind k = kind(); 55 if (k != null) { 56 for (MethodHandle mh : k.getters()) { 57 Object x = "?"; 58 try { 59 x = mh.invoke(this); 60 } catch (Throwable ex) { 61 x = "<<"+ex.getMessage()+">>"; 62 } 63 buf.append(", ").append(x); 64 } 65 } 66 buf.append("]"); 67 return buf.toString(); 68 } 69 70 public List<Object> asList() { 71 final List<MethodHandle> getters = kind().getters(); 72 ArrayList<Object> res = new ArrayList<>(getters.size()); 73 for (MethodHandle getter : getters) { 74 try { 75 res.add(getter.invoke(this)); 76 } catch (Throwable ex) { 77 throw new AssertionError(ex); 78 } 79 } 80 return res; 81 } 82 } 83 84 public static class Kind extends ClassSpecializer<Frob, Byte, Kind>.SpeciesData { 85 public Kind(SpecTest outer, Byte key) { 86 outer.super(key); 87 } 88 89 public MethodHandle factory() { 90 return super.factory(); 91 } 92 93 public List<MethodHandle> getters() { 94 return super.getters(); 95 } 96 97 private static final List<Class<?>> FIELD_TYPES 98 = Arrays.asList(String.class, float.class, Double.class, boolean.class, Object[].class, Object.class); 99 100 public static int MAX_KEY = FIELD_TYPES.size(); 101 102 @Override 103 protected List<Class<?>> deriveFieldTypes(Byte key) { 104 return FIELD_TYPES.subList(0, key); 105 } 106 107 @Override 108 protected Class<? extends Frob> deriveSuperClass() { 109 return FrobImpl.class; 110 } 111 112 @Override 113 protected MethodHandle deriveTransformHelper(MemberName transform, int whichtm) { 114 throw new AssertionError(); 115 } 116 117 @Override 118 protected <X> List<X> deriveTransformHelperArguments(MemberName transform, int whichtm, List<X> args, List<X> fields) { 119 throw new AssertionError(); 120 } 121 } 122 123 class SpecTest extends ClassSpecializer<Frob, Byte, Kind> { 124 private static final MemberName SPECIES_DATA_ACCESSOR; 125 static { 126 try { 127 SPECIES_DATA_ACCESSOR = MethodHandles.publicLookup() 128 .resolveOrFail(REF_invokeVirtual, FrobImpl.class, "kind", MethodType.methodType(Kind.class)); 129 } catch (ReflectiveOperationException ex) { 130 throw new AssertionError("Bootstrap link error", ex); 131 } 132 } 133 134 public SpecTest() { 135 super(Frob.class, Byte.class, Kind.class, 136 MethodType.methodType(void.class, int.class), 137 SPECIES_DATA_ACCESSOR, 138 "KIND", 139 Arrays.asList()); 140 } 141 142 @Override 143 protected Kind newSpeciesData(Byte key) { 144 return new Kind(this, key); 145 } 146 147 public static Kind kind(int key) { 148 return (Kind) SPEC_TEST.findSpecies((byte)key); 149 } 150 } 151 152 static final SpecTest SPEC_TEST = new SpecTest(); 153 154 } 155