001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Mikhail Y. Fursov
019: */package org.apache.harmony.drlvm;
020:
021: import org.apache.harmony.drlvm.VMHelper;
022: import org.vmmagic.unboxed.*;
023: import org.vmmagic.pragma.*;
024:
025: class VMHelperFastPath {
026:
027: private static final int VTABLE_SUPERCLASSES_OFFSET = getVtableSuperclassesOffset();
028: private static final int CLASS_INF_TYPE_0_OFFSET = getVtableIntfTypeOffset(0);
029: private static final int CLASS_INF_TABLE_0_OFFSET = getVtableIntfTableOffset(0);
030: private static final int CLASS_INF_TYPE_1_OFFSET = getVtableIntfTypeOffset(1);
031: private static final int CLASS_INF_TABLE_1_OFFSET = getVtableIntfTableOffset(1);
032: private static final int CLASS_INF_TYPE_2_OFFSET = getVtableIntfTypeOffset(2);
033: private static final int CLASS_INF_TABLE_2_OFFSET = getVtableIntfTableOffset(2);
034:
035: private VMHelperFastPath() {
036: }
037:
038: //TODO: leave only one version
039: //TODO: refactor code to use getVtableIntfTableOffset method (+ avoid extra comparisons while refactoring)
040:
041: @Inline
042: public static Address getInterfaceVTable3(Address intfType,
043: Object obj) {
044:
045: //Returning zero address if the object is null
046: //is safe in terms of preserving program semantics(the exception will be generated on the first method invocation) and
047: //allows profitable code transformations such as hoisting vm helper outside the loop body.
048: //This is our current convention which touches all variants of this helper,
049: //If it changes, all variants must be fixed.
050:
051: if (obj == null) {
052: return Address.zero();
053: }
054:
055: Address vtableAddr = VMHelper.getVTable(obj);
056:
057: Address inf0Type = vtableAddr.loadAddress(Offset
058: .fromIntZeroExtend(CLASS_INF_TYPE_0_OFFSET));
059: if (inf0Type.EQ(intfType)) {
060: return vtableAddr.loadAddress(Offset
061: .fromIntZeroExtend(CLASS_INF_TABLE_0_OFFSET));
062: }
063:
064: Address inf1Type = vtableAddr.loadAddress(Offset
065: .fromIntZeroExtend(CLASS_INF_TYPE_1_OFFSET));
066: if (inf1Type.EQ(intfType)) {
067: return vtableAddr.loadAddress(Offset
068: .fromIntZeroExtend(CLASS_INF_TABLE_1_OFFSET));
069: }
070:
071: Address inf2Type = vtableAddr.loadAddress(Offset
072: .fromIntZeroExtend(CLASS_INF_TYPE_2_OFFSET));
073: if (inf2Type.EQ(intfType)) {
074: return vtableAddr.loadAddress(Offset
075: .fromIntZeroExtend(CLASS_INF_TABLE_2_OFFSET));
076: }
077: //slow path version
078: return VMHelper.getInterfaceVTable(obj, intfType);
079: }
080:
081: @Inline
082: public static Address getInterfaceVTable2(Address intfType,
083: Object obj) {
084: Address vtableAddr = VMHelper.getVTable(obj);
085:
086: Address inf0Type = vtableAddr.loadAddress(Offset
087: .fromIntZeroExtend(CLASS_INF_TYPE_0_OFFSET));
088: if (inf0Type.EQ(intfType)) {
089: return vtableAddr.loadAddress(Offset
090: .fromIntZeroExtend(CLASS_INF_TABLE_0_OFFSET));
091: }
092:
093: Address inf1Type = vtableAddr.loadAddress(Offset
094: .fromIntZeroExtend(CLASS_INF_TYPE_1_OFFSET));
095: if (inf1Type.EQ(intfType)) {
096: return vtableAddr.loadAddress(Offset
097: .fromIntZeroExtend(CLASS_INF_TABLE_1_OFFSET));
098: }
099:
100: //slow path version
101: return VMHelper.getInterfaceVTable(obj, intfType);
102: }
103:
104: @Inline
105: public static Address getInterfaceVTable1(Address intfType,
106: Object obj) {
107: Address vtableAddr = VMHelper.getVTable(obj);
108:
109: Address inf0Type = vtableAddr.loadAddress(Offset
110: .fromIntZeroExtend(CLASS_INF_TYPE_0_OFFSET));
111: if (inf0Type.EQ(intfType)) {
112: return vtableAddr.loadAddress(Offset
113: .fromIntZeroExtend(CLASS_INF_TABLE_0_OFFSET));
114: }
115:
116: //slow path version
117: return VMHelper.getInterfaceVTable(obj, intfType);
118: }
119:
120: @Inline
121: public static boolean instanceOf(Address castType, Object obj) {
122: if (obj == null) {
123: return false;
124: }
125: if (VMHelper.isInterface(castType)) {
126: Address vtableAddr = VMHelper.getVTable(obj);
127:
128: Address inf0Type = vtableAddr.loadAddress(Offset
129: .fromIntZeroExtend(CLASS_INF_TYPE_0_OFFSET));
130: if (inf0Type.EQ(castType)) {
131: return true;
132: }
133:
134: Address inf1Type = vtableAddr.loadAddress(Offset
135: .fromIntZeroExtend(CLASS_INF_TYPE_1_OFFSET));
136: if (inf1Type.EQ(castType)) {
137: return true;
138: }
139: } else if (!VMHelper.isArray(castType)) {
140: int fastCheckDepth = VMHelper
141: .getFastTypeCheckDepth(castType);
142: if (fastCheckDepth != 0) {
143: return fastClassInstanceOf(obj, castType,
144: fastCheckDepth);
145: }
146: }
147: return VMHelper.instanceOf(obj, castType);
148:
149: }
150:
151: @Inline
152: public static void checkCast(Address castType, Object obj) {
153: if (obj == null) {
154: return;
155: }
156: if (VMHelper.isInterface(castType)) {
157: Address vtableAddr = VMHelper.getVTable(obj);
158:
159: Address inf0Type = vtableAddr.loadAddress(Offset
160: .fromIntZeroExtend(CLASS_INF_TYPE_0_OFFSET));
161: if (inf0Type.EQ(castType)) {
162: return;
163: }
164:
165: Address inf1Type = vtableAddr.loadAddress(Offset
166: .fromIntZeroExtend(CLASS_INF_TYPE_1_OFFSET));
167: if (inf1Type.EQ(castType)) {
168: return;
169: }
170: } else if (!VMHelper.isArray(castType)) {
171: int fastCheckDepth = VMHelper
172: .getFastTypeCheckDepth(castType);
173: if (fastCheckDepth != 0
174: && fastClassInstanceOf(obj, castType,
175: fastCheckDepth)) {
176: return;
177: }
178: }
179: VMHelper.checkCast(obj, castType);
180: }
181:
182: @Inline
183: public static boolean fastClassInstanceOf(Object obj,
184: Address castType, int fastCheckDepth) {
185: Address objVtableAddr = VMHelper.getVTable(obj);
186: Address objClassType = objVtableAddr.loadAddress(Offset
187: .fromIntZeroExtend(VMHelper.VTABLE_CLASS_OFFSET));
188:
189: if (objClassType.EQ(castType)) {
190: return true;
191: }
192: if (VMHelper.isFinal(castType)) {
193: return false;
194: }
195:
196: int subTypeOffset = VTABLE_SUPERCLASSES_OFFSET
197: + VMHelper.POINTER_TYPE_SIZE * (fastCheckDepth - 1);
198: Address depthSubType = objVtableAddr.loadAddress(Offset
199: .fromIntZeroExtend(subTypeOffset));
200: return depthSubType.EQ(castType);
201: }
202:
203: private static native int getVtableIntfTypeOffset(int n);
204:
205: private static native int getVtableIntfTableOffset(int n);
206:
207: private static native int getVtableSuperclassesOffset();
208: }
|