1 /* 2 * Copyright (c) 2022, 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 package helpers; 24 25 import java.lang.constant.ClassDesc; 26 import java.util.HashMap; 27 import java.util.List; 28 import java.util.Random; 29 import java.lang.classfile.*; 30 import java.lang.classfile.attribute.*; 31 import java.lang.classfile.constantpool.*; 32 import java.lang.classfile.instruction.*; 33 import java.lang.constant.ModuleDesc; 34 import java.lang.constant.PackageDesc; 35 import java.lang.classfile.components.CodeStackTracker; 36 37 class RebuildingTransformation { 38 39 static private Random pathSwitch = new Random(1234); 40 41 static byte[] transform(ClassModel clm) { 42 return ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(clm.thisClass().asSymbol(), clb -> { 43 for (var cle : clm) { 44 switch (cle) { 45 case AccessFlags af -> clb.withFlags(af.flagsMask()); 46 case Superclass sc -> clb.withSuperclass(sc.superclassEntry().asSymbol()); 47 case Interfaces i -> clb.withInterfaceSymbols(i.interfaces().stream().map(ClassEntry::asSymbol).toArray(ClassDesc[]::new)); 48 case ClassFileVersion v -> clb.withVersion(v.majorVersion(), v.minorVersion()); 49 case FieldModel fm -> 50 clb.withField(fm.fieldName().stringValue(), fm.fieldTypeSymbol(), fb -> { 51 for (var fe : fm) { 52 switch (fe) { 53 case AccessFlags af -> fb.withFlags(af.flagsMask()); 54 case ConstantValueAttribute a -> fb.with(ConstantValueAttribute.of(a.constant().constantValue())); 55 case DeprecatedAttribute a -> fb.with(DeprecatedAttribute.of()); 56 case RuntimeInvisibleAnnotationsAttribute a -> fb.with(RuntimeInvisibleAnnotationsAttribute.of(transformAnnotations(a.annotations()))); 57 case RuntimeInvisibleTypeAnnotationsAttribute a -> fb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); 58 case RuntimeVisibleAnnotationsAttribute a -> fb.with(RuntimeVisibleAnnotationsAttribute.of(transformAnnotations(a.annotations()))); 59 case RuntimeVisibleTypeAnnotationsAttribute a -> fb.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); 60 case SignatureAttribute a -> fb.with(SignatureAttribute.of(Signature.parseFrom(a.asTypeSignature().signatureString()))); 61 case SyntheticAttribute a -> fb.with(SyntheticAttribute.of()); 62 case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); 63 case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName()); 64 } 65 } 66 }); 67 case MethodModel mm -> { 68 clb.withMethod(mm.methodName().stringValue(), mm.methodTypeSymbol(), mm.flags().flagsMask(), mb -> { 69 for (var me : mm) { 70 switch (me) { 71 case AccessFlags af -> mb.withFlags(af.flagsMask()); 72 case CodeModel com -> mb.withCode(cb -> cb.transforming(CodeStackTracker.of(), cob -> { 73 var labels = new HashMap<Label, Label>(); 74 for (var coe : com) { 75 switch (coe) { 76 case ArrayLoadInstruction i -> { 77 switch (i.typeKind()) { 78 case ByteType -> cob.baload(); 79 case ShortType -> cob.saload(); 80 case IntType -> cob.iaload(); 81 case FloatType -> cob.faload(); 82 case LongType -> cob.laload(); 83 case DoubleType -> cob.daload(); 84 case ReferenceType -> cob.aaload(); 85 case CharType -> cob.caload(); 86 default -> throw new AssertionError("Should not reach here"); 87 } 88 } 89 case ArrayStoreInstruction i -> { 90 switch (i.typeKind()) { 91 case ByteType -> cob.bastore(); 92 case ShortType -> cob.sastore(); 93 case IntType -> cob.iastore(); 94 case FloatType -> cob.fastore(); 95 case LongType -> cob.lastore(); 96 case DoubleType -> cob.dastore(); 97 case ReferenceType -> cob.aastore(); 98 case CharType -> cob.castore(); 99 default -> throw new AssertionError("Should not reach here"); 100 } 101 } 102 case BranchInstruction i -> { 103 var target = labels.computeIfAbsent(i.target(), l -> cob.newLabel()); 104 switch (i.opcode()) { 105 case GOTO -> cob.goto_(target); 106 case GOTO_W -> cob.goto_w(target); 107 case IF_ACMPEQ -> cob.if_acmpeq(target); 108 case IF_ACMPNE -> cob.if_acmpne(target); 109 case IF_ICMPEQ -> cob.if_icmpeq(target); 110 case IF_ICMPGE -> cob.if_icmpge(target); 111 case IF_ICMPGT -> cob.if_icmpgt(target); 112 case IF_ICMPLE -> cob.if_icmple(target); 113 case IF_ICMPLT -> cob.if_icmplt(target); 114 case IF_ICMPNE -> cob.if_icmpne(target); 115 case IFNONNULL -> cob.if_nonnull(target); 116 case IFNULL -> cob.if_null(target); 117 case IFEQ -> cob.ifeq(target); 118 case IFGE -> cob.ifge(target); 119 case IFGT -> cob.ifgt(target); 120 case IFLE -> cob.ifle(target); 121 case IFLT -> cob.iflt(target); 122 case IFNE -> cob.ifne(target); 123 default -> throw new AssertionError("Should not reach here"); 124 } 125 } 126 case ConstantInstruction i -> { 127 if (i.constantValue() == null) 128 if (pathSwitch.nextBoolean()) cob.aconst_null(); 129 else cob.constantInstruction(null); 130 else switch (i.constantValue()) { 131 case Integer iVal -> { 132 if (iVal == 1 && pathSwitch.nextBoolean()) cob.iconst_1(); 133 else if (iVal == 2 && pathSwitch.nextBoolean()) cob.iconst_2(); 134 else if (iVal == 3 && pathSwitch.nextBoolean()) cob.iconst_3(); 135 else if (iVal == 4 && pathSwitch.nextBoolean()) cob.iconst_4(); 136 else if (iVal == 5 && pathSwitch.nextBoolean()) cob.iconst_5(); 137 else if (iVal == -1 && pathSwitch.nextBoolean()) cob.iconst_m1(); 138 else if (iVal >= -128 && iVal <= 127 && pathSwitch.nextBoolean()) cob.bipush(iVal); 139 else if (iVal >= -32768 && iVal <= 32767 && pathSwitch.nextBoolean()) cob.sipush(iVal); 140 else cob.constantInstruction(iVal); 141 } 142 case Long lVal -> { 143 if (lVal == 0 && pathSwitch.nextBoolean()) cob.lconst_0(); 144 else if (lVal == 1 && pathSwitch.nextBoolean()) cob.lconst_1(); 145 else cob.constantInstruction(lVal); 146 } 147 case Float fVal -> { 148 if (fVal == 0.0 && pathSwitch.nextBoolean()) cob.fconst_0(); 149 else if (fVal == 1.0 && pathSwitch.nextBoolean()) cob.fconst_1(); 150 else if (fVal == 2.0 && pathSwitch.nextBoolean()) cob.fconst_2(); 151 else cob.constantInstruction(fVal); 152 } 153 case Double dVal -> { 154 if (dVal == 0.0d && pathSwitch.nextBoolean()) cob.dconst_0(); 155 else if (dVal == 1.0d && pathSwitch.nextBoolean()) cob.dconst_1(); 156 else cob.constantInstruction(dVal); 157 } 158 default -> cob.constantInstruction(i.constantValue()); 159 } 160 } 161 case ConvertInstruction i -> { 162 switch (i.fromType()) { 163 case DoubleType -> { 164 switch (i.toType()) { 165 case FloatType -> cob.d2f(); 166 case IntType -> cob.d2i(); 167 case LongType -> cob.d2l(); 168 default -> throw new AssertionError("Should not reach here"); 169 } 170 } 171 case FloatType -> { 172 switch (i.toType()) { 173 case DoubleType -> cob.f2d(); 174 case IntType -> cob.f2i(); 175 case LongType -> cob.f2l(); 176 default -> throw new AssertionError("Should not reach here"); 177 } 178 } 179 case IntType -> { 180 switch (i.toType()) { 181 case ByteType -> cob.i2b(); 182 case CharType -> cob.i2c(); 183 case DoubleType -> cob.i2d(); 184 case FloatType -> cob.i2f(); 185 case LongType -> cob.i2l(); 186 case ShortType -> cob.i2s(); 187 default -> throw new AssertionError("Should not reach here"); 188 } 189 } 190 case LongType -> { 191 switch (i.toType()) { 192 case DoubleType -> cob.l2d(); 193 case FloatType -> cob.l2f(); 194 case IntType -> cob.l2i(); 195 default -> throw new AssertionError("Should not reach here"); 196 } 197 } 198 default -> throw new AssertionError("Should not reach here"); 199 } 200 } 201 case DiscontinuedInstruction.JsrInstruction i -> 202 cob.with(DiscontinuedInstruction.JsrInstruction.of(i.opcode(), labels.computeIfAbsent(i.target(), l -> cob.newLabel()))); 203 case DiscontinuedInstruction.RetInstruction i -> 204 cob.with(DiscontinuedInstruction.RetInstruction.of(i.opcode(), i.slot())); 205 case FieldInstruction i -> { 206 if (pathSwitch.nextBoolean()) { 207 switch (i.opcode()) { 208 case GETFIELD -> cob.getfield(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 209 case GETSTATIC -> cob.getstatic(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 210 case PUTFIELD -> cob.putfield(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 211 case PUTSTATIC -> cob.putstatic(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 212 default -> throw new AssertionError("Should not reach here"); 213 } 214 } else { 215 switch (i.opcode()) { 216 case GETFIELD -> cob.getfield(i.field()); 217 case GETSTATIC -> cob.getstatic(i.field()); 218 case PUTFIELD -> cob.putfield(i.field()); 219 case PUTSTATIC -> cob.putstatic(i.field()); 220 default -> throw new AssertionError("Should not reach here"); 221 } 222 } 223 } 224 case InvokeDynamicInstruction i -> { 225 if (pathSwitch.nextBoolean()) cob.invokedynamic(i.invokedynamic().asSymbol()); 226 else cob.invokedynamic(i.invokedynamic()); 227 } 228 case InvokeInstruction i -> { 229 if (pathSwitch.nextBoolean()) { 230 if (i.isInterface()) { 231 switch (i.opcode()) { 232 case INVOKEINTERFACE -> cob.invokeinterface(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 233 case INVOKESPECIAL -> cob.invokespecial(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol(), true); 234 case INVOKESTATIC -> cob.invokestatic(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol(), true); 235 default -> throw new AssertionError("Should not reach here"); 236 } 237 } else { 238 switch (i.opcode()) { 239 case INVOKESPECIAL -> cob.invokespecial(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 240 case INVOKESTATIC -> cob.invokestatic(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 241 case INVOKEVIRTUAL -> cob.invokevirtual(i.owner().asSymbol(), i.name().stringValue(), i.typeSymbol()); 242 default -> throw new AssertionError("Should not reach here"); 243 } 244 } 245 } else { 246 switch (i.method()) { 247 case InterfaceMethodRefEntry en -> { 248 switch (i.opcode()) { 249 case INVOKEINTERFACE -> cob.invokeinterface(en); 250 case INVOKESPECIAL -> cob.invokespecial(en); 251 case INVOKESTATIC -> cob.invokestatic(en); 252 default -> throw new AssertionError("Should not reach here"); 253 } 254 } 255 case MethodRefEntry en -> { 256 switch (i.opcode()) { 257 case INVOKESPECIAL -> cob.invokespecial(en); 258 case INVOKESTATIC -> cob.invokestatic(en); 259 case INVOKEVIRTUAL -> cob.invokevirtual(en); 260 default -> throw new AssertionError("Should not reach here"); 261 } 262 } 263 default -> throw new AssertionError("Should not reach here"); 264 } 265 } 266 } 267 case LoadInstruction i -> { 268 switch (i.typeKind()) { 269 case IntType -> cob.iload(i.slot()); 270 case FloatType -> cob.fload(i.slot()); 271 case LongType -> cob.lload(i.slot()); 272 case DoubleType -> cob.dload(i.slot()); 273 case ReferenceType -> cob.aload(i.slot()); 274 default -> throw new AssertionError("Should not reach here"); 275 } 276 } 277 case StoreInstruction i -> { 278 switch (i.typeKind()) { 279 case IntType -> cob.istore(i.slot()); 280 case FloatType -> cob.fstore(i.slot()); 281 case LongType -> cob.lstore(i.slot()); 282 case DoubleType -> cob.dstore(i.slot()); 283 case ReferenceType -> cob.astore(i.slot()); 284 default -> throw new AssertionError("Should not reach here"); 285 } 286 } 287 case IncrementInstruction i -> 288 cob.iinc(i.slot(), i.constant()); 289 case LookupSwitchInstruction i -> 290 cob.lookupswitch(labels.computeIfAbsent(i.defaultTarget(), l -> cob.newLabel()), 291 i.cases().stream().map(sc -> 292 SwitchCase.of(sc.caseValue(), labels.computeIfAbsent(sc.target(), l -> cob.newLabel()))).toList()); 293 case MonitorInstruction i -> { 294 switch (i.opcode()) { 295 case MONITORENTER -> cob.monitorenter(); 296 case MONITOREXIT -> cob.monitorexit(); 297 default -> throw new AssertionError("Should not reach here"); 298 } 299 } 300 case NewMultiArrayInstruction i -> { 301 if (pathSwitch.nextBoolean()) { 302 cob.multianewarray(i.arrayType().asSymbol(), i.dimensions()); 303 } else { 304 cob.multianewarray(i.arrayType(), i.dimensions()); 305 } 306 } 307 case NewObjectInstruction i -> { 308 if (pathSwitch.nextBoolean()) { 309 cob.new_(i.className().asSymbol()); 310 } else { 311 cob.new_(i.className()); 312 } 313 } 314 case NewPrimitiveArrayInstruction i -> 315 cob.newarray(i.typeKind()); 316 case NewReferenceArrayInstruction i -> { 317 if (pathSwitch.nextBoolean()) { 318 cob.anewarray(i.componentType().asSymbol()); 319 } else { 320 cob.anewarray(i.componentType()); 321 } 322 } 323 case NopInstruction i -> 324 cob.nop(); 325 case OperatorInstruction i -> { 326 switch (i.opcode()) { 327 case IADD -> cob.iadd(); 328 case LADD -> cob.ladd(); 329 case FADD -> cob.fadd(); 330 case DADD -> cob.dadd(); 331 case ISUB -> cob.isub(); 332 case LSUB -> cob.lsub(); 333 case FSUB -> cob.fsub(); 334 case DSUB -> cob.dsub(); 335 case IMUL -> cob.imul(); 336 case LMUL -> cob.lmul(); 337 case FMUL -> cob.fmul(); 338 case DMUL -> cob.dmul(); 339 case IDIV -> cob.idiv(); 340 case LDIV -> cob.ldiv(); 341 case FDIV -> cob.fdiv(); 342 case DDIV -> cob.ddiv(); 343 case IREM -> cob.irem(); 344 case LREM -> cob.lrem(); 345 case FREM -> cob.frem(); 346 case DREM -> cob.drem(); 347 case INEG -> cob.ineg(); 348 case LNEG -> cob.lneg(); 349 case FNEG -> cob.fneg(); 350 case DNEG -> cob.dneg(); 351 case ISHL -> cob.ishl(); 352 case LSHL -> cob.lshl(); 353 case ISHR -> cob.ishr(); 354 case LSHR -> cob.lshr(); 355 case IUSHR -> cob.iushr(); 356 case LUSHR -> cob.lushr(); 357 case IAND -> cob.iand(); 358 case LAND -> cob.land(); 359 case IOR -> cob.ior(); 360 case LOR -> cob.lor(); 361 case IXOR -> cob.ixor(); 362 case LXOR -> cob.lxor(); 363 case LCMP -> cob.lcmp(); 364 case FCMPL -> cob.fcmpl(); 365 case FCMPG -> cob.fcmpg(); 366 case DCMPL -> cob.dcmpl(); 367 case DCMPG -> cob.dcmpg(); 368 case ARRAYLENGTH -> cob.arraylength(); 369 default -> throw new AssertionError("Should not reach here"); 370 } 371 } 372 case ReturnInstruction i -> { 373 switch (i.typeKind()) { 374 case IntType -> cob.ireturn(); 375 case FloatType -> cob.freturn(); 376 case LongType -> cob.lreturn(); 377 case DoubleType -> cob.dreturn(); 378 case ReferenceType -> cob.areturn(); 379 case VoidType -> cob.return_(); 380 default -> throw new AssertionError("Should not reach here"); 381 } 382 } 383 case StackInstruction i -> { 384 switch (i.opcode()) { 385 case POP -> cob.pop(); 386 case POP2 -> cob.pop2(); 387 case DUP -> cob.dup(); 388 case DUP_X1 -> cob.dup_x1(); 389 case DUP_X2 -> cob.dup_x2(); 390 case DUP2 -> cob.dup2(); 391 case DUP2_X1 -> cob.dup2_x1(); 392 case DUP2_X2 -> cob.dup2_x2(); 393 case SWAP -> cob.swap(); 394 default -> throw new AssertionError("Should not reach here"); 395 } 396 } 397 case TableSwitchInstruction i -> 398 cob.tableswitch(i.lowValue(), i.highValue(), 399 labels.computeIfAbsent(i.defaultTarget(), l -> cob.newLabel()), 400 i.cases().stream().map(sc -> 401 SwitchCase.of(sc.caseValue(), labels.computeIfAbsent(sc.target(), l -> cob.newLabel()))).toList()); 402 case ThrowInstruction i -> cob.athrow(); 403 case TypeCheckInstruction i -> { 404 if (pathSwitch.nextBoolean()) { 405 switch (i.opcode()) { 406 case CHECKCAST -> cob.checkcast(i.type().asSymbol()); 407 case INSTANCEOF -> cob.instanceof_(i.type().asSymbol()); 408 default -> throw new AssertionError("Should not reach here"); 409 } 410 } else { 411 switch (i.opcode()) { 412 case CHECKCAST -> cob.checkcast(i.type()); 413 case INSTANCEOF -> cob.instanceof_(i.type()); 414 default -> throw new AssertionError("Should not reach here"); 415 } 416 } 417 } 418 case CharacterRange pi -> 419 cob.characterRange(labels.computeIfAbsent(pi.startScope(), l -> cob.newLabel()), 420 labels.computeIfAbsent(pi.endScope(), l -> cob.newLabel()), 421 pi.characterRangeStart(), pi.characterRangeEnd(), pi.flags()); 422 case ExceptionCatch pi -> 423 pi.catchType().ifPresentOrElse( 424 catchType -> cob.exceptionCatch(labels.computeIfAbsent(pi.tryStart(), l -> cob.newLabel()), 425 labels.computeIfAbsent(pi.tryEnd(), l -> cob.newLabel()), 426 labels.computeIfAbsent(pi.handler(), l -> cob.newLabel()), 427 catchType.asSymbol()), 428 () -> cob.exceptionCatchAll(labels.computeIfAbsent(pi.tryStart(), l -> cob.newLabel()), 429 labels.computeIfAbsent(pi.tryEnd(), l -> cob.newLabel()), 430 labels.computeIfAbsent(pi.handler(), l -> cob.newLabel()))); 431 case LabelTarget pi -> 432 cob.labelBinding(labels.computeIfAbsent(pi.label(), l -> cob.newLabel())); 433 case LineNumber pi -> 434 cob.lineNumber(pi.line()); 435 case LocalVariable pi -> 436 cob.localVariable(pi.slot(), pi.name().stringValue(), pi.typeSymbol(), 437 labels.computeIfAbsent(pi.startScope(), l -> cob.newLabel()), 438 labels.computeIfAbsent(pi.endScope(), l -> cob.newLabel())); 439 case LocalVariableType pi -> 440 cob.localVariableType(pi.slot(), pi.name().stringValue(), 441 Signature.parseFrom(pi.signatureSymbol().signatureString()), 442 labels.computeIfAbsent(pi.startScope(), l -> cob.newLabel()), 443 labels.computeIfAbsent(pi.endScope(), l -> cob.newLabel())); 444 case RuntimeInvisibleTypeAnnotationsAttribute a -> 445 cob.with(RuntimeInvisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), cob, labels))); 446 case RuntimeVisibleTypeAnnotationsAttribute a -> 447 cob.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), cob, labels))); 448 case StackMapTableAttribute a -> 449 throw new AssertionError("Unexpected StackMapTableAttribute here"); 450 case CustomAttribute a -> 451 throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); 452 } 453 } 454 com.findAttribute(Attributes.STACK_MAP_TABLE).ifPresent(smta -> 455 cob.with(StackMapTableAttribute.of(smta.entries().stream().map(fr -> 456 StackMapFrameInfo.of(labels.computeIfAbsent(fr.target(), l -> cob.newLabel()), 457 transformFrameTypeInfos(fr.locals(), cob, labels), 458 transformFrameTypeInfos(fr.stack(), cob, labels))).toList()))); 459 })); 460 case AnnotationDefaultAttribute a -> mb.with(AnnotationDefaultAttribute.of(transformAnnotationValue(a.defaultValue()))); 461 case DeprecatedAttribute a -> mb.with(DeprecatedAttribute.of()); 462 case ExceptionsAttribute a -> mb.with(ExceptionsAttribute.ofSymbols(a.exceptions().stream().map(ClassEntry::asSymbol).toArray(ClassDesc[]::new))); 463 case MethodParametersAttribute a -> mb.with(MethodParametersAttribute.of(a.parameters().stream().map(mp -> 464 MethodParameterInfo.ofParameter(mp.name().map(Utf8Entry::stringValue), mp.flagsMask())).toArray(MethodParameterInfo[]::new))); 465 case RuntimeInvisibleAnnotationsAttribute a -> mb.with(RuntimeInvisibleAnnotationsAttribute.of(transformAnnotations(a.annotations()))); 466 case RuntimeInvisibleParameterAnnotationsAttribute a -> mb.with(RuntimeInvisibleParameterAnnotationsAttribute.of(a.parameterAnnotations().stream().map(pas -> List.of(transformAnnotations(pas))).toList())); 467 case RuntimeInvisibleTypeAnnotationsAttribute a -> mb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); 468 case RuntimeVisibleAnnotationsAttribute a -> mb.with(RuntimeVisibleAnnotationsAttribute.of(transformAnnotations(a.annotations()))); 469 case RuntimeVisibleParameterAnnotationsAttribute a -> mb.with(RuntimeVisibleParameterAnnotationsAttribute.of(a.parameterAnnotations().stream().map(pas -> List.of(transformAnnotations(pas))).toList())); 470 case RuntimeVisibleTypeAnnotationsAttribute a -> mb.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); 471 case SignatureAttribute a -> mb.with(SignatureAttribute.of(MethodSignature.parseFrom(a.asMethodSignature().signatureString()))); 472 case SyntheticAttribute a -> mb.with(SyntheticAttribute.of()); 473 case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); 474 case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName()); 475 } 476 } 477 }); 478 } 479 case CompilationIDAttribute a -> clb.with(CompilationIDAttribute.of(a.compilationId().stringValue())); 480 case DeprecatedAttribute a -> clb.with(DeprecatedAttribute.of()); 481 case EnclosingMethodAttribute a -> clb.with(EnclosingMethodAttribute.of(a.enclosingClass().asSymbol(), a.enclosingMethodName().map(Utf8Entry::stringValue), a.enclosingMethodTypeSymbol())); 482 case InnerClassesAttribute a -> clb.with(InnerClassesAttribute.of(a.classes().stream().map(ici -> InnerClassInfo.of( 483 ici.innerClass().asSymbol(), 484 ici.outerClass().map(ClassEntry::asSymbol), 485 ici.innerName().map(Utf8Entry::stringValue), 486 ici.flagsMask())).toArray(InnerClassInfo[]::new))); 487 case ModuleAttribute a -> clb.with(ModuleAttribute.of(a.moduleName().asSymbol(), mob -> { 488 mob.moduleFlags(a.moduleFlagsMask()); 489 a.moduleVersion().ifPresent(v -> mob.moduleVersion(v.stringValue())); 490 for (var req : a.requires()) mob.requires(req.requires().asSymbol(), req.requiresFlagsMask(), req.requiresVersion().map(Utf8Entry::stringValue).orElse(null)); 491 for (var exp : a.exports()) mob.exports(exp.exportedPackage().asSymbol(), exp.exportsFlagsMask(), exp.exportsTo().stream().map(ModuleEntry::asSymbol).toArray(ModuleDesc[]::new)); 492 for (var opn : a.opens()) mob.opens(opn.openedPackage().asSymbol(), opn.opensFlagsMask(), opn.opensTo().stream().map(ModuleEntry::asSymbol).toArray(ModuleDesc[]::new)); 493 for (var use : a.uses()) mob.uses(use.asSymbol()); 494 for (var prov : a.provides()) mob.provides(prov.provides().asSymbol(), prov.providesWith().stream().map(ClassEntry::asSymbol).toArray(ClassDesc[]::new)); 495 })); 496 case ModuleHashesAttribute a -> clb.with(ModuleHashesAttribute.of(a.algorithm().stringValue(), 497 a.hashes().stream().map(mh -> ModuleHashInfo.of(mh.moduleName().asSymbol(), mh.hash())).toArray(ModuleHashInfo[]::new))); 498 case ModuleMainClassAttribute a -> clb.with(ModuleMainClassAttribute.of(a.mainClass().asSymbol())); 499 case ModulePackagesAttribute a -> clb.with(ModulePackagesAttribute.ofNames(a.packages().stream().map(PackageEntry::asSymbol).toArray(PackageDesc[]::new))); 500 case ModuleResolutionAttribute a -> clb.with(ModuleResolutionAttribute.of(a.resolutionFlags())); 501 case ModuleTargetAttribute a -> clb.with(ModuleTargetAttribute.of(a.targetPlatform().stringValue())); 502 case NestHostAttribute a -> clb.with(NestHostAttribute.of(a.nestHost().asSymbol())); 503 case NestMembersAttribute a -> clb.with(NestMembersAttribute.ofSymbols(a.nestMembers().stream().map(ClassEntry::asSymbol).toArray(ClassDesc[]::new))); 504 case PermittedSubclassesAttribute a -> clb.with(PermittedSubclassesAttribute.ofSymbols(a.permittedSubclasses().stream().map(ClassEntry::asSymbol).toArray(ClassDesc[]::new))); 505 case RecordAttribute a -> clb.with(RecordAttribute.of(a.components().stream().map(rci -> 506 RecordComponentInfo.of(rci.name().stringValue(), rci.descriptorSymbol(), rci.attributes().stream().mapMulti((rca, rcac) -> { 507 switch(rca) { 508 case RuntimeInvisibleAnnotationsAttribute riaa -> rcac.accept(RuntimeInvisibleAnnotationsAttribute.of(transformAnnotations(riaa.annotations()))); 509 case RuntimeInvisibleTypeAnnotationsAttribute ritaa -> rcac.accept(RuntimeInvisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(ritaa.annotations(), null, null))); 510 case RuntimeVisibleAnnotationsAttribute rvaa -> rcac.accept(RuntimeVisibleAnnotationsAttribute.of(transformAnnotations(rvaa.annotations()))); 511 case RuntimeVisibleTypeAnnotationsAttribute rvtaa -> rcac.accept(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(rvtaa.annotations(), null, null))); 512 case SignatureAttribute sa -> rcac.accept(SignatureAttribute.of(Signature.parseFrom(sa.asTypeSignature().signatureString()))); 513 default -> throw new AssertionError("Unexpected record component attribute: " + rca.attributeName()); 514 }}).toArray(Attribute[]::new))).toArray(RecordComponentInfo[]::new))); 515 case RuntimeInvisibleAnnotationsAttribute a -> clb.with(RuntimeInvisibleAnnotationsAttribute.of(transformAnnotations(a.annotations()))); 516 case RuntimeInvisibleTypeAnnotationsAttribute a -> clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); 517 case RuntimeVisibleAnnotationsAttribute a -> clb.with(RuntimeVisibleAnnotationsAttribute.of(transformAnnotations(a.annotations()))); 518 case RuntimeVisibleTypeAnnotationsAttribute a -> clb.with(RuntimeVisibleTypeAnnotationsAttribute.of(transformTypeAnnotations(a.annotations(), null, null))); 519 case SignatureAttribute a -> clb.with(SignatureAttribute.of(ClassSignature.parseFrom(a.asClassSignature().signatureString()))); 520 case SourceDebugExtensionAttribute a -> clb.with(SourceDebugExtensionAttribute.of(a.contents())); 521 case SourceFileAttribute a -> clb.with(SourceFileAttribute.of(a.sourceFile().stringValue())); 522 case SourceIDAttribute a -> clb.with(SourceIDAttribute.of(a.sourceId().stringValue())); 523 case SyntheticAttribute a -> clb.with(SyntheticAttribute.of()); 524 case CustomAttribute a -> throw new AssertionError("Unexpected custom attribute: " + a.attributeName()); 525 case UnknownAttribute a -> throw new AssertionError("Unexpected unknown attribute: " + a.attributeName()); 526 } 527 } 528 }); 529 } 530 531 static Annotation[] transformAnnotations(List<Annotation> annotations) { 532 return annotations.stream().map(a -> transformAnnotation(a)).toArray(Annotation[]::new); 533 } 534 535 static Annotation transformAnnotation(Annotation a) { 536 return Annotation.of(a.classSymbol(), a.elements().stream().map(ae -> AnnotationElement.of(ae.name().stringValue(), transformAnnotationValue(ae.value()))).toArray(AnnotationElement[]::new)); 537 } 538 539 static AnnotationValue transformAnnotationValue(AnnotationValue av) { 540 return switch (av) { 541 case AnnotationValue.OfAnnotation oa -> AnnotationValue.ofAnnotation(transformAnnotation(oa.annotation())); 542 case AnnotationValue.OfArray oa -> AnnotationValue.ofArray(oa.values().stream().map(v -> transformAnnotationValue(v)).toArray(AnnotationValue[]::new)); 543 case AnnotationValue.OfString v -> AnnotationValue.of(v.stringValue()); 544 case AnnotationValue.OfDouble v -> AnnotationValue.of(v.doubleValue()); 545 case AnnotationValue.OfFloat v -> AnnotationValue.of(v.floatValue()); 546 case AnnotationValue.OfLong v -> AnnotationValue.of(v.longValue()); 547 case AnnotationValue.OfInteger v -> AnnotationValue.of(v.intValue()); 548 case AnnotationValue.OfShort v -> AnnotationValue.of(v.shortValue()); 549 case AnnotationValue.OfCharacter v -> AnnotationValue.of(v.charValue()); 550 case AnnotationValue.OfByte v -> AnnotationValue.of(v.byteValue()); 551 case AnnotationValue.OfBoolean v -> AnnotationValue.of(v.booleanValue()); 552 case AnnotationValue.OfClass oc -> AnnotationValue.of(oc.classSymbol()); 553 case AnnotationValue.OfEnum oe -> AnnotationValue.ofEnum(oe.classSymbol(), oe.constantName().stringValue()); 554 }; 555 } 556 557 static TypeAnnotation[] transformTypeAnnotations(List<TypeAnnotation> annotations, CodeBuilder cob, HashMap<Label, Label> labels) { 558 return annotations.stream().map(ta -> TypeAnnotation.of( 559 transformTargetInfo(ta.targetInfo(), cob, labels), 560 ta.targetPath().stream().map(tpc -> TypeAnnotation.TypePathComponent.of(tpc.typePathKind(), tpc.typeArgumentIndex())).toList(), 561 ta.classSymbol(), 562 ta.elements().stream().map(ae -> AnnotationElement.of(ae.name().stringValue(), transformAnnotationValue(ae.value()))).toList())).toArray(TypeAnnotation[]::new); 563 } 564 565 static TypeAnnotation.TargetInfo transformTargetInfo(TypeAnnotation.TargetInfo ti, CodeBuilder cob, HashMap<Label, Label> labels) { 566 return switch (ti) { 567 case TypeAnnotation.CatchTarget t -> TypeAnnotation.TargetInfo.ofExceptionParameter(t.exceptionTableIndex()); 568 case TypeAnnotation.EmptyTarget t -> TypeAnnotation.TargetInfo.of(t.targetType()); 569 case TypeAnnotation.FormalParameterTarget t -> TypeAnnotation.TargetInfo.ofMethodFormalParameter(t.formalParameterIndex()); 570 case TypeAnnotation.SupertypeTarget t -> TypeAnnotation.TargetInfo.ofClassExtends(t.supertypeIndex()); 571 case TypeAnnotation.ThrowsTarget t -> TypeAnnotation.TargetInfo.ofThrows(t.throwsTargetIndex()); 572 case TypeAnnotation.TypeParameterBoundTarget t -> TypeAnnotation.TargetInfo.ofTypeParameterBound(t.targetType(), t.typeParameterIndex(), t.boundIndex()); 573 case TypeAnnotation.TypeParameterTarget t -> TypeAnnotation.TargetInfo.ofTypeParameter(t.targetType(), t.typeParameterIndex()); 574 case TypeAnnotation.LocalVarTarget t -> TypeAnnotation.TargetInfo.ofVariable(t.targetType(), t.table().stream().map(lvti -> 575 TypeAnnotation.LocalVarTargetInfo.of(labels.computeIfAbsent(lvti.startLabel(), l -> cob.newLabel()), 576 labels.computeIfAbsent(lvti.endLabel(), l -> cob.newLabel()), lvti.index())).toList()); 577 case TypeAnnotation.OffsetTarget t -> TypeAnnotation.TargetInfo.ofOffset(t.targetType(), labels.computeIfAbsent(t.target(), l -> cob.newLabel())); 578 case TypeAnnotation.TypeArgumentTarget t -> TypeAnnotation.TargetInfo.ofTypeArgument(t.targetType(), 579 labels.computeIfAbsent(t.target(), l -> cob.newLabel()), t.typeArgumentIndex()); 580 }; 581 } 582 583 static List<StackMapFrameInfo.VerificationTypeInfo> transformFrameTypeInfos(List<StackMapFrameInfo.VerificationTypeInfo> infos, CodeBuilder cob, HashMap<Label, Label> labels) { 584 return infos.stream().map(ti -> { 585 return switch (ti) { 586 case StackMapFrameInfo.SimpleVerificationTypeInfo i -> i; 587 case StackMapFrameInfo.ObjectVerificationTypeInfo i -> StackMapFrameInfo.ObjectVerificationTypeInfo.of(i.classSymbol()); 588 case StackMapFrameInfo.UninitializedVerificationTypeInfo i -> StackMapFrameInfo.UninitializedVerificationTypeInfo.of(labels.computeIfAbsent(i.newTarget(), l -> cob.newLabel())); 589 }; 590 }).toList(); 591 } 592 }