1 cananian 1.1.2.1 // StubCode.java, created Sat Oct 23 15:33:33 1999 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Backend.Runtime1; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Backend.Generic.Frame; 7 cananian 1.1.2.1 import harpoon.Backend.Maps.NameMap; 8 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 9 cananian 1.1.2.1 import harpoon.ClassFile.HCode; 10 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement; 11 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 12 cananian 1.1.2.9 import harpoon.IR.Tree.DerivationGenerator; 13 cananian 1.1.2.1 import harpoon.IR.Tree.Bop; 14 cananian 1.1.2.1 import harpoon.IR.Tree.Exp; 15 cananian 1.1.2.1 import harpoon.IR.Tree.ExpList; 16 cananian 1.1.2.1 import harpoon.IR.Tree.Stm; 17 cananian 1.1.2.1 import harpoon.IR.Tree.Tree; 18 cananian 1.1.2.8 import harpoon.IR.Tree.TreeDerivation; 19 cananian 1.1.2.1 import harpoon.IR.Tree.Type; 20 cananian 1.1.2.1 import harpoon.IR.Tree.BINOP; 21 cananian 1.1.2.1 import harpoon.IR.Tree.CJUMP; 22 cananian 1.1.2.1 import harpoon.IR.Tree.CONST; 23 cananian 1.1.2.1 import harpoon.IR.Tree.LABEL; 24 cananian 1.1.2.1 import harpoon.IR.Tree.MEM; 25 cananian 1.1.2.1 import harpoon.IR.Tree.METHOD; 26 cananian 1.1.2.1 import harpoon.IR.Tree.MOVE; 27 cananian 1.1.2.1 import harpoon.IR.Tree.NAME; 28 cananian 1.1.2.1 import harpoon.IR.Tree.NATIVECALL; 29 cananian 1.1.2.1 import harpoon.IR.Tree.RETURN; 30 cananian 1.1.2.1 import harpoon.IR.Tree.SEGMENT; 31 cananian 1.1.2.1 import harpoon.IR.Tree.TEMP; 32 cananian 1.1.2.1 import harpoon.IR.Tree.THROW; 33 cananian 1.1.2.1 import harpoon.Temp.Label; 34 cananian 1.1.2.1 import harpoon.Temp.Temp; 35 cananian 1.1.2.1 36 cananian 1.1.2.2 import java.lang.reflect.Modifier; 37 cananian 1.1.2.2 38 cananian 1.1.2.1 import java.util.ArrayList; 39 cananian 1.1.2.1 import java.util.List; 40 cananian 1.1.2.1 /** 41 cananian 1.1.2.1 * <code>StubCode</code> is used to generate non-canonical tree code 42 cananian 1.1.2.1 * stubs for native methods. That is, a <code>StubCode</code> is a 43 cananian 1.1.2.1 * thunk from runtime-native methods to the JNI interface which 44 cananian 1.1.2.1 * C-code "native methods" conform to.<p> 45 cananian 1.1.2.1 * <code>StubCode</code> will generate a thunk for any old method you 46 cananian 1.1.2.1 * give to its constructor. It is the job of the 47 cananian 1.1.2.1 * <code>nativeTreeCodeFactory()</code> in <code>Runtime1.Runtime</code> 48 cananian 1.1.2.1 * to weed out native from non-native methods, give the proper ones 49 cananian 1.1.2.1 * to <code>StubCode</code>, and do the right thing with the stubs that 50 cananian 1.1.2.1 * <code>StubCode</code> makes. 51 cananian 1.1.2.1 * 52 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 53 cananian 1.3 * @version $Id: StubCode.java,v 1.3 2003/10/21 02:11:02 cananian Exp $ 54 cananian 1.1.2.1 */ 55 cananian 1.1.2.1 public class StubCode extends harpoon.IR.Tree.TreeCode { 56 cananian 1.1.2.1 final TreeBuilder m_tb; 57 cananian 1.1.2.1 final NameMap m_nm; 58 cananian 1.1.2.1 final int EXC_OFFSET; 59 cananian 1.1.2.1 final int REF_OFFSET; 60 cananian 1.1.2.9 final DerivationGenerator m_dg; 61 cananian 1.1.2.1 62 cananian 1.1.2.13 /** Creates a <code>StubCode</code>. 63 cananian 1.1.2.13 * @param method The method for which to generate code. 64 cananian 1.1.2.13 * @param frame The frame for the generated code. 65 cananian 1.1.2.16 */ 66 cananian 1.1.2.16 public StubCode(HMethod method, Frame frame) { 67 cananian 1.1.2.9 super(method, null, frame, new DerivationGenerator()); 68 cananian 1.1.2.20 this.m_nm = frame.getRuntime().getNameMap(); 69 cananian 1.1.2.20 this.m_tb = (TreeBuilder) frame.getRuntime().getTreeBuilder(); 70 cananian 1.1.2.12 // keep this synchronized with struct FNI_Thread_State in 71 cananian 1.1.2.12 // Runtime/include/jni-private.h and TreeBuilder._call_FNI_Monitor() 72 cananian 1.1.2.1 this.EXC_OFFSET = 1 * m_tb.POINTER_SIZE; 73 cananian 1.1.2.1 this.REF_OFFSET = 3 * m_tb.POINTER_SIZE; 74 cananian 1.1.2.9 this.m_dg = (DerivationGenerator) getTreeDerivation(); 75 cananian 1.1.2.1 this.tree = buildStub(method); 76 cananian 1.1.2.1 } 77 cananian 1.1.2.1 78 cananian 1.1.2.9 // here is the real stub builder code. 79 cananian 1.1.2.1 Tree buildStub(HMethod method) { 80 cananian 1.1.2.9 final HClass HCcls = frame.getLinker().forName("java.lang.Class"); 81 cananian 1.1.2.9 final HClass HCthw = frame.getLinker().forName("java.lang.Throwable"); 82 cananian 1.1.2.9 83 cananian 1.1.2.1 List stmlist = new ArrayList(); 84 cananian 1.1.2.1 // segment change 85 cananian 1.1.2.1 stmlist.add(new SEGMENT(tf, null, SEGMENT.CODE)); 86 cananian 1.1.2.1 // add method header. 87 cananian 1.1.2.1 // (remember that first method parameter in tree form is the 88 cananian 1.1.2.1 // 'return exception address') 89 cananian 1.1.2.1 HClass[] paramTypes = method.getParameterTypes(); 90 cananian 1.1.2.5 if (!method.isStatic()) {// add 'this' parameter for non-static methods 91 cananian 1.1.2.5 HClass[] nparamTypes = new HClass[paramTypes.length+1]; 92 cananian 1.1.2.5 nparamTypes[0] = method.getDeclaringClass(); 93 cananian 1.1.2.5 System.arraycopy(paramTypes,0,nparamTypes,1,paramTypes.length); 94 cananian 1.1.2.5 paramTypes = nparamTypes; 95 cananian 1.1.2.5 } 96 cananian 1.1.2.1 Temp[] paramTemps = new Temp[paramTypes.length+1]; 97 cananian 1.1.2.1 TEMP[] paramTEMPs = new TEMP[paramTypes.length+1]; 98 cananian 1.1.2.1 paramTemps[0] = new Temp(tf.tempFactory(), "rexaddr"); 99 cananian 1.1.2.9 paramTEMPs[0] = _TEMP(tf, null, HClass.Void, paramTemps[0]); 100 cananian 1.1.2.1 for (int i=0; i<paramTypes.length; i++) { 101 cananian 1.1.2.1 paramTemps[i+1] = new Temp(tf.tempFactory(), "param"+i); 102 cananian 1.1.2.9 paramTEMPs[i+1] = _TEMP(tf, null, paramTypes[i], paramTemps[i+1]); 103 cananian 1.1.2.1 } 104 cananian 1.1.2.15 int rtype = (method.getReturnType()==HClass.Void) ? -1 : 105 cananian 1.1.2.15 class2type(method.getReturnType()); 106 cananian 1.1.2.15 stmlist.add(new METHOD(tf,null,m_nm.label(method), rtype, paramTEMPs)); 107 cananian 1.1.2.11 // get JNIEnv * (which is thread-local) 108 cananian 1.1.2.1 Temp envT = new Temp(tf.tempFactory(), "env"); 109 cananian 1.1.2.11 stmlist.add(new NATIVECALL 110 cananian 1.1.2.11 (tf, null, 111 cananian 1.1.2.11 _TEMP(tf, null, HClass.Void, envT) /*retval*/, 112 cananian 1.1.2.11 _NAME(tf, null, HClass.Void, 113 cananian 1.1.2.11 new Label(m_nm.c_function_name("FNI_GetJNIEnv"))), 114 cananian 1.1.2.11 null/* no args*/)); 115 cananian 1.1.2.11 116 cananian 1.1.2.1 // reset the exception field in the thread state. 117 cananian 1.1.2.12 /* CSA: i don't think we need to do this -- we clear the exception 118 cananian 1.1.2.12 * when we return. [mar-26-2000] 119 cananian 1.1.2.1 stmlist.add(new MOVE(tf, null, 120 cananian 1.1.2.9 _MEM(tf, null, HClass.Void, 121 cananian 1.1.2.1 new BINOP(tf, null, Type.POINTER, Bop.ADD, 122 cananian 1.1.2.9 _TEMP(tf, null, HClass.Void, 123 cananian 1.1.2.1 envT), 124 cananian 1.1.2.1 new CONST(tf, null, EXC_OFFSET) 125 cananian 1.1.2.1 )), 126 cananian 1.1.2.1 new CONST(tf, null))); // set to null. 127 cananian 1.1.2.12 */ 128 cananian 1.1.2.1 // save the top of the local ref stack (so we can restore it later) 129 cananian 1.1.2.1 Temp refT = new Temp(tf.tempFactory(), "lref"); 130 cananian 1.1.2.1 stmlist.add(new MOVE(tf, null, 131 cananian 1.1.2.9 _TEMP(tf, null, HClass.Void, refT), 132 cananian 1.1.2.9 _MEM(tf, null, HClass.Void, 133 cananian 1.1.2.1 new BINOP(tf, null, Type.POINTER, Bop.ADD, 134 cananian 1.1.2.9 _TEMP(tf, null, HClass.Void, 135 cananian 1.1.2.1 envT), 136 cananian 1.1.2.1 new CONST(tf, null, REF_OFFSET) 137 cananian 1.1.2.1 )))); 138 cananian 1.1.2.1 // wrap objects in parameter list 139 cananian 1.1.2.1 for (int i=0; i<paramTypes.length; i++) 140 cananian 1.1.2.19 if (!paramTypes[i].isPrimitive()) { 141 cananian 1.1.2.19 Temp wrapped = new Temp(paramTemps[i+1]); 142 cananian 1.1.2.1 stmlist.add(new NATIVECALL 143 cananian 1.1.2.1 (tf, null, 144 cananian 1.1.2.9 _TEMP 145 cananian 1.1.2.19 (tf, null, HClass.Void, wrapped), 146 cananian 1.1.2.9 _NAME 147 cananian 1.1.2.9 (tf, null, HClass.Void, 148 cananian 1.1.2.10 new Label(m_nm.c_function_name 149 cananian 1.1.2.10 ("FNI_NewLocalRef"))), 150 cananian 1.1.2.9 new ExpList 151 cananian 1.1.2.9 (_TEMP(tf, null, HClass.Void, envT), 152 cananian 1.1.2.1 new ExpList 153 cananian 1.1.2.9 (_TEMP(tf, null, paramTypes[i],paramTemps[i+1]), 154 cananian 1.1.2.1 null)))); 155 cananian 1.1.2.19 // after this point, use wrapped temp 156 cananian 1.1.2.19 paramTypes[i] = HClass.Void; 157 cananian 1.1.2.19 paramTemps[i+1] = wrapped; 158 cananian 1.1.2.19 } 159 cananian 1.1.2.1 // wrap a class object pointer for static methods. 160 cananian 1.1.2.1 Temp classT = null; 161 cananian 1.1.2.1 if (method.isStatic()) { 162 cananian 1.1.2.1 classT = new Temp(tf.tempFactory(), "jclass"); 163 cananian 1.1.2.1 stmlist.add(new NATIVECALL 164 cananian 1.1.2.1 (tf, null, 165 cananian 1.1.2.9 _TEMP 166 cananian 1.1.2.9 (tf,null,HClass.Void, classT), 167 cananian 1.1.2.9 _NAME 168 cananian 1.1.2.10 (tf,null,HClass.Void, new Label(m_nm.c_function_name 169 cananian 1.1.2.10 ("FNI_NewLocalRef"))), 170 cananian 1.1.2.1 new ExpList 171 cananian 1.1.2.9 (_TEMP(tf, null, HClass.Void, envT), 172 cananian 1.1.2.1 new ExpList 173 cananian 1.1.2.9 (_NAME(tf, null, HCcls, 174 cananian 1.1.2.1 m_nm.label(method.getDeclaringClass(), 175 cananian 1.1.2.1 "classobj")), 176 cananian 1.1.2.1 null)))); 177 cananian 1.1.2.1 } 178 cananian 1.1.2.14 // if this method is synchronized, lock the object. 179 cananian 1.1.2.14 Temp lockT = (classT != null) ? classT : paramTemps[1]; 180 cananian 1.1.2.17 emitMonitorLockUnlock(stmlist, envT, lockT, true/*lock*/); 181 cananian 1.1.2.1 // make the native call's parameters, in reverse order 182 cananian 1.1.2.1 ExpList jniParams = null; 183 cananian 1.1.2.1 for (int i=paramTypes.length-1; i>=0; i--) 184 cananian 1.1.2.1 jniParams = new ExpList 185 cananian 1.1.2.9 (_TEMP(tf, null, paramTypes[i], paramTemps[i+1]), 186 cananian 1.1.2.1 jniParams); 187 cananian 1.1.2.1 // second parameter is either a jclass for a static method 188 cananian 1.1.2.5 // or an (already added) 'this' object 189 cananian 1.1.2.1 if (classT != null) 190 cananian 1.1.2.9 jniParams = new ExpList(_TEMP(tf, null, HCcls, classT), 191 cananian 1.1.2.1 jniParams); 192 cananian 1.1.2.1 // first parameter is the JNIEnv * 193 cananian 1.1.2.9 jniParams = new ExpList(_TEMP(tf, null, HClass.Void, envT), 194 cananian 1.1.2.1 jniParams); 195 cananian 1.1.2.1 // Do the call. 196 cananian 1.1.2.1 Temp retT = null; 197 cananian 1.1.2.19 HClass rettype = method.getReturnType(); 198 cananian 1.1.2.19 if (rettype!=HClass.Void) { 199 cananian 1.1.2.1 retT = new Temp(tf.tempFactory(), "retval"); 200 cananian 1.1.2.19 if (!rettype.isPrimitive()) rettype=HClass.Void;//retval is wrapped 201 cananian 1.1.2.19 } 202 cananian 1.1.2.1 stmlist.add(new NATIVECALL(tf, null, 203 cananian 1.1.2.1 (retT==null) ? null : 204 cananian 1.1.2.19 _TEMP(tf, null, rettype, retT), 205 cananian 1.1.2.9 _NAME(tf, null, HClass.Void, 206 cananian 1.1.2.10 new Label(m_nm.c_function_name 207 cananian 1.1.2.10 (jniMangle(method)))), 208 cananian 1.1.2.1 jniParams)); 209 cananian 1.1.2.1 // now clean up afterward: check for exceptions, etc. 210 cananian 1.1.2.1 Temp excT = new Temp(tf.tempFactory(), "excval"); 211 cananian 1.1.2.1 stmlist.add(new MOVE(tf, null, 212 cananian 1.1.2.9 _TEMP(tf, null, HClass.Void, excT), 213 cananian 1.1.2.9 _MEM(tf, null, HClass.Void, 214 cananian 1.1.2.1 new BINOP(tf, null, Type.POINTER, Bop.ADD, 215 cananian 1.1.2.9 _TEMP(tf, null, HClass.Void, 216 cananian 1.1.2.1 envT), 217 cananian 1.1.2.1 new CONST(tf, null, EXC_OFFSET) 218 cananian 1.1.2.1 )))); 219 cananian 1.1.2.1 Label no_exceptions = new Label(); 220 cananian 1.1.2.1 Label yes_exceptions = new Label(); 221 cananian 1.1.2.1 stmlist.add(new CJUMP(tf, null, 222 cananian 1.1.2.1 new BINOP(tf, null, Type.POINTER, Bop.CMPEQ, 223 cananian 1.1.2.9 _TEMP(tf, null, HClass.Void, excT), 224 cananian 1.1.2.1 new CONST(tf, null)/*null pointer*/), 225 cananian 1.1.2.1 no_exceptions, yes_exceptions)); 226 cananian 1.1.2.1 // no exceptions occurred. unwrap return value and return from stub. 227 cananian 1.1.2.1 stmlist.add(new LABEL(tf, null, no_exceptions, false)); 228 cananian 1.1.2.19 emitMonitorLockUnlock(stmlist, envT, lockT, false/*unlock*/); 229 cananian 1.1.2.1 Exp retexp; 230 cananian 1.1.2.1 if (retT==null) 231 cananian 1.1.2.1 retexp = new CONST(tf, null); 232 cananian 1.1.2.1 else { 233 cananian 1.1.2.19 rettype = method.getReturnType();//reset to unwrapped type. 234 cananian 1.1.2.19 if (!rettype.isPrimitive()) { 235 cananian 1.1.2.19 Temp unwrapped = new Temp(retT); 236 cananian 1.1.2.1 stmlist.add(new NATIVECALL(tf, null, 237 cananian 1.1.2.19 _TEMP(tf, null, rettype, unwrapped), 238 cananian 1.1.2.9 _NAME(tf, null, HClass.Void, 239 cananian 1.1.2.10 new Label(m_nm.c_function_name 240 cananian 1.1.2.10 ("FNI_Unwrap"))), 241 cananian 1.1.2.1 new ExpList 242 cananian 1.1.2.9 (_TEMP(tf, null, HClass.Void, retT), 243 cananian 1.1.2.9 null) 244 cananian 1.1.2.1 )); 245 cananian 1.1.2.19 retT = unwrapped; // after this point, use unwrapped temp 246 cananian 1.1.2.19 } 247 cananian 1.1.2.9 retexp = _TEMP(tf, null, rettype, retT); 248 cananian 1.1.2.1 } 249 cananian 1.1.2.1 emitFreeLocals(stmlist, envT, refT); 250 cananian 1.1.2.1 stmlist.add(new RETURN(tf, null, retexp)); 251 cananian 1.1.2.1 // an exception occurred. unwrap exception value and throw it. 252 cananian 1.1.2.6 // (don't forget to clear the exception before we invoke any more 253 cananian 1.1.2.6 // jni functions!) 254 cananian 1.1.2.1 stmlist.add(new LABEL(tf, null, yes_exceptions, false)); 255 cananian 1.1.2.6 stmlist.add(new NATIVECALL(tf, null, null, 256 cananian 1.1.2.9 _NAME(tf, null, HClass.Void, 257 cananian 1.1.2.10 new Label(m_nm.c_function_name 258 cananian 1.1.2.10 ("FNI_ExceptionClear"))), 259 cananian 1.1.2.6 new ExpList 260 cananian 1.1.2.9 (_TEMP(tf, null, HClass.Void, envT), 261 cananian 1.1.2.6 null) 262 cananian 1.1.2.6 )); 263 cananian 1.1.2.19 emitMonitorLockUnlock(stmlist, envT, lockT, false/*unlock*/); 264 cananian 1.1.2.19 Temp unwrapped = new Temp(excT); 265 cananian 1.1.2.1 stmlist.add(new NATIVECALL(tf, null, 266 cananian 1.1.2.19 _TEMP(tf, null, HCthw, unwrapped), 267 cananian 1.1.2.9 _NAME(tf, null, HClass.Void, 268 cananian 1.1.2.10 new Label(m_nm.c_function_name 269 cananian 1.1.2.10 ("FNI_Unwrap"))), 270 cananian 1.1.2.1 new ExpList 271 cananian 1.1.2.9 (_TEMP(tf, null, HClass.Void, excT), 272 cananian 1.1.2.1 null) 273 cananian 1.1.2.1 )); 274 cananian 1.1.2.19 excT = unwrapped; // after this point, use unwrapped temp 275 cananian 1.1.2.1 emitFreeLocals(stmlist, envT, refT); 276 cananian 1.1.2.1 stmlist.add(new THROW(tf, null, 277 cananian 1.1.2.9 _TEMP(tf, null, HCthw, excT), 278 cananian 1.1.2.9 _TEMP(tf, null, HClass.Void, paramTemps[0]) 279 cananian 1.1.2.1 )); 280 cananian 1.1.2.1 return Stm.toStm(stmlist); 281 cananian 1.1.2.14 } 282 cananian 1.1.2.14 private void emitMonitorLockUnlock(List stmlist, Temp envT, 283 cananian 1.1.2.17 Temp lockT, boolean isLock) { 284 cananian 1.1.2.14 // if this method is not synchronized, skip this. 285 cananian 1.1.2.14 if (!Modifier.isSynchronized(getMethod().getModifiers())) return; 286 cananian 1.1.2.14 // okay, emit native call to FNI_MonitorEnter/Exit(). 287 cananian 1.1.2.14 Temp discardT = new Temp(tf.tempFactory(), "discard"); 288 cananian 1.1.2.14 stmlist.add(new NATIVECALL 289 cananian 1.1.2.14 (tf, null, 290 cananian 1.1.2.14 _TEMP(tf, null, HClass.Int, discardT)/* retval*/, 291 cananian 1.1.2.14 _NAME(tf, null, HClass.Void, 292 cananian 1.1.2.14 new Label(m_nm.c_function_name 293 cananian 1.1.2.14 (isLock ? 294 cananian 1.1.2.14 "FNI_MonitorEnter":"FNI_MonitorExit"))), 295 cananian 1.1.2.14 new ExpList(_TEMP(tf, null, HClass.Void, envT), 296 cananian 1.1.2.17 // note type of lockT is HClass.Void because 297 cananian 1.1.2.17 // it has been wrapped. 298 cananian 1.1.2.17 new ExpList(_TEMP(tf, null, HClass.Void, 299 cananian 1.1.2.17 lockT), null)))); 300 cananian 1.1.2.1 } 301 cananian 1.1.2.1 private void emitFreeLocals(List stmlist, Temp envT, Temp refT) { 302 cananian 1.1.2.1 stmlist.add(new NATIVECALL 303 cananian 1.1.2.1 (tf, null, null, // free local references 304 cananian 1.1.2.9 _NAME(tf, null, HClass.Void, 305 cananian 1.1.2.10 new Label(m_nm.c_function_name 306 cananian 1.1.2.10 ("FNI_DeleteLocalRefsUpTo"))), 307 cananian 1.1.2.9 new ExpList(_TEMP(tf, null, HClass.Void, envT), 308 cananian 1.1.2.9 new ExpList(_TEMP(tf, null, HClass.Void, refT), 309 cananian 1.1.2.4 null)))); 310 cananian 1.1.2.1 } 311 cananian 1.1.2.1 312 cananian 1.1.2.9 private TEMP _TEMP(TreeFactory tf, HCodeElement src, 313 cananian 1.1.2.9 HClass type, Temp temp) { 314 cananian 1.1.2.9 TEMP result = new TEMP(tf, src, class2type(type), temp); 315 cananian 1.1.2.9 m_dg.putTypeAndTemp(result, type, temp); 316 cananian 1.1.2.9 return result; 317 cananian 1.1.2.9 } 318 cananian 1.1.2.9 private MEM _MEM(TreeFactory tf, HCodeElement src, 319 cananian 1.1.2.9 HClass type, Exp exp) { 320 cananian 1.1.2.9 MEM result = new MEM(tf, src, class2type(type), exp); 321 cananian 1.1.2.9 m_dg.putType(result, type); 322 cananian 1.1.2.9 return result; 323 cananian 1.1.2.9 } 324 cananian 1.1.2.9 private NAME _NAME(TreeFactory tf, HCodeElement src, 325 cananian 1.1.2.9 HClass type, Label label) { 326 cananian 1.1.2.9 NAME result = new NAME(tf, src, label); 327 cananian 1.1.2.9 m_dg.putType(result, type); 328 cananian 1.1.2.9 return result; 329 cananian 1.1.2.9 } 330 cananian 1.1.2.9 331 cananian 1.1.2.1 private static int class2type(HClass hc) { 332 cananian 1.1.2.1 if (!hc.isPrimitive()) return Type.POINTER; 333 cananian 1.1.2.9 if (hc==HClass.Void) return Type.POINTER; 334 cananian 1.1.2.1 if (hc==HClass.Boolean || hc==HClass.Byte || hc==HClass.Char || 335 cananian 1.1.2.1 hc==HClass.Int || hc==HClass.Short) return Type.INT; 336 cananian 1.1.2.1 if (hc==HClass.Double) return Type.DOUBLE; 337 cananian 1.1.2.1 if (hc==HClass.Float) return Type.FLOAT; 338 cananian 1.1.2.1 if (hc==HClass.Long) return Type.LONG; 339 cananian 1.1.2.1 throw new Error("Unknown primitive type: "+hc); 340 cananian 1.1.2.1 } 341 cananian 1.1.2.1 342 cananian 1.1.2.1 private static String jniMangle(HMethod m) { 343 cananian 1.1.2.2 // jni sez use short name unless two native methods would use the 344 cananian 1.1.2.2 // same short name. So, let's check that, shall we? 345 cananian 1.1.2.2 boolean useShort = true; 346 cananian 1.1.2.2 HMethod[] allm = m.getDeclaringClass().getMethods(); 347 cananian 1.1.2.2 for (int i=0; i<allm.length; i++) 348 cananian 1.1.2.2 if (Modifier.isNative(allm[i].getModifiers()) && 349 cananian 1.1.2.2 allm[i].getName().equals(m.getName()) && 350 cananian 1.1.2.2 !allm[i].equals(m)) 351 cananian 1.1.2.2 useShort = false; 352 cananian 1.1.2.10 String mangled = "Java_" + 353 cananian 1.1.2.2 encode(m.getDeclaringClass().getName()) + 354 cananian 1.1.2.2 "_" + 355 cananian 1.1.2.2 encode(m.getName()); 356 cananian 1.1.2.2 if (!useShort) { 357 cananian 1.1.2.2 String desc = m.getDescriptor(); 358 cananian 1.1.2.2 mangled += "__" + 359 cananian 1.1.2.2 encode(desc.substring(1, desc.lastIndexOf(')'))); 360 cananian 1.1.2.2 } 361 cananian 1.1.2.2 return mangled; 362 cananian 1.1.2.2 } 363 cananian 1.1.2.2 364 cananian 1.1.2.2 //-------- CODE BELOW THIS LINE WAS COPIED FROM DefaultNameMap.java ---- 365 cananian 1.1.2.2 // (so if you find a bug here, fix it there, too!) 366 cananian 1.1.2.2 367 cananian 1.1.2.2 /** Apply the JNI-standard unicode-to-C encoding. */ 368 cananian 1.1.2.2 private static String encode(String s) { 369 cananian 1.1.2.2 StringBuffer sb = new StringBuffer(); 370 cananian 1.1.2.2 for(int i=0; i<s.length(); i++) { 371 cananian 1.1.2.2 switch(s.charAt(i)) { 372 cananian 1.1.2.2 case '.': 373 cananian 1.1.2.2 case '/': 374 cananian 1.1.2.2 sb.append("_"); 375 cananian 1.1.2.2 break; 376 cananian 1.1.2.2 case '_': 377 cananian 1.1.2.2 sb.append("_1"); 378 cananian 1.1.2.2 break; 379 cananian 1.1.2.2 case ';': 380 cananian 1.1.2.2 sb.append("_2"); 381 cananian 1.1.2.2 break; 382 cananian 1.1.2.2 case '[': 383 cananian 1.1.2.2 sb.append("_3"); 384 cananian 1.1.2.2 break; 385 cananian 1.1.2.2 default: 386 cananian 1.1.2.2 if ((s.charAt(i) >= 'a' && 387 cananian 1.1.2.2 s.charAt(i) <= 'z') || 388 cananian 1.1.2.2 (s.charAt(i) >= 'A' && 389 cananian 1.1.2.2 s.charAt(i) <= 'Z') || 390 cananian 1.1.2.2 (s.charAt(i) >= '0' && 391 cananian 1.1.2.2 s.charAt(i) <= '9')) { 392 cananian 1.1.2.2 sb.append(s.charAt(i)); 393 cananian 1.1.2.2 } else { 394 cananian 1.1.2.2 sb.append("_0" + toHex(s.charAt(i), 4)); 395 cananian 1.1.2.2 } 396 cananian 1.1.2.2 break; 397 cananian 1.1.2.2 } 398 cananian 1.1.2.2 } 399 cananian 1.1.2.2 return sb.toString(); 400 cananian 1.1.2.2 } 401 cananian 1.1.2.2 /** Convert the integer <code>value</code> into a hexadecimal 402 cananian 1.1.2.2 * string with at least <code>num_digits</code> digits. */ 403 cananian 1.1.2.2 private static String toHex(int value, int num_digits) { 404 cananian 1.1.2.2 String hexval= // javah puts all hex vals in lowercase. 405 cananian 1.1.2.2 Integer.toHexString(value).toLowerCase(); 406 cananian 1.1.2.2 while(hexval.length()<num_digits) hexval="0"+hexval; 407 cananian 1.1.2.2 return hexval; 408 cananian 1.1.2.1 } 409 cananian 1.2 }