1 /* 2 * Copyright 2013, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package org.jf.dexlib2.writer; 33 34 import com.google.common.collect.Ordering; 35 import com.google.common.primitives.Ints; 36 import org.jf.dexlib2.Opcode; 37 import org.jf.dexlib2.Opcodes; 38 import org.jf.dexlib2.ReferenceType; 39 import org.jf.dexlib2.iface.instruction.DualReferenceInstruction; 40 import org.jf.dexlib2.iface.instruction.ReferenceInstruction; 41 import org.jf.dexlib2.iface.instruction.SwitchElement; 42 import org.jf.dexlib2.iface.instruction.formats.*; 43 import org.jf.dexlib2.iface.reference.*; 44 import org.jf.util.ExceptionWithContext; 45 46 import javax.annotation.Nonnull; 47 import java.io.IOException; 48 import java.util.Comparator; 49 import java.util.List; 50 51 public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference, 52 FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, 53 ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference, 54 CallSiteKey extends CallSiteReference> { 55 @Nonnull private final Opcodes opcodes; 56 @Nonnull private final DexDataWriter writer; 57 @Nonnull private final StringSection<?, StringRef> stringSection; 58 @Nonnull private final TypeSection<?, ?, TypeRef> typeSection; 59 @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection; 60 @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection; 61 @Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection; 62 @Nonnull private final MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection; 63 @Nonnull private final CallSiteSection<CallSiteKey, ?> callSiteSection; 64 65 @Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, 66 FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, 67 ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference, 68 CallSiteKey extends CallSiteReference> 69 InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, MethodHandleKey, CallSiteKey> makeInstructionWriter( @onnull Opcodes opcodes, @Nonnull DexDataWriter writer, @Nonnull StringSection<?, StringRef> stringSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection)70 makeInstructionWriter( 71 @Nonnull Opcodes opcodes, 72 @Nonnull DexDataWriter writer, 73 @Nonnull StringSection<?, StringRef> stringSection, 74 @Nonnull TypeSection<?, ?, TypeRef> typeSection, 75 @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, 76 @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, 77 @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, 78 @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, 79 @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) { 80 return new InstructionWriter< 81 StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, MethodHandleKey,CallSiteKey>( 82 opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection, 83 methodHandleSection, callSiteSection); 84 } 85 InstructionWriter(@onnull Opcodes opcodes, @Nonnull DexDataWriter writer, @Nonnull StringSection<?, StringRef> stringSection, @Nonnull TypeSection<?, ?, TypeRef> typeSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection)86 InstructionWriter(@Nonnull Opcodes opcodes, 87 @Nonnull DexDataWriter writer, 88 @Nonnull StringSection<?, StringRef> stringSection, 89 @Nonnull TypeSection<?, ?, TypeRef> typeSection, 90 @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, 91 @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, 92 @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, 93 @Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection, 94 @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) { 95 this.opcodes = opcodes; 96 this.writer = writer; 97 this.stringSection = stringSection; 98 this.typeSection = typeSection; 99 this.fieldSection = fieldSection; 100 this.methodSection = methodSection; 101 this.protoSection = protoSection; 102 this.methodHandleSection = methodHandleSection; 103 this.callSiteSection = callSiteSection; 104 } 105 getOpcodeValue(Opcode opcode)106 private short getOpcodeValue(Opcode opcode) { 107 Short value = opcodes.getOpcodeValue(opcode); 108 if (value == null) { 109 throw new ExceptionWithContext("Instruction %s is invalid for api %d", opcode.name, opcodes.api); 110 } 111 return value; 112 } 113 write(@onnull Instruction10t instruction)114 public void write(@Nonnull Instruction10t instruction) { 115 try { 116 writer.write(getOpcodeValue(instruction.getOpcode())); 117 writer.write(instruction.getCodeOffset()); 118 } catch (IOException ex) { 119 throw new RuntimeException(ex); 120 } 121 } 122 write(@onnull Instruction10x instruction)123 public void write(@Nonnull Instruction10x instruction) { 124 try { 125 writer.write(getOpcodeValue(instruction.getOpcode())); 126 writer.write(0); 127 } catch (IOException ex) { 128 throw new RuntimeException(ex); 129 } 130 } 131 write(@onnull Instruction11n instruction)132 public void write(@Nonnull Instruction11n instruction) { 133 try { 134 writer.write(getOpcodeValue(instruction.getOpcode())); 135 writer.write(packNibbles(instruction.getRegisterA(), instruction.getNarrowLiteral())); 136 } catch (IOException ex) { 137 throw new RuntimeException(ex); 138 } 139 } 140 write(@onnull Instruction11x instruction)141 public void write(@Nonnull Instruction11x instruction) { 142 try { 143 writer.write(getOpcodeValue(instruction.getOpcode())); 144 writer.write(instruction.getRegisterA()); 145 } catch (IOException ex) { 146 throw new RuntimeException(ex); 147 } 148 } 149 write(@onnull Instruction12x instruction)150 public void write(@Nonnull Instruction12x instruction) { 151 try { 152 writer.write(getOpcodeValue(instruction.getOpcode())); 153 writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); 154 } catch (IOException ex) { 155 throw new RuntimeException(ex); 156 } 157 } 158 write(@onnull Instruction20bc instruction)159 public void write(@Nonnull Instruction20bc instruction) { 160 try { 161 writer.write(getOpcodeValue(instruction.getOpcode())); 162 writer.write(instruction.getVerificationError()); 163 writer.writeUshort(getReferenceIndex(instruction)); 164 } catch (IOException ex) { 165 throw new RuntimeException(ex); 166 } 167 } 168 write(@onnull Instruction20t instruction)169 public void write(@Nonnull Instruction20t instruction) { 170 try { 171 writer.write(getOpcodeValue(instruction.getOpcode())); 172 writer.write(0); 173 writer.writeShort(instruction.getCodeOffset()); 174 } catch (IOException ex) { 175 throw new RuntimeException(ex); 176 } 177 } 178 write(@onnull Instruction21c instruction)179 public void write(@Nonnull Instruction21c instruction) { 180 try { 181 writer.write(getOpcodeValue(instruction.getOpcode())); 182 writer.write(instruction.getRegisterA()); 183 writer.writeUshort(getReferenceIndex(instruction)); 184 } catch (IOException ex) { 185 throw new RuntimeException(ex); 186 } 187 } 188 write(@onnull Instruction21ih instruction)189 public void write(@Nonnull Instruction21ih instruction) { 190 try { 191 writer.write(getOpcodeValue(instruction.getOpcode())); 192 writer.write(instruction.getRegisterA()); 193 writer.writeShort(instruction.getHatLiteral()); 194 } catch (IOException ex) { 195 throw new RuntimeException(ex); 196 } 197 } 198 write(@onnull Instruction21lh instruction)199 public void write(@Nonnull Instruction21lh instruction) { 200 try { 201 writer.write(getOpcodeValue(instruction.getOpcode())); 202 writer.write(instruction.getRegisterA()); 203 writer.writeShort(instruction.getHatLiteral()); 204 } catch (IOException ex) { 205 throw new RuntimeException(ex); 206 } 207 } 208 write(@onnull Instruction21s instruction)209 public void write(@Nonnull Instruction21s instruction) { 210 try { 211 writer.write(getOpcodeValue(instruction.getOpcode())); 212 writer.write(instruction.getRegisterA()); 213 writer.writeShort(instruction.getNarrowLiteral()); 214 } catch (IOException ex) { 215 throw new RuntimeException(ex); 216 } 217 } 218 write(@onnull Instruction21t instruction)219 public void write(@Nonnull Instruction21t instruction) { 220 try { 221 writer.write(getOpcodeValue(instruction.getOpcode())); 222 writer.write(instruction.getRegisterA()); 223 writer.writeShort(instruction.getCodeOffset()); 224 } catch (IOException ex) { 225 throw new RuntimeException(ex); 226 } 227 } 228 write(@onnull Instruction22b instruction)229 public void write(@Nonnull Instruction22b instruction) { 230 try { 231 writer.write(getOpcodeValue(instruction.getOpcode())); 232 writer.write(instruction.getRegisterA()); 233 writer.write(instruction.getRegisterB()); 234 writer.write(instruction.getNarrowLiteral()); 235 } catch (IOException ex) { 236 throw new RuntimeException(ex); 237 } 238 } 239 write(@onnull Instruction22c instruction)240 public void write(@Nonnull Instruction22c instruction) { 241 try { 242 writer.write(getOpcodeValue(instruction.getOpcode())); 243 writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); 244 writer.writeUshort(getReferenceIndex(instruction)); 245 } catch (IOException ex) { 246 throw new RuntimeException(ex); 247 } 248 } 249 write(@onnull Instruction22cs instruction)250 public void write(@Nonnull Instruction22cs instruction) { 251 try { 252 writer.write(getOpcodeValue(instruction.getOpcode())); 253 writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); 254 writer.writeUshort(instruction.getFieldOffset()); 255 } catch (IOException ex) { 256 throw new RuntimeException(ex); 257 } 258 } 259 write(@onnull Instruction22s instruction)260 public void write(@Nonnull Instruction22s instruction) { 261 try { 262 writer.write(getOpcodeValue(instruction.getOpcode())); 263 writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); 264 writer.writeShort(instruction.getNarrowLiteral()); 265 } catch (IOException ex) { 266 throw new RuntimeException(ex); 267 } 268 } 269 write(@onnull Instruction22t instruction)270 public void write(@Nonnull Instruction22t instruction) { 271 try { 272 writer.write(getOpcodeValue(instruction.getOpcode())); 273 writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); 274 writer.writeShort(instruction.getCodeOffset()); 275 } catch (IOException ex) { 276 throw new RuntimeException(ex); 277 } 278 } 279 write(@onnull Instruction22x instruction)280 public void write(@Nonnull Instruction22x instruction) { 281 try { 282 writer.write(getOpcodeValue(instruction.getOpcode())); 283 writer.write(instruction.getRegisterA()); 284 writer.writeUshort(instruction.getRegisterB()); 285 } catch (IOException ex) { 286 throw new RuntimeException(ex); 287 } 288 } 289 write(@onnull Instruction23x instruction)290 public void write(@Nonnull Instruction23x instruction) { 291 try { 292 writer.write(getOpcodeValue(instruction.getOpcode())); 293 writer.write(instruction.getRegisterA()); 294 writer.write(instruction.getRegisterB()); 295 writer.write(instruction.getRegisterC()); 296 } catch (IOException ex) { 297 throw new RuntimeException(ex); 298 } 299 } 300 write(@onnull Instruction30t instruction)301 public void write(@Nonnull Instruction30t instruction) { 302 try { 303 writer.write(getOpcodeValue(instruction.getOpcode())); 304 writer.write(0); 305 writer.writeInt(instruction.getCodeOffset()); 306 } catch (IOException ex) { 307 throw new RuntimeException(ex); 308 } 309 } 310 write(@onnull Instruction31c instruction)311 public void write(@Nonnull Instruction31c instruction) { 312 try { 313 writer.write(getOpcodeValue(instruction.getOpcode())); 314 writer.write(instruction.getRegisterA()); 315 writer.writeInt(getReferenceIndex(instruction)); 316 } catch (IOException ex) { 317 throw new RuntimeException(ex); 318 } 319 } 320 write(@onnull Instruction31i instruction)321 public void write(@Nonnull Instruction31i instruction) { 322 try { 323 writer.write(getOpcodeValue(instruction.getOpcode())); 324 writer.write(instruction.getRegisterA()); 325 writer.writeInt(instruction.getNarrowLiteral()); 326 } catch (IOException ex) { 327 throw new RuntimeException(ex); 328 } 329 } 330 write(@onnull Instruction31t instruction)331 public void write(@Nonnull Instruction31t instruction) { 332 try { 333 writer.write(getOpcodeValue(instruction.getOpcode())); 334 writer.write(instruction.getRegisterA()); 335 writer.writeInt(instruction.getCodeOffset()); 336 } catch (IOException ex) { 337 throw new RuntimeException(ex); 338 } 339 } 340 write(@onnull Instruction32x instruction)341 public void write(@Nonnull Instruction32x instruction) { 342 try { 343 writer.write(getOpcodeValue(instruction.getOpcode())); 344 writer.write(0); 345 writer.writeUshort(instruction.getRegisterA()); 346 writer.writeUshort(instruction.getRegisterB()); 347 } catch (IOException ex) { 348 throw new RuntimeException(ex); 349 } 350 } 351 write(@onnull Instruction35c instruction)352 public void write(@Nonnull Instruction35c instruction) { 353 try { 354 writer.write(getOpcodeValue(instruction.getOpcode())); 355 writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount())); 356 writer.writeUshort(getReferenceIndex(instruction)); 357 writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD())); 358 writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF())); 359 } catch (IOException ex) { 360 throw new RuntimeException(ex); 361 } 362 } 363 write(@onnull Instruction35mi instruction)364 public void write(@Nonnull Instruction35mi instruction) { 365 try { 366 writer.write(getOpcodeValue(instruction.getOpcode())); 367 writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount())); 368 writer.writeUshort(instruction.getInlineIndex()); 369 writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD())); 370 writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF())); 371 } catch (IOException ex) { 372 throw new RuntimeException(ex); 373 } 374 } 375 write(@onnull Instruction35ms instruction)376 public void write(@Nonnull Instruction35ms instruction) { 377 try { 378 writer.write(getOpcodeValue(instruction.getOpcode())); 379 writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount())); 380 writer.writeUshort(instruction.getVtableIndex()); 381 writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD())); 382 writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF())); 383 } catch (IOException ex) { 384 throw new RuntimeException(ex); 385 } 386 } 387 write(@onnull Instruction3rc instruction)388 public void write(@Nonnull Instruction3rc instruction) { 389 try { 390 writer.write(getOpcodeValue(instruction.getOpcode())); 391 writer.write(instruction.getRegisterCount()); 392 writer.writeUshort(getReferenceIndex(instruction)); 393 writer.writeUshort(instruction.getStartRegister()); 394 } catch (IOException ex) { 395 throw new RuntimeException(ex); 396 } 397 } 398 write(@onnull Instruction3rmi instruction)399 public void write(@Nonnull Instruction3rmi instruction) { 400 try { 401 writer.write(getOpcodeValue(instruction.getOpcode())); 402 writer.write(instruction.getRegisterCount()); 403 writer.writeUshort(instruction.getInlineIndex()); 404 writer.writeUshort(instruction.getStartRegister()); 405 } catch (IOException ex) { 406 throw new RuntimeException(ex); 407 } 408 } 409 410 write(@onnull Instruction3rms instruction)411 public void write(@Nonnull Instruction3rms instruction) { 412 try { 413 writer.write(getOpcodeValue(instruction.getOpcode())); 414 writer.write(instruction.getRegisterCount()); 415 writer.writeUshort(instruction.getVtableIndex()); 416 writer.writeUshort(instruction.getStartRegister()); 417 } catch (IOException ex) { 418 throw new RuntimeException(ex); 419 } 420 } 421 write(@onnull Instruction45cc instruction)422 public void write(@Nonnull Instruction45cc instruction) { 423 try { 424 writer.write(getOpcodeValue(instruction.getOpcode())); 425 writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount())); 426 writer.writeUshort(getReferenceIndex(instruction)); 427 writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD())); 428 writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF())); 429 writer.writeUshort(getReference2Index(instruction)); 430 } catch (IOException ex) { 431 throw new RuntimeException(ex); 432 } 433 } 434 write(@onnull Instruction4rcc instruction)435 public void write(@Nonnull Instruction4rcc instruction) { 436 try { 437 writer.write(getOpcodeValue(instruction.getOpcode())); 438 writer.write(instruction.getRegisterCount()); 439 writer.writeUshort(getReferenceIndex(instruction)); 440 writer.writeUshort(instruction.getStartRegister()); 441 writer.writeUshort(getReference2Index(instruction)); 442 } catch (IOException ex) { 443 throw new RuntimeException(ex); 444 } 445 } 446 write(@onnull Instruction51l instruction)447 public void write(@Nonnull Instruction51l instruction) { 448 try { 449 writer.write(getOpcodeValue(instruction.getOpcode())); 450 writer.write(instruction.getRegisterA()); 451 writer.writeLong(instruction.getWideLiteral()); 452 } catch (IOException ex) { 453 throw new RuntimeException(ex); 454 } 455 } 456 write(@onnull ArrayPayload instruction)457 public void write(@Nonnull ArrayPayload instruction) { 458 try { 459 writer.writeUshort(getOpcodeValue(instruction.getOpcode())); 460 writer.writeUshort(instruction.getElementWidth()); 461 List<Number> elements = instruction.getArrayElements(); 462 writer.writeInt(elements.size()); 463 switch (instruction.getElementWidth()) { 464 case 1: 465 for (Number element: elements) { 466 writer.write(element.byteValue()); 467 } 468 break; 469 case 2: 470 for (Number element: elements) { 471 writer.writeShort(element.shortValue()); 472 } 473 break; 474 case 4: 475 for (Number element: elements) { 476 writer.writeInt(element.intValue()); 477 } 478 break; 479 case 8: 480 for (Number element: elements) { 481 writer.writeLong(element.longValue()); 482 } 483 break; 484 } 485 if ((writer.getPosition() & 1) != 0) { 486 writer.write(0); 487 } 488 } catch (IOException ex) { 489 throw new RuntimeException(ex); 490 } 491 } 492 write(@onnull SparseSwitchPayload instruction)493 public void write(@Nonnull SparseSwitchPayload instruction) { 494 try { 495 writer.writeUbyte(0); 496 writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8); 497 List<? extends SwitchElement> elements = Ordering.from(switchElementComparator).immutableSortedCopy( 498 instruction.getSwitchElements()); 499 writer.writeUshort(elements.size()); 500 for (SwitchElement element: elements) { 501 writer.writeInt(element.getKey()); 502 } 503 for (SwitchElement element: elements) { 504 writer.writeInt(element.getOffset()); 505 } 506 } catch (IOException ex) { 507 throw new RuntimeException(ex); 508 } 509 } 510 511 private final Comparator<SwitchElement> switchElementComparator = new Comparator<SwitchElement>() { 512 @Override public int compare(SwitchElement element1, SwitchElement element2) { 513 return Ints.compare(element1.getKey(), element2.getKey()); 514 } 515 }; 516 write(@onnull PackedSwitchPayload instruction)517 public void write(@Nonnull PackedSwitchPayload instruction) { 518 try { 519 writer.writeUbyte(0); 520 writer.writeUbyte(getOpcodeValue(instruction.getOpcode()) >> 8); 521 List<? extends SwitchElement> elements = instruction.getSwitchElements(); 522 writer.writeUshort(elements.size()); 523 if (elements.size() == 0) { 524 writer.writeInt(0); 525 } else { 526 writer.writeInt(elements.get(0).getKey()); 527 for (SwitchElement element: elements) { 528 writer.writeInt(element.getOffset()); 529 } 530 } 531 } catch (IOException ex) { 532 throw new RuntimeException(ex); 533 } 534 } 535 packNibbles(int a, int b)536 private static int packNibbles(int a, int b) { 537 return (b << 4) | a; 538 } 539 getReferenceIndex(ReferenceInstruction referenceInstruction)540 private int getReferenceIndex(ReferenceInstruction referenceInstruction) { 541 return getReferenceIndex(referenceInstruction.getReferenceType(), 542 referenceInstruction.getReference()); 543 } 544 getReference2Index(DualReferenceInstruction referenceInstruction)545 private int getReference2Index(DualReferenceInstruction referenceInstruction) { 546 return getReferenceIndex(referenceInstruction.getReferenceType2(), 547 referenceInstruction.getReference2()); 548 } 549 getReferenceIndex(int referenceType, Reference reference)550 private int getReferenceIndex(int referenceType, Reference reference) { 551 switch (referenceType) { 552 case ReferenceType.FIELD: 553 return fieldSection.getItemIndex((FieldRefKey) reference); 554 case ReferenceType.METHOD: 555 return methodSection.getItemIndex((MethodRefKey) reference); 556 case ReferenceType.STRING: 557 return stringSection.getItemIndex((StringRef) reference); 558 case ReferenceType.TYPE: 559 return typeSection.getItemIndex((TypeRef) reference); 560 case ReferenceType.METHOD_PROTO: 561 return protoSection.getItemIndex((ProtoRefKey) reference); 562 case ReferenceType.METHOD_HANDLE: 563 return methodHandleSection.getItemIndex((MethodHandleKey) reference); 564 case ReferenceType.CALL_SITE: 565 return callSiteSection.getItemIndex((CallSiteKey) reference); 566 default: 567 throw new ExceptionWithContext("Unknown reference type: %d", referenceType); 568 } 569 } 570 } 571