• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 package com.android.tools.r8.graph;
5 
6 import com.android.tools.r8.dex.DexOutputBuffer;
7 import com.android.tools.r8.dex.FileWriter;
8 import com.android.tools.r8.dex.IndexedItemCollection;
9 import com.android.tools.r8.dex.MixedSectionCollection;
10 import com.android.tools.r8.errors.Unreachable;
11 import com.android.tools.r8.ir.code.ConstNumber;
12 import com.android.tools.r8.ir.code.ConstType;
13 import com.android.tools.r8.ir.code.Instruction;
14 import com.android.tools.r8.ir.code.Value;
15 import com.android.tools.r8.utils.EncodedValueUtils;
16 import java.util.Arrays;
17 
18 public abstract class DexValue extends DexItem {
19 
20   public static final byte VALUE_BYTE = 0x00;
21   public static final byte VALUE_SHORT = 0x02;
22   public static final byte VALUE_CHAR = 0x03;
23   public static final byte VALUE_INT = 0x04;
24   public static final byte VALUE_LONG = 0x06;
25   public static final byte VALUE_FLOAT = 0x10;
26   public static final byte VALUE_DOUBLE = 0x11;
27   public static final byte VALUE_METHOD_TYPE = 0x15;
28   public static final byte VALUE_METHOD_HANDLE = 0x16;
29   public static final byte VALUE_STRING = 0x17;
30   public static final byte VALUE_TYPE = 0x18;
31   public static final byte VALUE_FIELD = 0x19;
32   public static final byte VALUE_METHOD = 0x1a;
33   public static final byte VALUE_ENUM = 0x1b;
34   public static final byte VALUE_ARRAY = 0x1c;
35   public static final byte VALUE_ANNOTATION = 0x1d;
36   public static final byte VALUE_NULL = 0x1e;
37   public static final byte VALUE_BOOLEAN = 0x1f;
38 
writeHeader(byte type, int arg, DexOutputBuffer dest)39   private static void writeHeader(byte type, int arg, DexOutputBuffer dest) {
40     dest.putByte((byte) ((arg << 5) | type));
41   }
42 
43   @Override
collectMixedSectionItems(MixedSectionCollection mixedItems)44   void collectMixedSectionItems(MixedSectionCollection mixedItems) {
45     // Should never be visited.
46     assert false;
47   }
48 
sort()49   public abstract void sort();
50 
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)51   public abstract void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping);
52 
53   @Override
hashCode()54   public abstract int hashCode();
55 
56   @Override
equals(Object other)57   public abstract boolean equals(Object other);
58 
59   @Override
toString()60   public abstract String toString();
61 
defaultForType(DexType type, DexItemFactory factory)62   public static DexValue defaultForType(DexType type, DexItemFactory factory) {
63     if (type == factory.booleanType) {
64       return DexValueBoolean.DEFAULT;
65     }
66     if (type == factory.byteType) {
67       return DexValueByte.DEFAULT;
68     }
69     if (type == factory.charType) {
70       return DexValueChar.DEFAULT;
71     }
72     if (type == factory.shortType) {
73       return DexValueShort.DEFAULT;
74     }
75     if (type == factory.intType) {
76       return DexValueInt.DEFAULT;
77     }
78     if (type == factory.longType) {
79       return DexValueLong.DEFAULT;
80     }
81     if (type == factory.floatType) {
82       return DexValueFloat.DEFAULT;
83     }
84     if (type == factory.doubleType) {
85       return DexValueDouble.DEFAULT;
86     }
87     if (type.isArrayType() || type.isClassType()) {
88       return DexValueNull.NULL;
89     }
90     throw new Unreachable("No default value for unexpected type " + type);
91   }
92 
93   // Returns a const instruction for the non default value.
asConstInstruction(boolean hasClassInitializer, Value dest)94   public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
95     return null;
96   }
97 
isDefault(DexType type, DexItemFactory factory)98   public boolean isDefault(DexType type, DexItemFactory factory) {
99     return this == defaultForType(type, factory);
100   }
101 
102   static private abstract class SimpleDexValue extends DexValue {
103 
104     @Override
collectIndexedItems(IndexedItemCollection indexedItems)105     public void collectIndexedItems(IndexedItemCollection indexedItems) {
106       // Intentionally left empty
107     }
108 
109     @Override
sort()110     public void sort() {
111       // Intentionally empty
112     }
113 
writeIntegerTo(byte type, long value, int expected, DexOutputBuffer dest)114     protected static void writeIntegerTo(byte type, long value, int expected,
115         DexOutputBuffer dest) {
116       // Leave space for header.
117       dest.forward(1);
118       int length = dest.putSignedEncodedValue(value, expected);
119       dest.rewind(length + 1);
120       writeHeader(type, length - 1, dest);
121       dest.forward(length);
122     }
123 
124   }
125 
126   static public class DexValueByte extends SimpleDexValue {
127 
128     public static final DexValueByte DEFAULT = new DexValueByte((byte) 0);
129 
130     final byte value;
131 
DexValueByte(byte value)132     private DexValueByte(byte value) {
133       this.value = value;
134     }
135 
create(byte value)136     public static DexValueByte create(byte value) {
137       return value == DEFAULT.value ? DEFAULT : new DexValueByte(value);
138     }
139 
140     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)141     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
142       writeHeader(VALUE_BYTE, 0, dest);
143       dest.putSignedEncodedValue(value, 1);
144     }
145 
146     @Override
hashCode()147     public int hashCode() {
148       return value * 3;
149     }
150 
151     @Override
equals(Object other)152     public boolean equals(Object other) {
153       if (other == this) {
154         return true;
155       }
156       return other instanceof DexValueByte && value == ((DexValueByte) other).value;
157     }
158 
159     @Override
toString()160     public String toString() {
161       return "Byte " + value;
162     }
163 
164     @Override
asConstInstruction(boolean hasClassInitializer, Value dest)165     public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
166       return (this == DEFAULT && hasClassInitializer)
167           ? null
168           : new ConstNumber(ConstType.INT, dest, value);
169     }
170   }
171 
172   static public class DexValueShort extends SimpleDexValue {
173 
174     public static final DexValueShort DEFAULT = new DexValueShort((short) 0);
175     final short value;
176 
DexValueShort(short value)177     private DexValueShort(short value) {
178       this.value = value;
179     }
180 
create(short value)181     public static DexValueShort create(short value) {
182       return value == DEFAULT.value ? DEFAULT : new DexValueShort(value);
183     }
184 
185     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)186     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
187       writeIntegerTo(VALUE_SHORT, value, Short.BYTES, dest);
188     }
189 
190     @Override
hashCode()191     public int hashCode() {
192       return value * 7;
193     }
194 
195     @Override
equals(Object other)196     public boolean equals(Object other) {
197       if (other == this) {
198         return true;
199       }
200       return other instanceof DexValueShort && value == ((DexValueShort) other).value;
201     }
202 
203     @Override
toString()204     public String toString() {
205       return "Short " + value;
206     }
207 
208     @Override
asConstInstruction(boolean hasClassInitializer, Value dest)209     public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
210       return (this == DEFAULT && hasClassInitializer)
211           ? null
212           : new ConstNumber(ConstType.INT, dest, value);
213     }
214   }
215 
216   static public class DexValueChar extends SimpleDexValue {
217 
218     public static final DexValueChar DEFAULT = new DexValueChar((char) 0);
219     final char value;
220 
DexValueChar(char value)221     private DexValueChar(char value) {
222       this.value = value;
223     }
224 
create(char value)225     public static DexValueChar create(char value) {
226       return value == DEFAULT.value ? DEFAULT : new DexValueChar(value);
227     }
228 
229     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)230     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
231       dest.forward(1);
232       int length = dest.putUnsignedEncodedValue(value, 2);
233       dest.rewind(length + 1);
234       writeHeader(VALUE_CHAR, length - 1, dest);
235       dest.forward(length);
236     }
237 
238     @Override
hashCode()239     public int hashCode() {
240       return value * 5;
241     }
242 
243     @Override
equals(Object other)244     public boolean equals(Object other) {
245       if (other == this) {
246         return true;
247       }
248       return other instanceof DexValueChar && value == ((DexValueChar) other).value;
249     }
250 
251     @Override
toString()252     public String toString() {
253       return "Char " + value;
254     }
255 
256     @Override
asConstInstruction(boolean hasClassInitializer, Value dest)257     public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
258       return (this == DEFAULT && hasClassInitializer)
259           ? null
260           : new ConstNumber(ConstType.INT, dest, value);
261     }
262   }
263 
264   static public class DexValueInt extends SimpleDexValue {
265 
266     public static final DexValueInt DEFAULT = new DexValueInt(0);
267     public final int value;
268 
DexValueInt(int value)269     private DexValueInt(int value) {
270       this.value = value;
271     }
272 
create(int value)273     public static DexValueInt create(int value) {
274       return value == DEFAULT.value ? DEFAULT : new DexValueInt(value);
275     }
276 
277     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)278     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
279       writeIntegerTo(VALUE_INT, value, Integer.BYTES, dest);
280     }
281 
282     @Override
hashCode()283     public int hashCode() {
284       return value * 11;
285     }
286 
287     @Override
equals(Object other)288     public boolean equals(Object other) {
289       if (other == this) {
290         return true;
291       }
292       return other instanceof DexValueInt && value == ((DexValueInt) other).value;
293     }
294 
295     @Override
toString()296     public String toString() {
297       return "Int " + value;
298     }
299 
300     @Override
asConstInstruction(boolean hasClassInitializer, Value dest)301     public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
302       return (this == DEFAULT && hasClassInitializer)
303           ? null
304           : new ConstNumber(ConstType.INT, dest, value);
305     }
306   }
307 
308   static public class DexValueLong extends SimpleDexValue {
309 
310     public static final DexValueLong DEFAULT = new DexValueLong(0);
311     final long value;
312 
DexValueLong(long value)313     private DexValueLong(long value) {
314       this.value = value;
315     }
316 
create(long value)317     public static DexValueLong create(long value) {
318       return value == DEFAULT.value ? DEFAULT : new DexValueLong(value);
319     }
320 
321     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)322     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
323       writeIntegerTo(VALUE_LONG, value, Long.BYTES, dest);
324     }
325 
326     @Override
hashCode()327     public int hashCode() {
328       return (int) value * 13;
329     }
330 
331     @Override
equals(Object other)332     public boolean equals(Object other) {
333       if (other == this) {
334         return true;
335       }
336       return other instanceof DexValueLong && value == ((DexValueLong) other).value;
337     }
338 
339     @Override
toString()340     public String toString() {
341       return "Long " + value;
342     }
343 
344     @Override
asConstInstruction(boolean hasClassInitializer, Value dest)345     public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
346       return (this == DEFAULT && hasClassInitializer)
347           ? null
348           : new ConstNumber(ConstType.LONG, dest, value);
349     }
350   }
351 
352   static public class DexValueFloat extends SimpleDexValue {
353 
354     public static final DexValueFloat DEFAULT = new DexValueFloat(0);
355     final float value;
356 
DexValueFloat(float value)357     private DexValueFloat(float value) {
358       this.value = value;
359     }
360 
create(float value)361     public static DexValueFloat create(float value) {
362       return Float.compare(value, DEFAULT.value) == 0 ? DEFAULT : new DexValueFloat(value);
363     }
364 
365     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)366     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
367       dest.forward(1);
368       int length = EncodedValueUtils.putFloat(dest, value);
369       dest.rewind(length + 1);
370       writeHeader(VALUE_FLOAT, length - 1, dest);
371       dest.forward(length);
372     }
373 
374     @Override
hashCode()375     public int hashCode() {
376       return (int) value * 19;
377     }
378 
379     @Override
equals(Object other)380     public boolean equals(Object other) {
381       if (other == this) {
382         return true;
383       }
384       return (other instanceof DexValueFloat) &&
385           (Float.compare(value, ((DexValueFloat) other).value) == 0);
386     }
387 
388     @Override
toString()389     public String toString() {
390       return "Float " + value;
391     }
392 
393   }
394 
395   static public class DexValueDouble extends SimpleDexValue {
396 
397     public static final DexValueDouble DEFAULT = new DexValueDouble(0);
398 
399     final double value;
400 
DexValueDouble(double value)401     private DexValueDouble(double value) {
402       this.value = value;
403     }
404 
create(double value)405     public static DexValueDouble create(double value) {
406       return Double.compare(value, DEFAULT.value) == 0 ? DEFAULT : new DexValueDouble(value);
407     }
408 
409     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)410     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
411       dest.forward(1);
412       int length = EncodedValueUtils.putDouble(dest, value);
413       dest.rewind(length + 1);
414       writeHeader(VALUE_DOUBLE, length - 1, dest);
415       dest.forward(length);
416     }
417 
418     @Override
hashCode()419     public int hashCode() {
420       return (int) value * 29;
421     }
422 
423     @Override
equals(Object other)424     public boolean equals(Object other) {
425       if (other == this) {
426         return true;
427       }
428       return (other instanceof DexValueDouble) &&
429           (Double.compare(value, ((DexValueDouble) other).value) == 0);
430     }
431 
432     @Override
toString()433     public String toString() {
434       return "Double " + value;
435     }
436   }
437 
438   static private abstract class NestedDexValue<T extends IndexedDexItem> extends DexValue {
439 
440     public final T value;
441 
NestedDexValue(T value)442     private NestedDexValue(T value) {
443       this.value = value;
444     }
445 
getValueKind()446     protected abstract byte getValueKind();
447 
448     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)449     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
450       int offset = value.getOffset(mapping);
451       dest.forward(1);
452       int length = dest.putUnsignedEncodedValue(offset, 4);
453       dest.rewind(length + 1);
454       writeHeader(getValueKind(), length - 1, dest);
455       dest.forward(length);
456     }
457 
458     @Override
collectIndexedItems(IndexedItemCollection indexedItems)459     public void collectIndexedItems(IndexedItemCollection indexedItems) {
460       value.collectIndexedItems(indexedItems);
461     }
462 
463     @Override
sort()464     public void sort() {
465       // Intentionally empty.
466     }
467 
468     @Override
hashCode()469     public int hashCode() {
470       return value.hashCode() * 7 + getValueKind();
471     }
472 
473     @Override
equals(Object other)474     public boolean equals(Object other) {
475       if (other == this) {
476         return true;
477       }
478       if (other instanceof NestedDexValue) {
479         NestedDexValue<?> that = (NestedDexValue<?>) other;
480         return that.getValueKind() == getValueKind() && that.value.equals(value);
481       }
482       return false;
483     }
484 
485     @Override
toString()486     public String toString() {
487       return "Item " + getValueKind() + " " + value;
488     }
489   }
490 
491   static public class DexValueString extends NestedDexValue<DexString> {
492 
DexValueString(DexString value)493     public DexValueString(DexString value) {
494       super(value);
495     }
496 
497     @Override
getValueKind()498     protected byte getValueKind() {
499       return VALUE_STRING;
500     }
501   }
502 
503   static public class DexValueType extends NestedDexValue<DexType> {
504 
DexValueType(DexType value)505     public DexValueType(DexType value) {
506       super(value);
507     }
508 
509     @Override
getValueKind()510     protected byte getValueKind() {
511       return VALUE_TYPE;
512     }
513 
514     @Override
collectIndexedItems(IndexedItemCollection indexedItems)515     public void collectIndexedItems(IndexedItemCollection indexedItems) {
516       value.collectIndexedItems(indexedItems);
517     }
518   }
519 
520   static public class DexValueField extends NestedDexValue<DexField> {
521 
DexValueField(DexField value)522     public DexValueField(DexField value) {
523       super(value);
524     }
525 
526     @Override
getValueKind()527     protected byte getValueKind() {
528       return VALUE_FIELD;
529     }
530 
531     @Override
collectIndexedItems(IndexedItemCollection indexedItems)532     public void collectIndexedItems(IndexedItemCollection indexedItems) {
533       value.collectIndexedItems(indexedItems);
534     }
535   }
536 
537   static public class DexValueMethod extends NestedDexValue<DexMethod> {
538 
DexValueMethod(DexMethod value)539     public DexValueMethod(DexMethod value) {
540       super(value);
541     }
542 
543     @Override
getValueKind()544     protected byte getValueKind() {
545       return VALUE_METHOD;
546     }
547 
548     @Override
collectIndexedItems(IndexedItemCollection indexedItems)549     public void collectIndexedItems(IndexedItemCollection indexedItems) {
550       value.collectIndexedItems(indexedItems);
551     }
552   }
553 
554   static public class DexValueEnum extends NestedDexValue<DexField> {
555 
DexValueEnum(DexField value)556     public DexValueEnum(DexField value) {
557       super(value);
558     }
559 
560     @Override
getValueKind()561     protected byte getValueKind() {
562       return VALUE_ENUM;
563     }
564 
565     @Override
collectIndexedItems(IndexedItemCollection indexedItems)566     public void collectIndexedItems(IndexedItemCollection indexedItems) {
567       value.collectIndexedItems(indexedItems);
568     }
569   }
570 
571   static public class DexValueMethodType extends NestedDexValue<DexProto> {
572 
DexValueMethodType(DexProto value)573     public DexValueMethodType(DexProto value) {
574       super(value);
575     }
576 
577     @Override
getValueKind()578     protected byte getValueKind() {
579       return VALUE_METHOD_TYPE;
580     }
581 
582     @Override
collectIndexedItems(IndexedItemCollection indexedItems)583     public void collectIndexedItems(IndexedItemCollection indexedItems) {
584       value.collectIndexedItems(indexedItems);
585     }
586   }
587 
588   static public class DexValueArray extends DexValue {
589 
590     final DexValue[] values;
591 
DexValueArray(DexValue[] values)592     public DexValueArray(DexValue[] values) {
593       this.values = values;
594     }
595 
596     @Override
collectIndexedItems(IndexedItemCollection indexedItems)597     public void collectIndexedItems(IndexedItemCollection indexedItems) {
598       collectAll(indexedItems, values);
599     }
600 
601     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)602     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
603       writeHeader(VALUE_ARRAY, 0, dest);
604       dest.putUleb128(values.length);
605       for (DexValue value : values) {
606         value.writeTo(dest, mapping);
607       }
608     }
609 
610     @Override
sort()611     public void sort() {
612       for (DexValue value : values) {
613         value.sort();
614       }
615     }
616 
617     @Override
hashCode()618     public int hashCode() {
619       return Arrays.hashCode(values);
620     }
621 
622     @Override
equals(Object other)623     public boolean equals(Object other) {
624       if (other == this) {
625         return true;
626       }
627       if (other instanceof DexValueArray) {
628         DexValueArray that = (DexValueArray) other;
629         return Arrays.equals(that.values, values);
630       }
631       return false;
632     }
633 
634     @Override
toString()635     public String toString() {
636       return "Array " + Arrays.toString(values);
637     }
638   }
639 
640   static public class DexValueAnnotation extends DexValue {
641 
642     public final DexEncodedAnnotation value;
643 
DexValueAnnotation(DexEncodedAnnotation value)644     public DexValueAnnotation(DexEncodedAnnotation value) {
645       this.value = value;
646     }
647 
648     @Override
collectIndexedItems(IndexedItemCollection indexedItems)649     public void collectIndexedItems(IndexedItemCollection indexedItems) {
650       value.collectIndexedItems(indexedItems);
651     }
652 
653     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)654     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
655       writeHeader(VALUE_ANNOTATION, 0, dest);
656       FileWriter.writeEncodedAnnotation(value, dest, mapping);
657     }
658 
659     @Override
sort()660     public void sort() {
661       value.sort();
662     }
663 
664     @Override
hashCode()665     public int hashCode() {
666       return value.hashCode() * 7;
667     }
668 
669     @Override
equals(Object other)670     public boolean equals(Object other) {
671       if (other == this) {
672         return true;
673       }
674       if (other instanceof DexValueAnnotation) {
675         DexValueAnnotation that = (DexValueAnnotation) other;
676         return that.value.equals(value);
677       }
678       return false;
679     }
680 
681     @Override
toString()682     public String toString() {
683       return "Annotation " + value;
684     }
685   }
686 
687   static public class DexValueNull extends SimpleDexValue {
688 
689     public static final DexValue NULL = new DexValueNull();
690 
691     // See DexValueNull.NULL
DexValueNull()692     private DexValueNull() {
693     }
694 
695     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)696     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
697       writeHeader(VALUE_NULL, 0, dest);
698     }
699 
700     @Override
hashCode()701     public int hashCode() {
702       return 42;
703     }
704 
705     @Override
equals(Object other)706     public boolean equals(Object other) {
707       if (other == this) {
708         return true;
709       }
710       return (other instanceof DexValueNull);
711     }
712 
713     @Override
toString()714     public String toString() {
715       return "Null";
716     }
717   }
718 
719   static public class DexValueBoolean extends SimpleDexValue {
720 
721     private static final DexValueBoolean TRUE = new DexValueBoolean(true);
722     private static final DexValueBoolean FALSE = new DexValueBoolean(false);
723     // Use a separate instance for the default value to distinguish it from an explicit false value.
724     private static final DexValueBoolean DEFAULT = new DexValueBoolean(false);
725 
726     final boolean value;
727 
DexValueBoolean(boolean value)728     private DexValueBoolean(boolean value) {
729       this.value = value;
730     }
731 
create(boolean value)732     public static DexValueBoolean create(boolean value) {
733       return value ? TRUE : FALSE;
734     }
735 
736     @Override
writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping)737     public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
738       writeHeader(VALUE_BOOLEAN, value ? 1 : 0, dest);
739     }
740 
741     @Override
hashCode()742     public int hashCode() {
743       return value ? 1234 : 4321;
744     }
745 
746     @Override
equals(Object other)747     public boolean equals(Object other) {
748       if (other == this) {
749         return true;
750       }
751       return (other instanceof DexValueBoolean) && ((DexValueBoolean) other).value == value;
752     }
753 
754     @Override
toString()755     public String toString() {
756       return value ? "True" : "False";
757     }
758 
759     @Override
asConstInstruction(boolean hasClassInitializer, Value dest)760     public Instruction asConstInstruction(boolean hasClassInitializer, Value dest) {
761       return (this == DEFAULT && hasClassInitializer)
762           ? null
763           : new ConstNumber(ConstType.INT, dest, value ? 1 : 0);
764     }
765   }
766 
767   static public class DexValueMethodHandle extends NestedDexValue<DexMethodHandle> {
768 
DexValueMethodHandle(DexMethodHandle value)769     public DexValueMethodHandle(DexMethodHandle value) {
770       super(value);
771     }
772 
773     @Override
getValueKind()774     protected byte getValueKind() {
775       return VALUE_METHOD_HANDLE;
776     }
777 
778     @Override
collectIndexedItems(IndexedItemCollection indexedItems)779     public void collectIndexedItems(IndexedItemCollection indexedItems) {
780       value.collectIndexedItems(indexedItems);
781     }
782   }
783 }
784