1b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson/*
2b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Copyright (C) 2017 The Android Open Source Project
3b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson *
4b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Licensed under the Apache License, Version 2.0 (the "License");
5b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * you may not use this file except in compliance with the License.
6b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * You may obtain a copy of the License at
7b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson *
8b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson *      http://www.apache.org/licenses/LICENSE-2.0
9b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson *
10b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Unless required by applicable law or agreed to in writing, software
11b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * distributed under the License is distributed on an "AS IS" BASIS,
12b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * See the License for the specific language governing permissions and
14b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * limitations under the License.
15b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson */
16b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonpackage com.android.dx.dex.file;
17b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
18b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.Constant;
19b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstBaseMethodRef;
20b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstFieldRef;
21b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstInterfaceMethodRef;
22b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.rop.cst.CstMethodHandle;
23b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.util.AnnotatedOutput;
24b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonimport com.android.dx.util.Hex;
25b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
26b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson/**
27b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson * Representation of a method handle in a DEX file.
28b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson */
29b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodsonpublic final class MethodHandleItem extends IndexedItem {
30b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
31b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    /** The item size when placed in a DEX file. */
32b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    private final int ITEM_SIZE = 8;
33b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
34b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    /** {@code non-null;} The method handle represented by this item. */
35b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    private final CstMethodHandle methodHandle;
36b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
37b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    /**
38b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson     * Constructs an instance.
39b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson     *
40b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson     * @param methodHandle {@code non-null;} The method handle to represent in the DEX file.
41b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson     */
42b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    public MethodHandleItem(CstMethodHandle methodHandle) {
43b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        this.methodHandle = methodHandle;
44b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    }
45b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
46b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    /** {@inheritDoc} */
47b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    @Override
48b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    public ItemType itemType() {
49b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        return ItemType.TYPE_METHOD_HANDLE_ITEM;
50b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    }
51b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
52b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    /** {@inheritDoc} */
53b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    @Override
54b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    public int writeSize() {
55b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        return ITEM_SIZE;
56b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    }
57b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
58b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    /** {@inheritDoc} */
59b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    @Override
60b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    public void addContents(DexFile file) {
61b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        MethodHandlesSection methodHandles = file.getMethodHandles();
62b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        methodHandles.intern(methodHandle);
63b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    }
64b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
65b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    /** {@inheritDoc} */
66b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    @Override
67b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    public void writeTo(DexFile file, AnnotatedOutput out) {
68b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        int targetIndex = getTargetIndex(file);
69d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson        int mhType = methodHandle.getMethodHandleType();
70b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        if (out.annotates()) {
71d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson            out.annotate(0, indexString() + ' ' + methodHandle.toString());
72d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson            String typeComment = " // " + CstMethodHandle.getMethodHandleTypeName(mhType);
73d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson            out.annotate(2, "type:     " + Hex.u2(mhType) + typeComment);
74d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson            out.annotate(2, "reserved: " + Hex.u2(0));
75d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson            String targetComment = " // " +  methodHandle.getRef().toString();
76b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            if (methodHandle.isAccessor()) {
77d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson                out.annotate(2, "fieldId:  " + Hex.u2(targetIndex) + targetComment);
78b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            } else {
79d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson                out.annotate(2, "methodId: " + Hex.u2(targetIndex) + targetComment);
80b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            }
81d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson            out.annotate(2, "reserved: " + Hex.u2(0));
82b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        }
83d7a89b25ef0eaa08e19bdfd52343fb45e2c1655dOrion Hodson        out.writeShort(mhType);
84b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        out.writeShort(0);
85b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        out.writeShort(getTargetIndex(file));
86b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        out.writeShort(0);
87b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    }
88b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson
89b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    private int getTargetIndex(DexFile file) {
90b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        Constant ref = methodHandle.getRef();
91b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        if (methodHandle.isAccessor()) {
92b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            FieldIdsSection fieldIds = file.getFieldIds();
93b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            return fieldIds.indexOf((CstFieldRef) ref);
94b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        } else if (methodHandle.isInvocation()) {
95b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            if (ref instanceof CstInterfaceMethodRef) {
96b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson                ref = ((CstInterfaceMethodRef)ref).toMethodRef();
97b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            }
98b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            MethodIdsSection methodIds = file.getMethodIds();
99b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            return methodIds.indexOf((CstBaseMethodRef) ref);
100b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        } else {
101b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson            throw new IllegalStateException("Unhandled invocation type");
102b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson        }
103b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson    }
104b7d748318354aba23ba03f76bdefc31fa6adc885Orion Hodson}
105