1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,326 @@ 1.4 +/* 1.5 + * Copyright (c) 2003, 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 com.sun.tools.javac.code; 1.30 + 1.31 +import java.util.Iterator; 1.32 + 1.33 +import com.sun.tools.javac.tree.JCTree.JCLambda; 1.34 +import com.sun.tools.javac.util.*; 1.35 + 1.36 +/** A type annotation position. 1.37 +* 1.38 +* <p><b>This is NOT part of any supported API. 1.39 +* If you write code that depends on this, you do so at your own risk. 1.40 +* This code and its internal interfaces are subject to change or 1.41 +* deletion without notice.</b> 1.42 +*/ 1.43 +// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position 1.44 +public class TypeAnnotationPosition { 1.45 + 1.46 + public enum TypePathEntryKind { 1.47 + ARRAY(0), 1.48 + INNER_TYPE(1), 1.49 + WILDCARD(2), 1.50 + TYPE_ARGUMENT(3); 1.51 + 1.52 + public final int tag; 1.53 + 1.54 + private TypePathEntryKind(int tag) { 1.55 + this.tag = tag; 1.56 + } 1.57 + } 1.58 + 1.59 + public static class TypePathEntry { 1.60 + /** The fixed number of bytes per TypePathEntry. */ 1.61 + public static final int bytesPerEntry = 2; 1.62 + 1.63 + public final TypePathEntryKind tag; 1.64 + public final int arg; 1.65 + 1.66 + public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY); 1.67 + public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE); 1.68 + public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD); 1.69 + 1.70 + private TypePathEntry(TypePathEntryKind tag) { 1.71 + Assert.check(tag == TypePathEntryKind.ARRAY || 1.72 + tag == TypePathEntryKind.INNER_TYPE || 1.73 + tag == TypePathEntryKind.WILDCARD, 1.74 + "Invalid TypePathEntryKind: " + tag); 1.75 + this.tag = tag; 1.76 + this.arg = 0; 1.77 + } 1.78 + 1.79 + public TypePathEntry(TypePathEntryKind tag, int arg) { 1.80 + Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT, 1.81 + "Invalid TypePathEntryKind: " + tag); 1.82 + this.tag = tag; 1.83 + this.arg = arg; 1.84 + } 1.85 + 1.86 + public static TypePathEntry fromBinary(int tag, int arg) { 1.87 + Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag, 1.88 + "Invalid TypePathEntry tag/arg: " + tag + "/" + arg); 1.89 + switch (tag) { 1.90 + case 0: 1.91 + return ARRAY; 1.92 + case 1: 1.93 + return INNER_TYPE; 1.94 + case 2: 1.95 + return WILDCARD; 1.96 + case 3: 1.97 + return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg); 1.98 + default: 1.99 + Assert.error("Invalid TypePathEntryKind tag: " + tag); 1.100 + return null; 1.101 + } 1.102 + } 1.103 + 1.104 + @Override 1.105 + public String toString() { 1.106 + return tag.toString() + 1.107 + (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : ""); 1.108 + } 1.109 + 1.110 + @Override 1.111 + public boolean equals(Object other) { 1.112 + if (! (other instanceof TypePathEntry)) { 1.113 + return false; 1.114 + } 1.115 + TypePathEntry tpe = (TypePathEntry) other; 1.116 + return this.tag == tpe.tag && this.arg == tpe.arg; 1.117 + } 1.118 + 1.119 + @Override 1.120 + public int hashCode() { 1.121 + return this.tag.hashCode() * 17 + this.arg; 1.122 + } 1.123 + } 1.124 + 1.125 + public TargetType type = TargetType.UNKNOWN; 1.126 + 1.127 + // For generic/array types. 1.128 + public List<TypePathEntry> location = List.nil(); 1.129 + 1.130 + // Tree position. 1.131 + public int pos = -1; 1.132 + 1.133 + // For type casts, type tests, new, locals (as start_pc), 1.134 + // and method and constructor reference type arguments. 1.135 + public boolean isValidOffset = false; 1.136 + public int offset = -1; 1.137 + 1.138 + // For locals. arrays same length 1.139 + public int[] lvarOffset = null; 1.140 + public int[] lvarLength = null; 1.141 + public int[] lvarIndex = null; 1.142 + 1.143 + // For type parameter bound 1.144 + public int bound_index = Integer.MIN_VALUE; 1.145 + 1.146 + // For type parameter and method parameter 1.147 + public int parameter_index = Integer.MIN_VALUE; 1.148 + 1.149 + // For class extends, implements, and throws clauses 1.150 + public int type_index = Integer.MIN_VALUE; 1.151 + 1.152 + // For exception parameters, index into exception table. 1.153 + // In com.sun.tools.javac.jvm.Gen.genCatch we first set the type_index 1.154 + // to the catch type index - that value is only temporary. 1.155 + // Then in com.sun.tools.javac.jvm.Code.fillExceptionParameterPositions 1.156 + // we use that value to determine the exception table index. 1.157 + public int exception_index = Integer.MIN_VALUE; 1.158 + 1.159 + // If this type annotation is within a lambda expression, 1.160 + // store a pointer to the lambda expression tree in order 1.161 + // to allow a later translation to the right method. 1.162 + public JCLambda onLambda = null; 1.163 + 1.164 + public TypeAnnotationPosition() {} 1.165 + 1.166 + @Override 1.167 + public String toString() { 1.168 + StringBuilder sb = new StringBuilder(); 1.169 + sb.append('['); 1.170 + sb.append(type); 1.171 + 1.172 + switch (type) { 1.173 + // instanceof 1.174 + case INSTANCEOF: 1.175 + // new expression 1.176 + case NEW: 1.177 + // constructor/method reference receiver 1.178 + case CONSTRUCTOR_REFERENCE: 1.179 + case METHOD_REFERENCE: 1.180 + sb.append(", offset = "); 1.181 + sb.append(offset); 1.182 + break; 1.183 + // local variable 1.184 + case LOCAL_VARIABLE: 1.185 + // resource variable 1.186 + case RESOURCE_VARIABLE: 1.187 + if (lvarOffset == null) { 1.188 + sb.append(", lvarOffset is null!"); 1.189 + break; 1.190 + } 1.191 + sb.append(", {"); 1.192 + for (int i = 0; i < lvarOffset.length; ++i) { 1.193 + if (i != 0) sb.append("; "); 1.194 + sb.append("start_pc = "); 1.195 + sb.append(lvarOffset[i]); 1.196 + sb.append(", length = "); 1.197 + sb.append(lvarLength[i]); 1.198 + sb.append(", index = "); 1.199 + sb.append(lvarIndex[i]); 1.200 + } 1.201 + sb.append("}"); 1.202 + break; 1.203 + // method receiver 1.204 + case METHOD_RECEIVER: 1.205 + // Do nothing 1.206 + break; 1.207 + // type parameter 1.208 + case CLASS_TYPE_PARAMETER: 1.209 + case METHOD_TYPE_PARAMETER: 1.210 + sb.append(", param_index = "); 1.211 + sb.append(parameter_index); 1.212 + break; 1.213 + // type parameter bound 1.214 + case CLASS_TYPE_PARAMETER_BOUND: 1.215 + case METHOD_TYPE_PARAMETER_BOUND: 1.216 + sb.append(", param_index = "); 1.217 + sb.append(parameter_index); 1.218 + sb.append(", bound_index = "); 1.219 + sb.append(bound_index); 1.220 + break; 1.221 + // class extends or implements clause 1.222 + case CLASS_EXTENDS: 1.223 + sb.append(", type_index = "); 1.224 + sb.append(type_index); 1.225 + break; 1.226 + // throws 1.227 + case THROWS: 1.228 + sb.append(", type_index = "); 1.229 + sb.append(type_index); 1.230 + break; 1.231 + // exception parameter 1.232 + case EXCEPTION_PARAMETER: 1.233 + sb.append(", exception_index = "); 1.234 + sb.append(exception_index); 1.235 + break; 1.236 + // method parameter 1.237 + case METHOD_FORMAL_PARAMETER: 1.238 + sb.append(", param_index = "); 1.239 + sb.append(parameter_index); 1.240 + break; 1.241 + // type cast 1.242 + case CAST: 1.243 + // method/constructor/reference type argument 1.244 + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: 1.245 + case METHOD_INVOCATION_TYPE_ARGUMENT: 1.246 + case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: 1.247 + case METHOD_REFERENCE_TYPE_ARGUMENT: 1.248 + sb.append(", offset = "); 1.249 + sb.append(offset); 1.250 + sb.append(", type_index = "); 1.251 + sb.append(type_index); 1.252 + break; 1.253 + // We don't need to worry about these 1.254 + case METHOD_RETURN: 1.255 + case FIELD: 1.256 + break; 1.257 + case UNKNOWN: 1.258 + sb.append(", position UNKNOWN!"); 1.259 + break; 1.260 + default: 1.261 + Assert.error("Unknown target type: " + type); 1.262 + } 1.263 + 1.264 + // Append location data for generics/arrays. 1.265 + if (!location.isEmpty()) { 1.266 + sb.append(", location = ("); 1.267 + sb.append(location); 1.268 + sb.append(")"); 1.269 + } 1.270 + 1.271 + sb.append(", pos = "); 1.272 + sb.append(pos); 1.273 + 1.274 + if (onLambda != null) { 1.275 + sb.append(", onLambda hash = "); 1.276 + sb.append(onLambda.hashCode()); 1.277 + } 1.278 + 1.279 + sb.append(']'); 1.280 + return sb.toString(); 1.281 + } 1.282 + 1.283 + /** 1.284 + * Indicates whether the target tree of the annotation has been optimized 1.285 + * away from classfile or not. 1.286 + * @return true if the target has not been optimized away 1.287 + */ 1.288 + public boolean emitToClassfile() { 1.289 + return !type.isLocal() || isValidOffset; 1.290 + } 1.291 + 1.292 + 1.293 + public boolean matchesPos(int pos) { 1.294 + return this.pos == pos; 1.295 + } 1.296 + 1.297 + public void updatePosOffset(int to) { 1.298 + offset = to; 1.299 + lvarOffset = new int[]{to}; 1.300 + isValidOffset = true; 1.301 + } 1.302 + 1.303 + /** 1.304 + * Decode the binary representation for a type path and set 1.305 + * the {@code location} field. 1.306 + * 1.307 + * @param list The bytecode representation of the type path. 1.308 + */ 1.309 + public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) { 1.310 + ListBuffer<TypePathEntry> loc = new ListBuffer<>(); 1.311 + Iterator<Integer> iter = list.iterator(); 1.312 + while (iter.hasNext()) { 1.313 + Integer fst = iter.next(); 1.314 + Assert.check(iter.hasNext(), "Could not decode type path: " + list); 1.315 + Integer snd = iter.next(); 1.316 + loc = loc.append(TypePathEntry.fromBinary(fst, snd)); 1.317 + } 1.318 + return loc.toList(); 1.319 + } 1.320 + 1.321 + public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) { 1.322 + ListBuffer<Integer> loc = new ListBuffer<>(); 1.323 + for (TypePathEntry tpe : locs) { 1.324 + loc = loc.append(tpe.tag.tag); 1.325 + loc = loc.append(tpe.arg); 1.326 + } 1.327 + return loc.toList(); 1.328 + } 1.329 +}