Mercurial > hg > truffle
comparison src/share/vm/c1x/c1x_VMEntries.cpp @ 1423:760213a60e8b
* rewrite of the code installation
* partial support for safepoints
* macro-based CiTargetMethod interface
* code stub support
author | Lukas Stadler <lukas.stadler@oracle.com> |
---|---|
date | Mon, 16 Aug 2010 18:59:36 -0700 |
parents | 3483ec571caf |
children | 98fffb304868 |
comparison
equal
deleted
inserted
replaced
1422:3483ec571caf | 1423:760213a60e8b |
---|---|
25 | 25 |
26 # include "incls/_precompiled.incl" | 26 # include "incls/_precompiled.incl" |
27 # include "incls/_c1x_VMEntries.cpp.incl" | 27 # include "incls/_c1x_VMEntries.cpp.incl" |
28 | 28 |
29 | 29 |
30 /* | 30 |
31 * Class: com_sun_hotspot_c1x_VMEntries | 31 |
32 * Method: RiMethod_code | 32 // public byte[] RiMethod_code(HotSpotProxy method); |
33 * Signature: (Ljava/lang/reflect/Method;)[B | 33 JNIEXPORT jbyteArray JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1code(JNIEnv *env, jobject, jlong vmId) { |
34 */ | 34 methodOop method = C1XObjects::get<methodOop>(vmId); |
35 JNIEXPORT jbyteArray JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1code(JNIEnv *env, jobject, jobject method) { | 35 int code_size = method->code_size(); |
36 methodOop m = C1XObjects::getInternalMethod(method); | |
37 int code_size = m->code_size(); | |
38 jbyteArray result = env->NewByteArray(code_size); | 36 jbyteArray result = env->NewByteArray(code_size); |
39 env->SetByteArrayRegion(result, 0, code_size, (const jbyte *)m->code_base()); | 37 env->SetByteArrayRegion(result, 0, code_size, (const jbyte *)method->code_base()); |
40 return result; | 38 return result; |
41 } | 39 } |
42 | 40 |
43 /* | 41 // public int RiMethod_maxStackSize(HotSpotProxy method); |
44 * Class: com_sun_hotspot_c1x_VMEntries | 42 JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxStackSize(JNIEnv *, jobject, jlong vmId) { |
45 * Method: RiMethod_maxStackSize | 43 return C1XObjects::get<methodOop>(vmId)->max_stack(); |
46 * Signature: (Ljava/lang/reflect/Method;)I | 44 } |
47 */ | 45 |
48 JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxStackSize(JNIEnv *, jobject, jobject method) { | 46 // public int RiMethod_maxLocals(HotSpotProxy method); |
49 return C1XObjects::getInternalMethod(method)->max_stack(); | 47 JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxLocals(JNIEnv *, jobject, jlong vmId) { |
50 } | 48 return C1XObjects::get<methodOop>(vmId)->max_locals(); |
51 | 49 } |
52 /* | 50 |
53 * Class: com_sun_hotspot_c1x_VMEntries | 51 // public RiType RiMethod_holder(HotSpotProxy method); |
54 * Method: RiMethod_maxLocals | 52 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1holder(JNIEnv *, jobject, jlong vmId) { |
55 * Signature: (Ljava/lang/reflect/Method;)I | |
56 */ | |
57 JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxLocals(JNIEnv *, jobject, jobject method) { | |
58 return C1XObjects::getInternalMethod(method)->max_locals(); | |
59 } | |
60 | |
61 /* | |
62 * Class: com_sun_hotspot_c1x_VMEntries | |
63 * Method: RiMethod_holder | |
64 * Signature: (Ljava/lang/reflect/Method;)Lcom/sun/cri/ri/RiType; | |
65 */ | |
66 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1holder(JNIEnv *, jobject, jobject method) { | |
67 VM_ENTRY_MARK | 53 VM_ENTRY_MARK |
68 oop holder = VMExits::createRiType(C1XObjects::getInternalMethod(method)->method_holder(), THREAD); | 54 klassOop klass = C1XObjects::get<methodOop>(vmId)->method_holder(); |
55 jlong klassVmId = C1XObjects::add<klassOop>(klass); | |
56 Handle name = C1XObjects::toString<Handle>(klass->klass_part()->name(), CHECK_NULL); | |
57 oop holder = VMExits::createRiType(klassVmId, name, THREAD); | |
69 return JNIHandles::make_local(THREAD, holder); | 58 return JNIHandles::make_local(THREAD, holder); |
70 } | 59 } |
71 | 60 |
72 /* | 61 // public String RiMethod_signature(HotSpotProxy method); |
73 * Class: com_sun_hotspot_c1x_VMEntries | 62 JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1signature(JNIEnv *env, jobject, jlong vmId) { |
74 * Method: RiMethod_signature | |
75 * Signature: (Ljava/lang/reflect/Method;)Lcom/sun/cri/ri/RiSignature; | |
76 */ | |
77 JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1signature(JNIEnv *env, jobject, jobject method) { | |
78 VM_ENTRY_MARK | 63 VM_ENTRY_MARK |
79 return (jstring)JNIHandles::make_local(java_lang_String::create_from_symbol(C1XObjects::getInternalMethod(method)->signature(), Thread::current())()); | 64 methodOop method = C1XObjects::get<methodOop>(vmId); |
80 } | 65 return C1XObjects::toString<jstring>(method->signature(), THREAD); |
81 | 66 } |
82 /* | 67 |
83 * Class: com_sun_hotspot_c1x_VMEntries | 68 // public int RiMethod_accessFlags(HotSpotProxy method); |
84 * Method: RiMethod_name | 69 JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1accessFlags(JNIEnv *, jobject, jlong vmId) { |
85 * Signature: (Ljava/lang/reflect/Method;)Ljava/lang/String; | 70 return C1XObjects::get<methodOop>(vmId)->access_flags().as_int(); |
86 */ | 71 } |
87 JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1name(JNIEnv *env, jobject, jobject method) { | 72 |
88 VM_ENTRY_MARK | 73 // public RiType RiSignature_lookupType(String returnType, HotSpotProxy accessingClass); |
89 return (jstring)JNIHandles::make_local(java_lang_String::create_from_symbol(C1XObjects::getInternalMethod(method)->name(), Thread::current())()); | 74 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiSignature_1lookupType(JNIEnv *, jobject, jstring jname, jlong accessingClassVmId) { |
90 } | 75 VM_ENTRY_MARK; |
91 | 76 |
92 /* | 77 symbolOop nameSymbol = C1XObjects::toSymbol(jname); |
93 * Class: com_sun_hotspot_c1x_VMEntries | 78 Handle name = JNIHandles::resolve(jname); |
94 * Method: RiMethod_accessFlags | 79 |
95 * Signature: (Ljava/lang/reflect/Method;)I | 80 oop result; |
96 */ | 81 if (nameSymbol == vmSymbols::int_signature()) { |
97 JNIEXPORT jint JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1accessFlags(JNIEnv *, jobject, jobject method) { | 82 result = VMExits::createRiTypePrimitive((int)T_INT, THREAD); |
98 return C1XObjects::getInternalMethod(method)->access_flags().as_int(); | 83 } else if (nameSymbol == vmSymbols::long_signature()) { |
99 } | 84 result = VMExits::createRiTypePrimitive((int)T_LONG, THREAD); |
100 | 85 } else if (nameSymbol == vmSymbols::bool_signature()) { |
101 /* | 86 result = VMExits::createRiTypePrimitive((int)T_BOOLEAN, THREAD); |
102 * Class: com_sun_hotspot_c1x_VMEntries | 87 } else if (nameSymbol == vmSymbols::char_signature()) { |
103 * Method: RiSignature_lookupType | 88 result = VMExits::createRiTypePrimitive((int)T_CHAR, THREAD); |
104 * Signature: (Ljava/lang/String;Lcom/sun/cri/ri/RiType;)Lcom/sun/cri/ri/RiType; | 89 } else if (nameSymbol == vmSymbols::short_signature()) { |
105 */ | 90 result = VMExits::createRiTypePrimitive((int)T_SHORT, THREAD); |
106 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiSignature_1lookupType(JNIEnv *, jobject, jstring name, jobject accessor) { | 91 } else if (nameSymbol == vmSymbols::byte_signature()) { |
107 VM_ENTRY_MARK | 92 result = VMExits::createRiTypePrimitive((int)T_BYTE, THREAD); |
108 klassOop k = C1XObjects::getInternalClass(accessor); | 93 } else if (nameSymbol == vmSymbols::double_signature()) { |
109 oop n = JNIHandles::resolve(name); | 94 result = VMExits::createRiTypePrimitive((int)T_DOUBLE, THREAD); |
110 if (n == NULL) { | 95 } else if (nameSymbol == vmSymbols::float_signature()) { |
111 THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "Name must not be null.", NULL); | 96 result = VMExits::createRiTypePrimitive((int)T_FLOAT, THREAD); |
112 } | 97 } else { |
113 oop result = C1XCompiler::get_RiType(n, k, THREAD); | 98 Handle classloader; |
99 Handle protectionDomain; | |
100 if (accessingClassVmId != 0) { | |
101 classloader = C1XObjects::get<klassOop>(accessingClassVmId)->klass_part()->class_loader(); | |
102 protectionDomain = C1XObjects::get<klassOop>(accessingClassVmId)->klass_part()->protection_domain(); | |
103 } | |
104 klassOop resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); | |
105 if (resolved_type != NULL) { | |
106 result = VMExits::createRiType(C1XObjects::add<klassOop>(resolved_type), name, THREAD); | |
107 } else { | |
108 result = VMExits::createRiTypeUnresolved(name, accessingClassVmId, THREAD); | |
109 } | |
110 } | |
111 | |
114 return JNIHandles::make_local(THREAD, result); | 112 return JNIHandles::make_local(THREAD, result); |
115 } | 113 } |
116 | 114 |
117 | 115 // public Object RiConstantPool_lookupConstant(HotSpotProxy constantPool, int cpi); |
118 /* | 116 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jlong vmId, jint index) { |
119 * Class: com_sun_hotspot_c1x_VMEntries | |
120 * Method: RiConstantPool_lookupConstant | |
121 * Signature: (Ljava/lang/Class;I)Ljava/lang/Object; | |
122 */ | |
123 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jobject cpHandle, jint index) { | |
124 VM_ENTRY_MARK; | 117 VM_ENTRY_MARK; |
125 klassOop klass = C1XObjects::getInternalClass(cpHandle); | 118 |
126 constantPoolOop cp = instanceKlass::cast(klass)->constants(); | 119 constantPoolOop cp = C1XObjects::get<constantPoolOop>(vmId); |
127 | 120 |
128 oop result = NULL; | 121 oop result = NULL; |
129 constantTag tag = cp->tag_at(index); | 122 constantTag tag = cp->tag_at(index); |
130 if (tag.is_int()) { | 123 if (tag.is_int()) { |
131 result = VMExits::createCiConstantInt(cp->int_at(index), CHECK_0); | 124 result = VMExits::createCiConstantInt(cp->int_at(index), CHECK_0); |
146 // TODO: Gracefully exit compilation. | 139 // TODO: Gracefully exit compilation. |
147 fatal("out of memory during compilation!"); | 140 fatal("out of memory during compilation!"); |
148 return NULL; | 141 return NULL; |
149 } | 142 } |
150 } | 143 } |
151 result = VMExits::createCiConstantObject(string, CHECK_0); | 144 result = VMExits::createCiConstantObject(C1XObjects::add<oop>(string), CHECK_0); |
152 } else if (tag.is_klass() || tag.is_unresolved_klass()) { | 145 } else if (tag.is_klass() || tag.is_unresolved_klass()) { |
153 | 146 |
154 // TODO: Return RiType object | 147 // TODO: Return RiType object |
155 ShouldNotReachHere(); | 148 ShouldNotReachHere(); |
156 // 4881222: allow ldc to take a class type | 149 // 4881222: allow ldc to take a class type |
157 //bool ignore; | 150 //bool ignore; |
158 //ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor); | 151 //ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor); |
165 // "must be an instance or array klass "); | 158 // "must be an instance or array klass "); |
166 //return ciConstant(T_OBJECT, klass); | 159 //return ciConstant(T_OBJECT, klass); |
167 } else if (tag.is_object()) { | 160 } else if (tag.is_object()) { |
168 oop obj = cp->object_at(index); | 161 oop obj = cp->object_at(index); |
169 assert(obj->is_instance(), "must be an instance"); | 162 assert(obj->is_instance(), "must be an instance"); |
170 result = VMExits::createCiConstantObject(obj, CHECK_0); | 163 result = VMExits::createCiConstantObject(C1XObjects::add<oop>(obj), CHECK_0); |
171 } else { | 164 } else { |
172 ShouldNotReachHere(); | 165 ShouldNotReachHere(); |
173 } | 166 } |
174 | 167 |
175 return JNIHandles::make_local(THREAD, result); | 168 return JNIHandles::make_local(THREAD, result); |
176 } | 169 } |
177 | 170 |
178 /* | 171 // public RiMethod RiConstantPool_lookupMethod(HotSpotProxy constantPool, int cpi, byte byteCode |
179 * Class: com_sun_hotspot_c1x_VMEntries | 172 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jlong vmId, jint index, jbyte byteCode) { |
180 * Method: RiConstantPool_lookupMethod | |
181 * Signature: (Ljava/lang/Object;I)Lcom/sun/cri/ri/RiMethod; | |
182 */ | |
183 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jobject cpHandle, jint index, jbyte byteCode) { | |
184 VM_ENTRY_MARK; | 173 VM_ENTRY_MARK; |
185 klassOop klass = C1XObjects::getInternalClass(cpHandle); | 174 |
186 constantPoolOop cp = instanceKlass::cast(klass)->constants(); | 175 constantPoolOop cp = C1XObjects::get<constantPoolOop>(vmId); |
187 // assert(cp->tag_at(cp->cache() != NULL ? cp->cache()->entry_at(index)->constant_pool_index() : index).is_method(), "reading field from non-field cp index"); | 176 |
188 Bytecodes::Code bc = (Bytecodes::Code)(((int)byteCode) & 0xFF); | 177 Bytecodes::Code bc = (Bytecodes::Code)(((int)byteCode) & 0xFF); |
189 ciInstanceKlass* loading_klass = (ciInstanceKlass *)CURRENT_ENV->get_object(cp->pool_holder()); | 178 ciInstanceKlass* loading_klass = (ciInstanceKlass *)CURRENT_ENV->get_object(cp->pool_holder()); |
190 ciMethod *method = CURRENT_ENV->get_method_by_index(cp, index, bc, loading_klass); | 179 ciMethod *cimethod = CURRENT_ENV->get_method_by_index(cp, index, bc, loading_klass); |
191 return JNIHandles::make_local(THREAD, VMExits::createRiMethod((methodOop)method->get_oop(), THREAD)); | 180 methodOop method = (methodOop)cimethod->get_oop(); |
192 } | 181 Handle name = C1XObjects::toString<Handle>(method->name(), CHECK_NULL); |
193 | 182 return JNIHandles::make_local(THREAD, VMExits::createRiMethod(C1XObjects::add<methodOop>(method), name, THREAD)); |
194 /* | 183 } |
195 * Class: com_sun_hotspot_c1x_VMEntries | 184 |
196 * Method: RiConstantPool_lookupSignature | 185 // public RiSignature RiConstantPool_lookupSignature(HotSpotProxy constantPool, int cpi); |
197 * Signature: (Ljava/lang/Object;I)Lcom/sun/cri/ri/RiSignature; | 186 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupSignature(JNIEnv *env, jobject, jlong vmId, jint index) { |
198 */ | |
199 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupSignature(JNIEnv *env, jobject, jobject cpHandle, jint index) { | |
200 fatal("currently unsupported"); | 187 fatal("currently unsupported"); |
201 return NULL; | 188 return NULL; |
202 } | 189 } |
203 | 190 |
204 /* | 191 // public RiType RiConstantPool_lookupType(HotSpotProxy constantPool, int cpi); |
205 * Class: com_sun_hotspot_c1x_VMEntries | 192 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupType(JNIEnv *env, jobject, jlong vmId, jint index) { |
206 * Method: RiConstantPool_lookupType | |
207 * Signature: (Ljava/lang/Object;I)Lcom/sun/cri/ri/RiType; | |
208 */ | |
209 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupType(JNIEnv *env, jobject, jobject cpHandle, jint index) { | |
210 VM_ENTRY_MARK; | 193 VM_ENTRY_MARK; |
211 klassOop cpKlass = C1XObjects::getInternalClass(cpHandle); | 194 |
212 constantPoolOop cp = instanceKlass::cast(cpKlass)->constants(); | 195 constantPoolOop cp = C1XObjects::get<constantPoolOop>(vmId); |
213 ciInstanceKlass* loading_klass = (ciInstanceKlass *)CURRENT_ENV->get_object(cpKlass); | 196 |
197 ciInstanceKlass* loading_klass = (ciInstanceKlass *)CURRENT_ENV->get_object(cp->pool_holder()); | |
214 bool is_accessible = false; | 198 bool is_accessible = false; |
215 ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, index, is_accessible, loading_klass); | 199 ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, index, is_accessible, loading_klass); |
216 return JNIHandles::make_local(THREAD, C1XCompiler::get_RiType(klass, cpKlass, THREAD)); | 200 return JNIHandles::make_local(THREAD, C1XCompiler::get_RiType(klass, cp->klass(), THREAD)); |
217 | 201 |
218 } | 202 } |
219 | 203 |
220 /* | 204 // public RiField RiConstantPool_lookupField(HotSpotProxy constantPool, int cpi); |
221 * Class: com_sun_hotspot_c1x_VMEntries | 205 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jlong vmId, jint index) { |
222 * Method: RiConstantPool_lookupField | |
223 * Signature: (Ljava/lang/Object;I)Lcom/sun/cri/ri/RiField; | |
224 */ | |
225 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject cpHandle, jint index) { | |
226 VM_ENTRY_MARK; | 206 VM_ENTRY_MARK; |
227 klassOop klass = C1XObjects::getInternalClass(cpHandle); | 207 |
228 constantPoolOop cp = instanceKlass::cast(klass)->constants(); | 208 constantPoolOop cp = C1XObjects::get<constantPoolOop>(vmId); |
229 // assert(cp->tag_at(cp->cache() != NULL ? cp->cache()->entry_at(index)->constant_pool_index() : index).is_field(), "reading field from non-field cp index"); | 209 |
230 ciInstanceKlass* loading_klass = (ciInstanceKlass *)CURRENT_ENV->get_object(cp->pool_holder()); | 210 ciInstanceKlass* loading_klass = (ciInstanceKlass *)CURRENT_ENV->get_object(cp->pool_holder()); |
231 ciField *field = CURRENT_ENV->get_field_by_index(loading_klass, index); | 211 ciField *field = CURRENT_ENV->get_field_by_index(loading_klass, index); |
232 return JNIHandles::make_local(THREAD, C1XCompiler::get_RiField(field, THREAD)); | 212 return JNIHandles::make_local(THREAD, C1XCompiler::get_RiField(field, THREAD)); |
233 } | 213 } |
234 | 214 |
235 /* | 215 // public RiConstantPool RiType_constantPool(HotSpotProxy type); |
236 * Class: com_sun_hotspot_c1x_VMEntries | 216 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1constantPool(JNIEnv *, jobject, jlong vmId) { |
237 * Method: RiType_name | 217 VM_ENTRY_MARK; |
238 * Signature: (Ljava/lang/Class;)Ljava/lang/String; | 218 |
239 */ | 219 constantPoolOop constantPool = instanceKlass::cast(C1XObjects::get<klassOop>(vmId))->constants(); |
240 JNIEXPORT jstring JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1name(JNIEnv *env, jobject, jobject klass) { | 220 return JNIHandles::make_local(VMExits::createRiConstantPool(C1XObjects::add<constantPoolOop>(constantPool), THREAD)); |
241 VM_ENTRY_MARK | 221 } |
242 klassOop k = C1XObjects::getInternalClass(klass); | 222 |
243 return (jstring)JNIHandles::make_local(java_lang_String::create_from_symbol(k->klass_part()->name(), Thread::current())()); | 223 // public boolean RiType_isArrayClass(HotSpotProxy klass); |
244 } | 224 JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isArrayClass(JNIEnv *, jobject, jlong vmId) { |
245 | 225 return C1XObjects::get<klassOop>(vmId)->klass_part()->oop_is_javaArray(); |
246 /* | 226 } |
247 * Class: com_sun_hotspot_c1x_VMEntries | 227 |
248 * Method: RiType_isArrayClass | 228 // public boolean RiType_isInstanceClass(HotSpotProxy klass); |
249 * Signature: (Ljava/lang/Class;)Z | 229 JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInstanceClass(JNIEnv *, jobject, jlong vmId) { |
250 */ | 230 return C1XObjects::get<klassOop>(vmId)->klass_part()->oop_is_instance(); |
251 JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isArrayClass(JNIEnv *, jobject, jobject klass) { | 231 } |
252 klassOop o = C1XObjects::getInternalClass(klass); | 232 |
253 return o->klass_part()->oop_is_array(); | 233 // public boolean RiType_isInterface(HotSpotProxy klass); |
254 } | 234 JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInterface(JNIEnv *, jobject, jlong vmId) { |
255 | 235 return C1XObjects::get<klassOop>(vmId)->klass_part()->is_interface(); |
256 /* | |
257 * Class: com_sun_hotspot_c1x_VMEntries | |
258 * Method: RiType_isInstanceClass | |
259 * Signature: (Ljava/lang/Class;)Z | |
260 */ | |
261 JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInstanceClass(JNIEnv *, jobject, jobject klass) { | |
262 klassOop o = C1XObjects::getInternalClass(klass); | |
263 return o->klass_part()->oop_is_instanceKlass(); | |
264 } | |
265 | |
266 /* | |
267 * Class: com_sun_hotspot_c1x_VMEntries | |
268 * Method: RiType_isInterface | |
269 * Signature: (Ljava/lang/Class;)Z | |
270 */ | |
271 JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInterface(JNIEnv *, jobject, jobject klass) { | |
272 klassOop o = C1XObjects::getInternalClass(klass); | |
273 return o->klass_part()->is_interface(); | |
274 } | 236 } |
275 | 237 |
276 | 238 |
277 // helpers used to set fields in the HotSpotVMConfig object | 239 // helpers used to set fields in the HotSpotVMConfig object |
278 jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { | 240 jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { |
285 } | 247 } |
286 | 248 |
287 void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } | 249 void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } |
288 void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } | 250 void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } |
289 void set_long(JNIEnv* env, jobject obj, const char* name, long value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } | 251 void set_long(JNIEnv* env, jobject obj, const char* name, long value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } |
252 void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); } | |
253 void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); } | |
290 | 254 |
291 jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } | 255 jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } |
292 jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } | 256 jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } |
257 jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); } | |
293 jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } | 258 jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } |
294 jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } | 259 jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } |
295 | 260 |
296 | 261 |
297 // Helpful routine for computing field offsets at run time rather than hardcoding them | 262 BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; |
298 int compute_offset(klassOop klass_oop, const char* name, const char* sig) { | 263 int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); |
299 JavaThread* THREAD = JavaThread::current(); | 264 |
300 fieldDescriptor fd; | 265 // public HotSpotVMConfig getConfiguration(); |
301 instanceKlass* ik = instanceKlass::cast(klass_oop); | |
302 symbolOop name_symbol = SymbolTable::probe(name, (int)strlen(name)); | |
303 symbolOop signature_symbol = SymbolTable::probe(sig, (int)strlen(sig)); | |
304 if (name_symbol == NULL || signature_symbol == NULL || !ik->find_local_field(name_symbol, signature_symbol, &fd)) { | |
305 ResourceMark rm; | |
306 tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); | |
307 fatal("Invalid layout of c1x4hotspot class"); | |
308 } | |
309 return fd.offset(); | |
310 } | |
311 | |
312 | |
313 class TypeHelper { | |
314 public: | |
315 jclass jniHotSpotType; | |
316 jclass jniHotSpotTargetMethod; | |
317 klassOop HotSpotType; | |
318 klassOop HotSpotTargetMethod; | |
319 int HotSpotType_klassOop; | |
320 | |
321 TypeHelper(JNIEnv* jniEnv) { | |
322 jniHotSpotType = jniEnv->FindClass("com/sun/hotspot/c1x/HotSpotType"); | |
323 jniHotSpotTargetMethod = jniEnv->FindClass("com/sun/hotspot/c1x/HotSpotTargetMethod"); | |
324 } | |
325 | |
326 void initialize() { | |
327 HotSpotType = java_lang_Class::as_klassOop(JNIHandles::resolve(jniHotSpotType)); | |
328 HotSpotTargetMethod = java_lang_Class::as_klassOop(JNIHandles::resolve(jniHotSpotTargetMethod)); | |
329 HotSpotType_klassOop = compute_offset(HotSpotType, "klass", "Ljava/lang/Class;"); | |
330 } | |
331 }; | |
332 | |
333 | |
334 | |
335 | |
336 /* | |
337 * Class: com_sun_hotspot_c1x_VMEntries | |
338 * Method: installCode | |
339 * Signature: (Lcom/sun/hotspot/c1x/HotSpotTargetMethod;)V | |
340 */ | |
341 JNIEXPORT void JNICALL Java_com_sun_hotspot_c1x_VMEntries_installCode(JNIEnv *jniEnv, jobject, jobject targetMethod) { | |
342 TypeHelper types(jniEnv); | |
343 | |
344 methodOop m = C1XObjects::getInternalMethod(get_object(jniEnv, targetMethod, "method", "Ljava/lang/reflect/Method;")); | |
345 jbyteArray code = (jbyteArray)get_object(jniEnv, targetMethod, "code", "[B"); | |
346 jint codeSize = get_int(jniEnv, targetMethod, "codeSize"); | |
347 jintArray relocationOffsetsObj = (jintArray)get_object(jniEnv, targetMethod, "relocationOffsets", "[I"); | |
348 jobjectArray relocationDataObj = (jobjectArray)get_object(jniEnv, targetMethod, "relocationData", "[Ljava/lang/Object;"); | |
349 jint frameSize = get_int(jniEnv, targetMethod, "frameSize"); | |
350 | |
351 assert(codeSize > 0 && codeSize <= ((arrayOop)JNIHandles::resolve(code))->length(), "invalid codeSize"); | |
352 | |
353 CodeOffsets offsets; | |
354 | |
355 // TODO: This is a hack.. Produce correct entries. | |
356 offsets.set_value(CodeOffsets::Exceptions, 0); | |
357 offsets.set_value(CodeOffsets::Deopt, 0); | |
358 | |
359 offsets.set_value(CodeOffsets::Entry, get_int(jniEnv, targetMethod, "unverifiedEntrypoint")); | |
360 offsets.set_value(CodeOffsets::Verified_Entry, get_int(jniEnv, targetMethod, "verifiedEntrypoint")); | |
361 | |
362 VM_ENTRY_MARK; | |
363 ciEnv *env = CURRENT_ENV; | |
364 | |
365 types.initialize(); | |
366 | |
367 env->set_oop_recorder(new OopRecorder(env->arena())); | |
368 env->set_debug_info(new DebugInformationRecorder(env->oop_recorder())); | |
369 env->set_dependencies(new Dependencies(env)); | |
370 ciMethod *ciMethodObject = (ciMethod *)env->get_object(m); | |
371 | |
372 int relocationCount = relocationOffsetsObj == NULL ? 0 : ((arrayOop)JNIHandles::resolve(relocationOffsetsObj))->length(); | |
373 | |
374 CodeBuffer buffer("c1x nmethod", codeSize, relocationCount * relocInfo::length_limit); | |
375 buffer.initialize_oop_recorder(env->oop_recorder()); | |
376 | |
377 // copy the code into the newly created CodeBuffer | |
378 CodeSection* instructions = buffer.insts(); | |
379 memcpy(instructions->start(), ((arrayOop)JNIHandles::resolve(code))->base(T_BYTE), codeSize); | |
380 instructions->set_end(instructions->start() + codeSize); | |
381 | |
382 if (relocationCount > 0) { | |
383 jint* relocationOffsets = (jint*)((arrayOop)JNIHandles::resolve(relocationOffsetsObj))->base(T_INT); | |
384 oop* relocationObjects = (oop*)((arrayOop)JNIHandles::resolve(relocationDataObj))->base(T_OBJECT); | |
385 | |
386 for (int i=0; i<relocationCount; i++) { | |
387 address inst = (address)instructions->start() + relocationOffsets[i]; | |
388 u_char inst_byte = *inst; | |
389 oop obj = relocationObjects[i]; | |
390 assert(obj != NULL, "NULL oop needn't be patched"); | |
391 | |
392 if (java_lang_boxing_object::is_instance(obj, T_LONG)) { | |
393 address operand = Assembler::locate_operand(inst, Assembler::call32_operand); | |
394 long dest = obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG)); | |
395 long disp = dest - (long)(operand + 4); | |
396 assert(disp == (int) disp, "disp doesn't fit in 32 bits"); | |
397 *((int*)operand) = (int)disp; | |
398 | |
399 instructions->relocate(inst, runtime_call_Relocation::spec(), Assembler::call32_operand); | |
400 tty->print_cr("relocating (Long) %02x at %016x/%016x", inst_byte, inst, operand); | |
401 } else if (obj->is_a(types.HotSpotType)) { | |
402 address operand = Assembler::locate_operand(inst, Assembler::imm_operand); | |
403 | |
404 *((jobject*)operand) = JNIHandles::make_local(C1XObjects::getInternalClass(obj->obj_field(types.HotSpotType_klassOop))); | |
405 instructions->relocate(inst, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); | |
406 tty->print_cr("relocating (HotSpotType) %02x at %016x/%016x", inst_byte, inst, operand); | |
407 } else { | |
408 tty->print_cr("unknown relocation type"); | |
409 } | |
410 } | |
411 } | |
412 | |
413 buffer.print(); | |
414 | |
415 address entry = instructions->start() + offsets.value(CodeOffsets::Verified_Entry); | |
416 | |
417 | |
418 OopMapSet oop_map_set; | |
419 ExceptionHandlerTable handler_table; | |
420 ImplicitExceptionTable inc_table; | |
421 { | |
422 ThreadToNativeFromVM t((JavaThread*)THREAD); | |
423 env->register_method(ciMethodObject, -1, &offsets, 0, &buffer, frameSize, &oop_map_set, &handler_table, &inc_table, NULL, env->comp_level(), false, false); | |
424 | |
425 } | |
426 } | |
427 | |
428 /* | |
429 * Class: com_sun_hotspot_c1x_VMEntries | |
430 * Method: getConfiguration | |
431 * Signature: ()Lcom/sun/hotspot/c1x/HotSpotVMConfig; | |
432 */ | |
433 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_getConfiguration(JNIEnv *env, jobject) { | 266 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_getConfiguration(JNIEnv *env, jobject) { |
434 tty->print_cr("Java_com_sun_hotspot_c1x_VMEntries_getConfiguration"); | 267 tty->print_cr("Java_com_sun_hotspot_c1x_VMEntries_getConfiguration"); |
435 jclass klass = env->FindClass("com/sun/hotspot/c1x/HotSpotVMConfig"); | 268 jclass klass = env->FindClass("com/sun/hotspot/c1x/HotSpotVMConfig"); |
436 assert(klass != NULL, "HotSpot vm config class not found"); | 269 assert(klass != NULL, "HotSpot vm config class not found"); |
437 jobject config = env->AllocObject(klass); | 270 jobject config = env->AllocObject(klass); |
443 set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); | 276 set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); |
444 set_int(env, config, "vmPageSize", os::vm_page_size()); | 277 set_int(env, config, "vmPageSize", os::vm_page_size()); |
445 set_int(env, config, "stackShadowPages", StackShadowPages); | 278 set_int(env, config, "stackShadowPages", StackShadowPages); |
446 set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); | 279 set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); |
447 set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); | 280 set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); |
448 set_long(env, config, "instanceofStub", (long)Runtime1::entry_for(Runtime1::slow_subtype_check_id)); | 281 |
449 set_long(env, config, "debugStub", (long)warning); | 282 set_long(env, config, "instanceofStub", C1XObjects::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); |
283 set_long(env, config, "debugStub", C1XObjects::addStub((address)warning)); | |
284 set_long(env, config, "resolveStaticCallStub", C1XObjects::addStub(SharedRuntime::get_resolve_static_call_stub())); | |
285 jintArray arrayOffsets = env->NewIntArray(basicTypeCount); | |
286 for (int i=0; i<basicTypeCount; i++) { | |
287 jint offset = arrayOopDesc::base_offset_in_bytes(basicTypes[i]); | |
288 env->SetIntArrayRegion(arrayOffsets, i, 1, &offset); | |
289 } | |
290 set_int_array(env, config, "arrayOffsets", arrayOffsets); | |
291 set_int(env, config, "arrayClassElementOffset", objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)); | |
450 return config; | 292 return config; |
451 } | 293 } |
452 | 294 |
295 #define C1X_REGISTER_COUNT 32 | |
296 | |
297 VMReg get_hotspot_reg(jint c1x_reg) { | |
298 Register cpu_registers[] = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 }; | |
299 XMMRegister xmm_registers[] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; | |
300 | |
301 if (c1x_reg < 16) { | |
302 return cpu_registers[c1x_reg]->as_VMReg(); | |
303 } else { | |
304 assert(c1x_reg < C1X_REGISTER_COUNT, "invalid register number"); | |
305 return xmm_registers[c1x_reg - 16]->as_VMReg(); | |
306 } | |
307 | |
308 } | |
309 | |
310 static OopMap* create_oop_map(jint frame_size, jint parameter_count, oop debug_info) { | |
311 OopMap* map = new OopMap(frame_size, parameter_count); | |
312 arrayOop register_map = (arrayOop)CiDebugInfo::registerRefMap(debug_info); | |
313 arrayOop frame_map = (arrayOop)CiDebugInfo::frameRefMap(debug_info); | |
314 | |
315 jint register_count = VMRegImpl::stack2reg(0)->value(); | |
316 tty->print_cr("register count: %i", register_count); | |
317 | |
318 for (jint i=0; i<C1X_REGISTER_COUNT; i++) { | |
319 unsigned char byte = ((unsigned char*)register_map->base(T_BYTE))[i / 8]; | |
320 bool is_oop = (byte & (1 << (i % 8))) != 0; | |
321 VMReg reg = get_hotspot_reg(i); | |
322 if (is_oop) { | |
323 map->set_oop(reg); | |
324 } else { | |
325 map->set_value(reg); | |
326 } | |
327 } | |
328 | |
329 for (jint i=0; i<frame_size; i++) { | |
330 unsigned char byte = ((unsigned char*)frame_map->base(T_BYTE))[i / 8]; | |
331 bool is_oop = (byte & (1 << (i % 8))) != 0; | |
332 VMReg reg = VMRegImpl::stack2reg(i); | |
333 if (is_oop) { | |
334 map->set_oop(reg); | |
335 } else { | |
336 map->set_value(reg); | |
337 } | |
338 } | |
339 | |
340 // TODO parameters? | |
341 return map; | |
342 } | |
343 | |
344 static ScopeValue* get_hotspot_value(oop value) { | |
345 fatal("not implemented"); | |
346 if (value->is_a(CiRegisterValue::klass())) { | |
347 tty->print("register value"); | |
348 value->print(); | |
349 } else if (value->is_a(CiStackSlot::klass())) { | |
350 tty->print("stack value"); | |
351 value->print(); | |
352 } else { | |
353 ShouldNotReachHere(); | |
354 } | |
355 } | |
356 | |
357 | |
358 class CodeInstaller { | |
359 private: | |
360 ciEnv* _env; | |
361 | |
362 oop _citarget_method; | |
363 oop _hotspot_method; | |
364 oop _name; | |
365 arrayOop _sites; | |
366 CodeOffsets _offsets; | |
367 | |
368 arrayOop _code; | |
369 jint _code_size; | |
370 jint _frame_size; | |
371 jint _parameter_count; | |
372 jint _constants_size; | |
373 jint _total_size; | |
374 | |
375 CodeSection* _instructions; | |
376 CodeSection* _constants; | |
377 | |
378 OopRecorder* _oop_recorder; | |
379 DebugInformationRecorder* _debug_recorder; | |
380 Dependencies* _dependencies; | |
381 | |
382 public: | |
383 | |
384 // constructor used to create a method | |
385 CodeInstaller(oop target_method) { | |
386 VM_ENTRY_MARK; | |
387 _env = CURRENT_ENV; | |
388 | |
389 initialize_fields(target_method); | |
390 assert(_hotspot_method != NULL && _name == NULL, "installMethod needs NON-NULL method and NULL name"); | |
391 | |
392 | |
393 // TODO: This is a hack.. Produce correct entries. | |
394 _offsets.set_value(CodeOffsets::Exceptions, 0); | |
395 _offsets.set_value(CodeOffsets::Deopt, 0); | |
396 | |
397 methodOop method = C1XObjects::get<methodOop>(HotSpotMethod::vmId(_hotspot_method)); | |
398 ciMethod *ciMethodObject = (ciMethod *)_env->get_object(method); | |
399 _parameter_count = method->size_of_parameters(); | |
400 | |
401 // (very) conservative estimate: each site needs a relocation | |
402 CodeBuffer buffer("temp c1x method", _total_size, _sites->length() * relocInfo::length_limit); | |
403 initialize_buffer(buffer); | |
404 ExceptionHandlerTable handler_table; | |
405 ImplicitExceptionTable inc_table; | |
406 { | |
407 ThreadToNativeFromVM t((JavaThread*)THREAD); | |
408 _env->register_method(ciMethodObject, -1, &_offsets, 0, &buffer, _frame_size, _debug_recorder->_oopmaps, &handler_table, &inc_table, NULL, _env->comp_level(), false, false); | |
409 } | |
410 } | |
411 | |
412 // constructor used to create a stub | |
413 CodeInstaller(oop target_method, jlong& id) { | |
414 VM_ENTRY_MARK; | |
415 _env = CURRENT_ENV; | |
416 | |
417 initialize_fields(target_method); | |
418 assert(_hotspot_method == NULL && _name != NULL, "installMethod needs NON-NULL name and NULL method"); | |
419 | |
420 // (very) conservative estimate: each site needs a relocation | |
421 CodeBuffer buffer("temp c1x stub", _total_size, _sites->length() * relocInfo::length_limit); | |
422 initialize_buffer(buffer); | |
423 | |
424 const char* cname = java_lang_String::as_utf8_string(_name); | |
425 BufferBlob* blob = BufferBlob::create(strdup(cname), &buffer); // this is leaking strings... but only a limited number of stubs will be created | |
426 Disassembler::decode((CodeBlob*)blob); | |
427 id = C1XObjects::addStub(blob->instructions_begin()); | |
428 } | |
429 | |
430 private: | |
431 void initialize_fields(oop target_method) { | |
432 _citarget_method = HotSpotTargetMethod::targetMethod(target_method); | |
433 _hotspot_method = HotSpotTargetMethod::method(target_method); | |
434 _name = HotSpotTargetMethod::name(target_method); | |
435 _sites = (arrayOop)HotSpotTargetMethod::sites(target_method); | |
436 | |
437 _code = (arrayOop)CiTargetMethod::targetCode(_citarget_method); | |
438 _code_size = CiTargetMethod::targetCodeSize(_citarget_method); | |
439 _frame_size = CiTargetMethod::frameSize(_citarget_method); | |
440 | |
441 // (very) conservative estimate: each site needs a constant section entry | |
442 _constants_size = _sites->length() * BytesPerLong; | |
443 _total_size = align_size_up(_code_size, HeapWordSize) + _constants_size; | |
444 } | |
445 | |
446 void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { | |
447 | |
448 } | |
449 | |
450 void record_frame(jint pc_offset, oop code_pos, oop frame) { | |
451 oop caller_pos = CiCodePos::caller(code_pos); | |
452 if (caller_pos != NULL) { | |
453 oop caller_frame = CiDebugInfo_Frame::caller(frame); | |
454 record_frame(pc_offset, caller_pos, caller_frame); | |
455 } else { | |
456 assert(frame == NULL || CiDebugInfo_Frame::caller(frame) == NULL, "unexpected layout - different nesting of Frame and CiCodePos"); | |
457 } | |
458 | |
459 assert(frame == NULL || code_pos == CiDebugInfo_Frame::codePos(frame), "unexpected CiCodePos layout"); | |
460 | |
461 oop hotspot_method = CiCodePos::method(code_pos); | |
462 methodOop method = C1XObjects::get<methodOop>(HotSpotMethod::vmId(hotspot_method)); | |
463 ciMethod *cimethod = (ciMethod *)_env->get_object(method); | |
464 jint bci = CiCodePos::bci(code_pos); | |
465 | |
466 if (frame != NULL) { | |
467 jint local_count = CiDebugInfo_Frame::numLocals(frame); | |
468 jint expression_count = CiDebugInfo_Frame::numStack(frame); | |
469 jint monitor_count = CiDebugInfo_Frame::numLocks(frame); | |
470 arrayOop values = (arrayOop)CiDebugInfo_Frame::values(frame); | |
471 | |
472 assert(local_count + expression_count + monitor_count == values->length(), "unexpected values length"); | |
473 assert(monitor_count == 0, "monitors not supported"); | |
474 | |
475 GrowableArray<ScopeValue*>* locals = new GrowableArray<ScopeValue*>(); | |
476 GrowableArray<ScopeValue*>* expressions = new GrowableArray<ScopeValue*>(); | |
477 GrowableArray<MonitorValue*>* monitors = new GrowableArray<MonitorValue*>(); | |
478 | |
479 for (jint i=0; i<values->length(); i++) { | |
480 ScopeValue* value = get_hotspot_value(((oop*)values->base(T_OBJECT))[i]); | |
481 | |
482 if (i < local_count) { | |
483 locals->append(value); | |
484 } else if (i < local_count + expression_count) { | |
485 expressions->append(value); | |
486 } else { | |
487 ShouldNotReachHere(); | |
488 // monitors->append(value); | |
489 } | |
490 } | |
491 DebugToken* locals_token = _debug_recorder->create_scope_values(locals); | |
492 DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); | |
493 DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors); | |
494 | |
495 _debug_recorder->describe_scope(pc_offset, cimethod, bci, false, false, false, locals_token, expressions_token, monitors_token); | |
496 } else { | |
497 _debug_recorder->describe_scope(pc_offset, cimethod, bci, false, false, false, NULL, NULL, NULL); | |
498 } | |
499 } | |
500 | |
501 void site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { | |
502 oop runtime_call = CiTargetMethod_Call::runtimeCall(site); | |
503 oop hotspot_method = CiTargetMethod_Call::method(site); | |
504 oop symbol = CiTargetMethod_Call::symbol(site); | |
505 oop global_stub = CiTargetMethod_Call::globalStubID(site); | |
506 | |
507 oop debug_info = CiTargetMethod_Call::debugInfo(site); | |
508 arrayOop stack_map = (arrayOop)CiTargetMethod_Call::stackMap(site); | |
509 arrayOop register_map = (arrayOop)CiTargetMethod_Call::registerMap(site); | |
510 | |
511 assert((runtime_call ? 1 : 0) + (hotspot_method ? 1 : 0) + (symbol ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type"); | |
512 | |
513 if (runtime_call != NULL) { | |
514 tty->print_cr("runtime_call"); | |
515 } else if (global_stub != NULL) { | |
516 tty->print_cr("global_stub_id"); | |
517 } else if (symbol != NULL) { | |
518 tty->print_cr("symbol"); | |
519 } else { // method != NULL | |
520 assert(hotspot_method->is_a(SystemDictionary::HotSpotMethod_klass()), "unexpected RiMethod subclass"); | |
521 methodOop method = C1XObjects::get<methodOop>(HotSpotMethod::vmId(hotspot_method)); | |
522 | |
523 address instruction = _instructions->start() + pc_offset; | |
524 address operand = Assembler::locate_operand(instruction, Assembler::call32_operand); | |
525 address next_instruction = Assembler::locate_next_instruction(instruction); | |
526 jint next_pc_offset = next_instruction - _instructions->start(); | |
527 | |
528 assert(debug_info != NULL, "debug info expected"); | |
529 _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info)); | |
530 oop code_pos = CiDebugInfo::codePos(debug_info); | |
531 oop frame = CiDebugInfo::frame(debug_info); | |
532 record_frame(next_pc_offset, code_pos, frame); | |
533 | |
534 if (method->is_static()) { | |
535 tty->print_cr("static method"); | |
536 | |
537 | |
538 address dest = SharedRuntime::get_resolve_static_call_stub(); | |
539 long disp = dest - next_instruction; | |
540 assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); | |
541 *((jint*)operand) = (jint)disp; | |
542 | |
543 _instructions->relocate(instruction, relocInfo::static_call_type, Assembler::call32_operand); | |
544 tty->print_cr("relocating (Long) %016x/%016x", instruction, operand); | |
545 } else { | |
546 tty->print_cr("non-static method"); | |
547 ShouldNotReachHere(); | |
548 } | |
549 | |
550 _debug_recorder->end_safepoint(pc_offset); | |
551 } | |
552 } | |
553 | |
554 void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { | |
555 oop constant = CiTargetMethod_DataPatch::constant(site); | |
556 oop kind = CiConstant::kind(constant); | |
557 | |
558 address instruction = _instructions->start() + pc_offset; | |
559 address operand = Assembler::locate_operand(instruction, Assembler::disp32_operand); | |
560 address next_instruction = Assembler::locate_next_instruction(instruction); | |
561 | |
562 switch(CiKind::typeChar(kind)) { | |
563 case 'z': | |
564 case 'b': | |
565 case 's': | |
566 case 'c': | |
567 case 'i': | |
568 fatal("int-sized values not expected in DataPatch"); | |
569 break; | |
570 case 'f': | |
571 case 'l': | |
572 case 'd': { | |
573 // we don't care if this is a long/double/etc., the primitive field contains the right bits | |
574 address dest = _constants->end(); | |
575 *(jlong*)dest = CiConstant::primitive(constant); | |
576 _constants->set_end(dest + BytesPerLong); | |
577 | |
578 long disp = dest - next_instruction; | |
579 assert(disp == (jint) disp, "disp doesn't fit in 32 bits"); | |
580 *((jint*)operand) = (jint)disp; | |
581 | |
582 _instructions->relocate(instruction, section_word_Relocation::spec((address)dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); | |
583 tty->print_cr("relocating (Float/Long/Double) at %016x/%016x", instruction, operand); | |
584 break; | |
585 } | |
586 case 'a': | |
587 CiConstant::object(constant)->print(); | |
588 tty->print_cr("DataPatch of object type"); | |
589 break; | |
590 default: | |
591 fatal("unexpected CiKind in DataPatch"); | |
592 break; | |
593 } | |
594 } | |
595 | |
596 void site_ExceptionHandler(CodeBuffer& buffer, jint pc_offset, oop site) { | |
597 | |
598 } | |
599 | |
600 void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { | |
601 oop id_obj = CiTargetMethod_Mark::id(site); | |
602 arrayOop references = (arrayOop)CiTargetMethod_Mark::references(site); | |
603 | |
604 if (id_obj != NULL) { | |
605 assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected"); | |
606 jint id = id_obj->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT)); | |
607 | |
608 address instruction = _instructions->start() + pc_offset; | |
609 | |
610 switch (id) { | |
611 case C1XCompiler::MARK_UNVERIFIED_ENTRY: | |
612 _offsets.set_value(CodeOffsets::Entry, pc_offset); | |
613 break; | |
614 case C1XCompiler::MARK_VERIFIED_ENTRY: | |
615 _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset); | |
616 break; | |
617 case C1XCompiler::MARK_STATIC_CALL_STUB: { | |
618 assert(references->length() == 1, "static call stub needs one reference"); | |
619 oop ref = ((oop*)references->base(T_OBJECT))[0]; | |
620 address call_pc = _instructions->start() + CiTargetMethod_Site::pcOffset(ref); | |
621 _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc)); | |
622 break; | |
623 } | |
624 } | |
625 } | |
626 } | |
627 | |
628 // perform data and call relocation on the CodeBuffer | |
629 void initialize_buffer(CodeBuffer& buffer) { | |
630 _oop_recorder = new OopRecorder(_env->arena()); | |
631 _env->set_oop_recorder(_oop_recorder); | |
632 _debug_recorder = new DebugInformationRecorder(_env->oop_recorder()); | |
633 _debug_recorder->set_oopmaps(new OopMapSet()); | |
634 _dependencies = new Dependencies(_env); | |
635 | |
636 _env->set_oop_recorder(_oop_recorder); | |
637 _env->set_debug_info(_debug_recorder); | |
638 _env->set_dependencies(_dependencies); | |
639 buffer.initialize_oop_recorder(_oop_recorder); | |
640 | |
641 buffer.initialize_consts_size(_constants_size); | |
642 _instructions = buffer.insts(); | |
643 _constants = buffer.consts(); | |
644 | |
645 // copy the code into the newly created CodeBuffer | |
646 memcpy(_instructions->start(), _code->base(T_BYTE), _code_size); | |
647 _instructions->set_end(_instructions->start() + _code_size); | |
648 | |
649 oop* sites = (oop*)_sites->base(T_OBJECT); | |
650 for (int i=0; i<_sites->length(); i++) { | |
651 oop site = sites[i]; | |
652 jint pc_offset = CiTargetMethod_Site::pcOffset(site); | |
653 | |
654 if (site->is_a(CiTargetMethod_Safepoint::klass())) { | |
655 tty->print_cr("safepoint at %i", pc_offset); | |
656 site_Safepoint(buffer, pc_offset, site); | |
657 } else if (site->is_a(CiTargetMethod_Call::klass())) { | |
658 tty->print_cr("call at %i", pc_offset); | |
659 site_Call(buffer, pc_offset, site); | |
660 } else if (site->is_a(CiTargetMethod_DataPatch::klass())) { | |
661 tty->print_cr("datapatch at %i", pc_offset); | |
662 site_DataPatch(buffer, pc_offset, site); | |
663 } else if (site->is_a(CiTargetMethod_ExceptionHandler::klass())) { | |
664 tty->print_cr("exception handler at %i", pc_offset); | |
665 site_ExceptionHandler(buffer, pc_offset, site); | |
666 } else if (site->is_a(CiTargetMethod_Mark::klass())) { | |
667 tty->print_cr("mark at %i", pc_offset); | |
668 site_Mark(buffer, pc_offset, site); | |
669 } else { | |
670 ShouldNotReachHere(); | |
671 } | |
672 } | |
673 | |
674 /* | |
675 if (_relocation_count > 0) { | |
676 jint* relocation_offsets = (jint*)((arrayOop)JNIHandles::resolve(_relocation_offsets))->base(T_INT); | |
677 oop* relocation_objects = (oop*)((arrayOop)JNIHandles::resolve(_relocation_data))->base(T_OBJECT); | |
678 | |
679 for (int i = 0; i < _relocation_count; i++) { | |
680 address inst = (address)instructions->start() + relocation_offsets[i]; | |
681 u_char inst_byte = *inst; | |
682 oop obj = relocation_objects[i]; | |
683 assert(obj != NULL, "NULL oop needn't be patched"); | |
684 | |
685 if (obj->is_a(SystemDictionary::HotSpotProxy_klass())) { | |
686 jlong id = com_sun_hotspot_c1x_HotSpotProxy::get_id(obj); | |
687 switch (id & C1XObjects::TYPE_MASK) { | |
688 case C1XObjects::CONSTANT: { | |
689 address operand = Assembler::locate_operand(inst, Assembler::imm_operand); | |
690 | |
691 *((jobject*)operand) = JNIHandles::make_local(C1XObjects::get<oop>(id)); | |
692 instructions->relocate(inst, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); | |
693 tty->print_cr("relocating (HotSpotType) %02x at %016x/%016x", inst_byte, inst, operand); | |
694 break; | |
695 } | |
696 case C1XObjects::STUB: { | |
697 address operand = Assembler::locate_operand(inst, Assembler::call32_operand); | |
698 | |
699 long dest = (long)C1XObjects::getStub(id); | |
700 long disp = dest - (long)(operand + 4); | |
701 assert(disp == (int) disp, "disp doesn't fit in 32 bits"); | |
702 *((int*)operand) = (int)disp; | |
703 | |
704 instructions->relocate(inst, runtime_call_Relocation::spec(), Assembler::call32_operand); | |
705 tty->print_cr("relocating (Long) %02x at %016x/%016x", inst_byte, inst, operand); | |
706 break; | |
707 } | |
708 } | |
709 } else if (java_lang_boxing_object::is_instance(obj)) { | |
710 address operand = Assembler::locate_operand(inst, Assembler::disp32_operand); | |
711 long dest = (long)constants->end(); | |
712 if (java_lang_boxing_object::is_instance(obj, T_LONG)) { | |
713 // tty->print("relocate: %l\n", obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); | |
714 *(jlong*)constants->end() = obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG)); | |
715 } else if (java_lang_boxing_object::is_instance(obj, T_DOUBLE)) { | |
716 // tty->print("relocate: %f\n", obj->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); | |
717 *(jdouble*)constants->end() = obj->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE)); | |
718 } else if (java_lang_boxing_object::is_instance(obj, T_FLOAT)) { | |
719 // tty->print("relocate: %f\n", obj->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); | |
720 *(jfloat*)constants->end() = obj->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT)); | |
721 } | |
722 constants->set_end(constants->end() + 8); | |
723 | |
724 long disp = dest - (long)(operand + 4); | |
725 assert(disp == (int) disp, "disp doesn't fit in 32 bits"); | |
726 *((int*)operand) = (int)disp; | |
727 | |
728 instructions->relocate(inst, section_word_Relocation::spec((address)dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); | |
729 tty->print_cr("relocating (Long/Double) %02x at %016x/%016x", inst_byte, inst, operand); | |
730 } else if (obj->is_a(_types.HotSpotTypeResolved)) { | |
731 address operand = Assembler::locate_operand(inst, Assembler::imm_operand); | |
732 | |
733 *((jobject*)operand) = JNIHandles::make_local(C1XObjects::get<klassOop>(obj->obj_field(_types.HotSpotTypeResolved_klassOop))); | |
734 instructions->relocate(inst, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); | |
735 tty->print_cr("relocating (HotSpotType) %02x at %016x/%016x", inst_byte, inst, operand); | |
736 } else { | |
737 tty->print_cr("unknown relocation type"); | |
738 obj->print(); | |
739 } | |
740 } | |
741 }*/ | |
742 } | |
743 }; | |
744 | |
745 // public void installMethod(HotSpotTargetMethod targetMethod); | |
746 JNIEXPORT void JNICALL Java_com_sun_hotspot_c1x_VMEntries_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod) { | |
747 CodeInstaller installer(JNIHandles::resolve(targetMethod)); | |
748 } | |
749 | |
750 // public HotSpotProxy installStub(HotSpotTargetMethod targetMethod, String name); | |
751 JNIEXPORT jlong JNICALL Java_com_sun_hotspot_c1x_VMEntries_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { | |
752 jlong id; | |
753 CodeInstaller installer(JNIHandles::resolve(targetMethod), id); | |
754 return id; | |
755 } | |
756 | |
757 | |
758 | |
759 | |
760 #define CC (char*) /*cast a literal from (const char*)*/ | |
761 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) | |
762 | |
763 #define PROXY "J" | |
764 #define TYPE "Lcom/sun/cri/ri/RiType;" | |
765 #define METHOD "Lcom/sun/cri/ri/RiMethod;" | |
766 #define SIGNATURE "Lcom/sun/cri/ri/RiSignature;" | |
767 #define FIELD "Lcom/sun/cri/ri/RiField;" | |
768 #define CONSTANT_POOL "Lcom/sun/cri/ri/RiConstantPool;" | |
769 #define TARGET_METHOD "Lcom/sun/hotspot/c1x/HotSpotTargetMethod;" | |
770 #define CONFIG "Lcom/sun/hotspot/c1x/HotSpotVMConfig;" | |
771 #define HS_METHOD "Lcom/sun/hotspot/c1x/HotSpotMethod;" | |
772 #define CI_CONSTANT "Lcom/sun/cri/ci/CiConstant;" | |
773 #define STRING "Ljava/lang/String;" | |
774 #define OBJECT "Ljava/lang/Object;" | |
453 | 775 |
454 JNINativeMethod VMEntries_methods[] = { | 776 JNINativeMethod VMEntries_methods[] = { |
455 {CC"RiMethod_code", CC"(Ljava/lang/reflect/Method;)[B", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1code)}, | 777 {CC"RiMethod_code", CC"("PROXY")[B", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1code)}, |
456 {CC"RiMethod_maxStackSize", CC"(Ljava/lang/reflect/Method;)I", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxStackSize)}, | 778 {CC"RiMethod_maxStackSize", CC"("PROXY")I", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxStackSize)}, |
457 {CC"RiMethod_maxLocals", CC"(Ljava/lang/reflect/Method;)I", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxLocals)}, | 779 {CC"RiMethod_maxLocals", CC"("PROXY")I", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1maxLocals)}, |
458 {CC"RiMethod_holder", CC"(Ljava/lang/reflect/Method;)Lcom/sun/cri/ri/RiType;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1holder)}, | 780 {CC"RiMethod_holder", CC"("PROXY")"TYPE, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1holder)}, |
459 {CC"RiMethod_signature", CC"(Ljava/lang/reflect/Method;)Ljava/lang/String;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1signature)}, | 781 {CC"RiMethod_signature", CC"("PROXY")"STRING, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1signature)}, |
460 {CC"RiMethod_name", CC"(Ljava/lang/reflect/Method;)Ljava/lang/String;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1name)}, | 782 {CC"RiMethod_accessFlags", CC"("PROXY")I", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1accessFlags)}, |
461 {CC"RiMethod_accessFlags", CC"(Ljava/lang/reflect/Method;)I", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiMethod_1accessFlags)}, | 783 {CC"RiSignature_lookupType", CC"("STRING PROXY")"TYPE, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiSignature_1lookupType)}, |
462 {CC"RiSignature_lookupType", CC"(Ljava/lang/String;Ljava/lang/Class;)Lcom/sun/cri/ri/RiType;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiSignature_1lookupType)}, | 784 {CC"RiConstantPool_lookupConstant", CC"("PROXY"I)"CI_CONSTANT, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupConstant)}, |
463 {CC"RiType_name", CC"(Ljava/lang/Class;)Ljava/lang/String;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1name)}, | 785 {CC"RiConstantPool_lookupMethod", CC"("PROXY"IB)"METHOD, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupMethod)}, |
464 {CC"RiConstantPool_lookupConstant", CC"(Ljava/lang/Class;I)Ljava/lang/Object;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupConstant)}, | 786 {CC"RiConstantPool_lookupSignature", CC"("PROXY"I)"SIGNATURE, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupSignature)}, |
465 {CC"RiConstantPool_lookupMethod", CC"(Ljava/lang/Class;IB)Lcom/sun/cri/ri/RiMethod;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupMethod)}, | 787 {CC"RiConstantPool_lookupType", CC"("PROXY"I)"TYPE, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupType)}, |
466 {CC"RiConstantPool_lookupSignature", CC"(Ljava/lang/Class;I)Lcom/sun/cri/ri/RiSignature;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupSignature)}, | 788 {CC"RiConstantPool_lookupField", CC"("PROXY"I)"FIELD, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupField)}, |
467 {CC"RiConstantPool_lookupType", CC"(Ljava/lang/Class;I)Lcom/sun/cri/ri/RiType;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupType)}, | 789 {CC"RiType_constantPool", CC"("PROXY")"CONSTANT_POOL, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1constantPool)}, |
468 {CC"RiConstantPool_lookupField", CC"(Ljava/lang/Class;I)Lcom/sun/cri/ri/RiField;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiConstantPool_1lookupField)}, | 790 {CC"RiType_isArrayClass", CC"("PROXY")Z", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1isArrayClass)}, |
469 {CC"RiType_isArrayClass", CC"(Ljava/lang/Class;)Z", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1isArrayClass)}, | 791 {CC"RiType_isInstanceClass", CC"("PROXY")Z", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInstanceClass)}, |
470 {CC"RiType_isInstanceClass", CC"(Ljava/lang/Class;)Z", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInstanceClass)}, | 792 {CC"RiType_isInterface", CC"("PROXY")Z", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInterface)}, |
471 {CC"RiType_isInterface", CC"(Ljava/lang/Class;)Z", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_RiType_1isInterface)}, | 793 {CC"getConfiguration", CC"()"CONFIG, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_getConfiguration)}, |
472 {CC"installCode", CC"(Lcom/sun/hotspot/c1x/HotSpotTargetMethod;)V", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_installCode)}, | 794 {CC"installMethod", CC"("TARGET_METHOD")V", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_installMethod)}, |
473 {CC"getConfiguration", CC"()Lcom/sun/hotspot/c1x/HotSpotVMConfig;", FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_getConfiguration)} | 795 {CC"installStub", CC"("TARGET_METHOD")"PROXY, FN_PTR(Java_com_sun_hotspot_c1x_VMEntries_installStub)} |
474 }; | 796 }; |
475 | 797 |
476 int VMEntries_methods_count() { | 798 int VMEntries_methods_count() { |
477 return sizeof(VMEntries_methods) / sizeof(JNINativeMethod); | 799 return sizeof(VMEntries_methods) / sizeof(JNINativeMethod); |
478 } | 800 } |