Mercurial > hg > graal-compiler
comparison src/cpu/x86/vm/sharedRuntime_x86_32.cpp @ 4873:0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
Reviewed-by: kvn
author | never |
---|---|
date | Wed, 01 Feb 2012 16:57:08 -0800 |
parents | 5432047c7db7 |
children | 1d7922586cf6 |
comparison
equal
deleted
inserted
replaced
4872:aa3d708d67c4 | 4873:0382d2b469b2 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
1089 __ movptr(rax, Address(rbp, -wordSize)); | 1089 __ movptr(rax, Address(rbp, -wordSize)); |
1090 } | 1090 } |
1091 } | 1091 } |
1092 } | 1092 } |
1093 | 1093 |
1094 | |
1095 static void save_or_restore_arguments(MacroAssembler* masm, | |
1096 const int stack_slots, | |
1097 const int total_in_args, | |
1098 const int arg_save_area, | |
1099 OopMap* map, | |
1100 VMRegPair* in_regs, | |
1101 BasicType* in_sig_bt) { | |
1102 // if map is non-NULL then the code should store the values, | |
1103 // otherwise it should load them. | |
1104 int handle_index = 0; | |
1105 // Save down double word first | |
1106 for ( int i = 0; i < total_in_args; i++) { | |
1107 if (in_regs[i].first()->is_XMMRegister() && in_sig_bt[i] == T_DOUBLE) { | |
1108 int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; | |
1109 int offset = slot * VMRegImpl::stack_slot_size; | |
1110 handle_index += 2; | |
1111 assert(handle_index <= stack_slots, "overflow"); | |
1112 if (map != NULL) { | |
1113 __ movdbl(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); | |
1114 } else { | |
1115 __ movdbl(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); | |
1116 } | |
1117 } | |
1118 if (in_regs[i].first()->is_Register() && in_sig_bt[i] == T_LONG) { | |
1119 int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; | |
1120 int offset = slot * VMRegImpl::stack_slot_size; | |
1121 handle_index += 2; | |
1122 assert(handle_index <= stack_slots, "overflow"); | |
1123 if (map != NULL) { | |
1124 __ movl(Address(rsp, offset), in_regs[i].first()->as_Register()); | |
1125 if (in_regs[i].second()->is_Register()) { | |
1126 __ movl(Address(rsp, offset + 4), in_regs[i].second()->as_Register()); | |
1127 } | |
1128 } else { | |
1129 __ movl(in_regs[i].first()->as_Register(), Address(rsp, offset)); | |
1130 if (in_regs[i].second()->is_Register()) { | |
1131 __ movl(in_regs[i].second()->as_Register(), Address(rsp, offset + 4)); | |
1132 } | |
1133 } | |
1134 } | |
1135 } | |
1136 // Save or restore single word registers | |
1137 for ( int i = 0; i < total_in_args; i++) { | |
1138 if (in_regs[i].first()->is_Register()) { | |
1139 int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; | |
1140 int offset = slot * VMRegImpl::stack_slot_size; | |
1141 assert(handle_index <= stack_slots, "overflow"); | |
1142 if (in_sig_bt[i] == T_ARRAY && map != NULL) { | |
1143 map->set_oop(VMRegImpl::stack2reg(slot));; | |
1144 } | |
1145 | |
1146 // Value is in an input register pass we must flush it to the stack | |
1147 const Register reg = in_regs[i].first()->as_Register(); | |
1148 switch (in_sig_bt[i]) { | |
1149 case T_ARRAY: | |
1150 if (map != NULL) { | |
1151 __ movptr(Address(rsp, offset), reg); | |
1152 } else { | |
1153 __ movptr(reg, Address(rsp, offset)); | |
1154 } | |
1155 break; | |
1156 case T_BOOLEAN: | |
1157 case T_CHAR: | |
1158 case T_BYTE: | |
1159 case T_SHORT: | |
1160 case T_INT: | |
1161 if (map != NULL) { | |
1162 __ movl(Address(rsp, offset), reg); | |
1163 } else { | |
1164 __ movl(reg, Address(rsp, offset)); | |
1165 } | |
1166 break; | |
1167 case T_OBJECT: | |
1168 default: ShouldNotReachHere(); | |
1169 } | |
1170 } else if (in_regs[i].first()->is_XMMRegister()) { | |
1171 if (in_sig_bt[i] == T_FLOAT) { | |
1172 int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; | |
1173 int offset = slot * VMRegImpl::stack_slot_size; | |
1174 assert(handle_index <= stack_slots, "overflow"); | |
1175 if (map != NULL) { | |
1176 __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); | |
1177 } else { | |
1178 __ movflt(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); | |
1179 } | |
1180 } | |
1181 } else if (in_regs[i].first()->is_stack()) { | |
1182 if (in_sig_bt[i] == T_ARRAY && map != NULL) { | |
1183 int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); | |
1184 map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots)); | |
1185 } | |
1186 } | |
1187 } | |
1188 } | |
1189 | |
1190 // Check GC_locker::needs_gc and enter the runtime if it's true. This | |
1191 // keeps a new JNI critical region from starting until a GC has been | |
1192 // forced. Save down any oops in registers and describe them in an | |
1193 // OopMap. | |
1194 static void check_needs_gc_for_critical_native(MacroAssembler* masm, | |
1195 Register thread, | |
1196 int stack_slots, | |
1197 int total_c_args, | |
1198 int total_in_args, | |
1199 int arg_save_area, | |
1200 OopMapSet* oop_maps, | |
1201 VMRegPair* in_regs, | |
1202 BasicType* in_sig_bt) { | |
1203 __ block_comment("check GC_locker::needs_gc"); | |
1204 Label cont; | |
1205 __ cmp8(ExternalAddress((address)GC_locker::needs_gc_address()), false); | |
1206 __ jcc(Assembler::equal, cont); | |
1207 | |
1208 // Save down any incoming oops and call into the runtime to halt for a GC | |
1209 | |
1210 OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); | |
1211 | |
1212 save_or_restore_arguments(masm, stack_slots, total_in_args, | |
1213 arg_save_area, map, in_regs, in_sig_bt); | |
1214 | |
1215 address the_pc = __ pc(); | |
1216 oop_maps->add_gc_map( __ offset(), map); | |
1217 __ set_last_Java_frame(thread, rsp, noreg, the_pc); | |
1218 | |
1219 __ block_comment("block_for_jni_critical"); | |
1220 __ push(thread); | |
1221 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::block_for_jni_critical))); | |
1222 __ increment(rsp, wordSize); | |
1223 | |
1224 __ get_thread(thread); | |
1225 __ reset_last_Java_frame(thread, false, true); | |
1226 | |
1227 save_or_restore_arguments(masm, stack_slots, total_in_args, | |
1228 arg_save_area, NULL, in_regs, in_sig_bt); | |
1229 | |
1230 __ bind(cont); | |
1231 #ifdef ASSERT | |
1232 if (StressCriticalJNINatives) { | |
1233 // Stress register saving | |
1234 OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); | |
1235 save_or_restore_arguments(masm, stack_slots, total_in_args, | |
1236 arg_save_area, map, in_regs, in_sig_bt); | |
1237 // Destroy argument registers | |
1238 for (int i = 0; i < total_in_args - 1; i++) { | |
1239 if (in_regs[i].first()->is_Register()) { | |
1240 const Register reg = in_regs[i].first()->as_Register(); | |
1241 __ xorptr(reg, reg); | |
1242 } else if (in_regs[i].first()->is_XMMRegister()) { | |
1243 __ xorpd(in_regs[i].first()->as_XMMRegister(), in_regs[i].first()->as_XMMRegister()); | |
1244 } else if (in_regs[i].first()->is_FloatRegister()) { | |
1245 ShouldNotReachHere(); | |
1246 } else if (in_regs[i].first()->is_stack()) { | |
1247 // Nothing to do | |
1248 } else { | |
1249 ShouldNotReachHere(); | |
1250 } | |
1251 if (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_DOUBLE) { | |
1252 i++; | |
1253 } | |
1254 } | |
1255 | |
1256 save_or_restore_arguments(masm, stack_slots, total_in_args, | |
1257 arg_save_area, NULL, in_regs, in_sig_bt); | |
1258 } | |
1259 #endif | |
1260 } | |
1261 | |
1262 // Unpack an array argument into a pointer to the body and the length | |
1263 // if the array is non-null, otherwise pass 0 for both. | |
1264 static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType in_elem_type, VMRegPair body_arg, VMRegPair length_arg) { | |
1265 Register tmp_reg = rax; | |
1266 assert(!body_arg.first()->is_Register() || body_arg.first()->as_Register() != tmp_reg, | |
1267 "possible collision"); | |
1268 assert(!length_arg.first()->is_Register() || length_arg.first()->as_Register() != tmp_reg, | |
1269 "possible collision"); | |
1270 | |
1271 // Pass the length, ptr pair | |
1272 Label is_null, done; | |
1273 VMRegPair tmp(tmp_reg->as_VMReg()); | |
1274 if (reg.first()->is_stack()) { | |
1275 // Load the arg up from the stack | |
1276 simple_move32(masm, reg, tmp); | |
1277 reg = tmp; | |
1278 } | |
1279 __ testptr(reg.first()->as_Register(), reg.first()->as_Register()); | |
1280 __ jccb(Assembler::equal, is_null); | |
1281 __ lea(tmp_reg, Address(reg.first()->as_Register(), arrayOopDesc::base_offset_in_bytes(in_elem_type))); | |
1282 simple_move32(masm, tmp, body_arg); | |
1283 // load the length relative to the body. | |
1284 __ movl(tmp_reg, Address(tmp_reg, arrayOopDesc::length_offset_in_bytes() - | |
1285 arrayOopDesc::base_offset_in_bytes(in_elem_type))); | |
1286 simple_move32(masm, tmp, length_arg); | |
1287 __ jmpb(done); | |
1288 __ bind(is_null); | |
1289 // Pass zeros | |
1290 __ xorptr(tmp_reg, tmp_reg); | |
1291 simple_move32(masm, tmp, body_arg); | |
1292 simple_move32(masm, tmp, length_arg); | |
1293 __ bind(done); | |
1294 } | |
1295 | |
1296 | |
1094 // --------------------------------------------------------------------------- | 1297 // --------------------------------------------------------------------------- |
1095 // Generate a native wrapper for a given method. The method takes arguments | 1298 // Generate a native wrapper for a given method. The method takes arguments |
1096 // in the Java compiled code convention, marshals them to the native | 1299 // in the Java compiled code convention, marshals them to the native |
1097 // convention (handlizes oops, etc), transitions to native, makes the call, | 1300 // convention (handlizes oops, etc), transitions to native, makes the call, |
1098 // returns to java state (possibly blocking), unhandlizes any result and | 1301 // returns to java state (possibly blocking), unhandlizes any result and |
1099 // returns. | 1302 // returns. |
1303 // | |
1304 // Critical native functions are a shorthand for the use of | |
1305 // GetPrimtiveArrayCritical and disallow the use of any other JNI | |
1306 // functions. The wrapper is expected to unpack the arguments before | |
1307 // passing them to the callee and perform checks before and after the | |
1308 // native call to ensure that they GC_locker | |
1309 // lock_critical/unlock_critical semantics are followed. Some other | |
1310 // parts of JNI setup are skipped like the tear down of the JNI handle | |
1311 // block and the check for pending exceptions it's impossible for them | |
1312 // to be thrown. | |
1313 // | |
1314 // They are roughly structured like this: | |
1315 // if (GC_locker::needs_gc()) | |
1316 // SharedRuntime::block_for_jni_critical(); | |
1317 // tranistion to thread_in_native | |
1318 // unpack arrray arguments and call native entry point | |
1319 // check for safepoint in progress | |
1320 // check if any thread suspend flags are set | |
1321 // call into JVM and possible unlock the JNI critical | |
1322 // if a GC was suppressed while in the critical native. | |
1323 // transition back to thread_in_Java | |
1324 // return to caller | |
1325 // | |
1100 nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, | 1326 nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, |
1101 methodHandle method, | 1327 methodHandle method, |
1102 int compile_id, | 1328 int compile_id, |
1103 int total_in_args, | 1329 int total_in_args, |
1104 int comp_args_on_stack, | 1330 int comp_args_on_stack, |
1105 BasicType *in_sig_bt, | 1331 BasicType *in_sig_bt, |
1106 VMRegPair *in_regs, | 1332 VMRegPair *in_regs, |
1107 BasicType ret_type) { | 1333 BasicType ret_type) { |
1334 bool is_critical_native = true; | |
1335 address native_func = method->critical_native_function(); | |
1336 if (native_func == NULL) { | |
1337 native_func = method->native_function(); | |
1338 is_critical_native = false; | |
1339 } | |
1340 assert(native_func != NULL, "must have function"); | |
1108 | 1341 |
1109 // An OopMap for lock (and class if static) | 1342 // An OopMap for lock (and class if static) |
1110 OopMapSet *oop_maps = new OopMapSet(); | 1343 OopMapSet *oop_maps = new OopMapSet(); |
1111 | 1344 |
1112 // We have received a description of where all the java arg are located | 1345 // We have received a description of where all the java arg are located |
1113 // on entry to the wrapper. We need to convert these args to where | 1346 // on entry to the wrapper. We need to convert these args to where |
1114 // the jni function will expect them. To figure out where they go | 1347 // the jni function will expect them. To figure out where they go |
1115 // we convert the java signature to a C signature by inserting | 1348 // we convert the java signature to a C signature by inserting |
1116 // the hidden arguments as arg[0] and possibly arg[1] (static method) | 1349 // the hidden arguments as arg[0] and possibly arg[1] (static method) |
1117 | 1350 |
1118 int total_c_args = total_in_args + 1; | 1351 int total_c_args = total_in_args; |
1119 if (method->is_static()) { | 1352 if (!is_critical_native) { |
1120 total_c_args++; | 1353 total_c_args += 1; |
1354 if (method->is_static()) { | |
1355 total_c_args++; | |
1356 } | |
1357 } else { | |
1358 for (int i = 0; i < total_in_args; i++) { | |
1359 if (in_sig_bt[i] == T_ARRAY) { | |
1360 total_c_args++; | |
1361 } | |
1362 } | |
1121 } | 1363 } |
1122 | 1364 |
1123 BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); | 1365 BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); |
1124 VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); | 1366 VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); |
1367 BasicType* in_elem_bt = NULL; | |
1125 | 1368 |
1126 int argc = 0; | 1369 int argc = 0; |
1127 out_sig_bt[argc++] = T_ADDRESS; | 1370 if (!is_critical_native) { |
1128 if (method->is_static()) { | 1371 out_sig_bt[argc++] = T_ADDRESS; |
1129 out_sig_bt[argc++] = T_OBJECT; | 1372 if (method->is_static()) { |
1130 } | 1373 out_sig_bt[argc++] = T_OBJECT; |
1131 | 1374 } |
1132 int i; | 1375 |
1133 for (i = 0; i < total_in_args ; i++ ) { | 1376 for (int i = 0; i < total_in_args ; i++ ) { |
1134 out_sig_bt[argc++] = in_sig_bt[i]; | 1377 out_sig_bt[argc++] = in_sig_bt[i]; |
1135 } | 1378 } |
1136 | 1379 } else { |
1380 Thread* THREAD = Thread::current(); | |
1381 in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, total_in_args); | |
1382 SignatureStream ss(method->signature()); | |
1383 for (int i = 0; i < total_in_args ; i++ ) { | |
1384 if (in_sig_bt[i] == T_ARRAY) { | |
1385 // Arrays are passed as int, elem* pair | |
1386 out_sig_bt[argc++] = T_INT; | |
1387 out_sig_bt[argc++] = T_ADDRESS; | |
1388 Symbol* atype = ss.as_symbol(CHECK_NULL); | |
1389 const char* at = atype->as_C_string(); | |
1390 if (strlen(at) == 2) { | |
1391 assert(at[0] == '[', "must be"); | |
1392 switch (at[1]) { | |
1393 case 'B': in_elem_bt[i] = T_BYTE; break; | |
1394 case 'C': in_elem_bt[i] = T_CHAR; break; | |
1395 case 'D': in_elem_bt[i] = T_DOUBLE; break; | |
1396 case 'F': in_elem_bt[i] = T_FLOAT; break; | |
1397 case 'I': in_elem_bt[i] = T_INT; break; | |
1398 case 'J': in_elem_bt[i] = T_LONG; break; | |
1399 case 'S': in_elem_bt[i] = T_SHORT; break; | |
1400 case 'Z': in_elem_bt[i] = T_BOOLEAN; break; | |
1401 default: ShouldNotReachHere(); | |
1402 } | |
1403 } | |
1404 } else { | |
1405 out_sig_bt[argc++] = in_sig_bt[i]; | |
1406 in_elem_bt[i] = T_VOID; | |
1407 } | |
1408 if (in_sig_bt[i] != T_VOID) { | |
1409 assert(in_sig_bt[i] == ss.type(), "must match"); | |
1410 ss.next(); | |
1411 } | |
1412 } | |
1413 } | |
1137 | 1414 |
1138 // Now figure out where the args must be stored and how much stack space | 1415 // Now figure out where the args must be stored and how much stack space |
1139 // they require (neglecting out_preserve_stack_slots but space for storing | 1416 // they require. |
1140 // the 1st six register arguments). It's weird see int_stk_helper. | |
1141 // | |
1142 int out_arg_slots; | 1417 int out_arg_slots; |
1143 out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); | 1418 out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); |
1144 | 1419 |
1145 // Compute framesize for the wrapper. We need to handlize all oops in | 1420 // Compute framesize for the wrapper. We need to handlize all oops in |
1146 // registers a max of 2 on x86. | 1421 // registers a max of 2 on x86. |
1149 | 1424 |
1150 // First count the abi requirement plus all of the outgoing args | 1425 // First count the abi requirement plus all of the outgoing args |
1151 int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; | 1426 int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; |
1152 | 1427 |
1153 // Now the space for the inbound oop handle area | 1428 // Now the space for the inbound oop handle area |
1429 int total_save_slots = 2 * VMRegImpl::slots_per_word; // 2 arguments passed in registers | |
1430 if (is_critical_native) { | |
1431 // Critical natives may have to call out so they need a save area | |
1432 // for register arguments. | |
1433 int double_slots = 0; | |
1434 int single_slots = 0; | |
1435 for ( int i = 0; i < total_in_args; i++) { | |
1436 if (in_regs[i].first()->is_Register()) { | |
1437 const Register reg = in_regs[i].first()->as_Register(); | |
1438 switch (in_sig_bt[i]) { | |
1439 case T_ARRAY: | |
1440 case T_BOOLEAN: | |
1441 case T_BYTE: | |
1442 case T_SHORT: | |
1443 case T_CHAR: | |
1444 case T_INT: single_slots++; break; | |
1445 case T_LONG: double_slots++; break; | |
1446 default: ShouldNotReachHere(); | |
1447 } | |
1448 } else if (in_regs[i].first()->is_XMMRegister()) { | |
1449 switch (in_sig_bt[i]) { | |
1450 case T_FLOAT: single_slots++; break; | |
1451 case T_DOUBLE: double_slots++; break; | |
1452 default: ShouldNotReachHere(); | |
1453 } | |
1454 } else if (in_regs[i].first()->is_FloatRegister()) { | |
1455 ShouldNotReachHere(); | |
1456 } | |
1457 } | |
1458 total_save_slots = double_slots * 2 + single_slots; | |
1459 // align the save area | |
1460 if (double_slots != 0) { | |
1461 stack_slots = round_to(stack_slots, 2); | |
1462 } | |
1463 } | |
1154 | 1464 |
1155 int oop_handle_offset = stack_slots; | 1465 int oop_handle_offset = stack_slots; |
1156 stack_slots += 2*VMRegImpl::slots_per_word; | 1466 stack_slots += total_save_slots; |
1157 | 1467 |
1158 // Now any space we need for handlizing a klass if static method | 1468 // Now any space we need for handlizing a klass if static method |
1159 | 1469 |
1160 int klass_slot_offset = 0; | 1470 int klass_slot_offset = 0; |
1161 int klass_offset = -1; | 1471 int klass_offset = -1; |
1162 int lock_slot_offset = 0; | 1472 int lock_slot_offset = 0; |
1163 bool is_static = false; | 1473 bool is_static = false; |
1164 int oop_temp_slot_offset = 0; | |
1165 | 1474 |
1166 if (method->is_static()) { | 1475 if (method->is_static()) { |
1167 klass_slot_offset = stack_slots; | 1476 klass_slot_offset = stack_slots; |
1168 stack_slots += VMRegImpl::slots_per_word; | 1477 stack_slots += VMRegImpl::slots_per_word; |
1169 klass_offset = klass_slot_offset * VMRegImpl::stack_slot_size; | 1478 klass_offset = klass_slot_offset * VMRegImpl::stack_slot_size; |
1219 intptr_t start = (intptr_t)__ pc(); | 1528 intptr_t start = (intptr_t)__ pc(); |
1220 | 1529 |
1221 // First thing make an ic check to see if we should even be here | 1530 // First thing make an ic check to see if we should even be here |
1222 | 1531 |
1223 // We are free to use all registers as temps without saving them and | 1532 // We are free to use all registers as temps without saving them and |
1224 // restoring them except rbp,. rbp, is the only callee save register | 1533 // restoring them except rbp. rbp is the only callee save register |
1225 // as far as the interpreter and the compiler(s) are concerned. | 1534 // as far as the interpreter and the compiler(s) are concerned. |
1226 | 1535 |
1227 | 1536 |
1228 const Register ic_reg = rax; | 1537 const Register ic_reg = rax; |
1229 const Register receiver = rcx; | 1538 const Register receiver = rcx; |
1230 Label hit; | 1539 Label hit; |
1231 Label exception_pending; | 1540 Label exception_pending; |
1232 | |
1233 | 1541 |
1234 __ verify_oop(receiver); | 1542 __ verify_oop(receiver); |
1235 __ cmpptr(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); | 1543 __ cmpptr(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); |
1236 __ jcc(Assembler::equal, hit); | 1544 __ jcc(Assembler::equal, hit); |
1237 | 1545 |
1290 __ fat_nop(); | 1598 __ fat_nop(); |
1291 } | 1599 } |
1292 | 1600 |
1293 // Generate a new frame for the wrapper. | 1601 // Generate a new frame for the wrapper. |
1294 __ enter(); | 1602 __ enter(); |
1295 // -2 because return address is already present and so is saved rbp, | 1603 // -2 because return address is already present and so is saved rbp |
1296 __ subptr(rsp, stack_size - 2*wordSize); | 1604 __ subptr(rsp, stack_size - 2*wordSize); |
1297 | 1605 |
1298 // Frame is now completed as far a size and linkage. | 1606 // Frame is now completed as far as size and linkage. |
1299 | |
1300 int frame_complete = ((intptr_t)__ pc()) - start; | 1607 int frame_complete = ((intptr_t)__ pc()) - start; |
1301 | 1608 |
1302 // Calculate the difference between rsp and rbp,. We need to know it | 1609 // Calculate the difference between rsp and rbp,. We need to know it |
1303 // after the native call because on windows Java Natives will pop | 1610 // after the native call because on windows Java Natives will pop |
1304 // the arguments and it is painful to do rsp relative addressing | 1611 // the arguments and it is painful to do rsp relative addressing |
1317 #endif /* COMPILER2 */ | 1624 #endif /* COMPILER2 */ |
1318 | 1625 |
1319 // Compute the rbp, offset for any slots used after the jni call | 1626 // Compute the rbp, offset for any slots used after the jni call |
1320 | 1627 |
1321 int lock_slot_rbp_offset = (lock_slot_offset*VMRegImpl::stack_slot_size) - fp_adjustment; | 1628 int lock_slot_rbp_offset = (lock_slot_offset*VMRegImpl::stack_slot_size) - fp_adjustment; |
1322 int oop_temp_slot_rbp_offset = (oop_temp_slot_offset*VMRegImpl::stack_slot_size) - fp_adjustment; | |
1323 | 1629 |
1324 // We use rdi as a thread pointer because it is callee save and | 1630 // We use rdi as a thread pointer because it is callee save and |
1325 // if we load it once it is usable thru the entire wrapper | 1631 // if we load it once it is usable thru the entire wrapper |
1326 const Register thread = rdi; | 1632 const Register thread = rdi; |
1327 | 1633 |
1330 | 1636 |
1331 const Register oop_handle_reg = rsi; | 1637 const Register oop_handle_reg = rsi; |
1332 | 1638 |
1333 __ get_thread(thread); | 1639 __ get_thread(thread); |
1334 | 1640 |
1641 if (is_critical_native) { | |
1642 check_needs_gc_for_critical_native(masm, thread, stack_slots, total_c_args, total_in_args, | |
1643 oop_handle_offset, oop_maps, in_regs, in_sig_bt); | |
1644 } | |
1335 | 1645 |
1336 // | 1646 // |
1337 // We immediately shuffle the arguments so that any vm call we have to | 1647 // We immediately shuffle the arguments so that any vm call we have to |
1338 // make from here on out (sync slow path, jvmti, etc.) we will have | 1648 // make from here on out (sync slow path, jvmti, etc.) we will have |
1339 // captured the oops from our caller and have a valid oopMap for | 1649 // captured the oops from our caller and have a valid oopMap for |
1351 // We ignore the extra arguments during the shuffle and handle them at the | 1661 // We ignore the extra arguments during the shuffle and handle them at the |
1352 // last moment. The shuffle is described by the two calling convention | 1662 // last moment. The shuffle is described by the two calling convention |
1353 // vectors we have in our possession. We simply walk the java vector to | 1663 // vectors we have in our possession. We simply walk the java vector to |
1354 // get the source locations and the c vector to get the destinations. | 1664 // get the source locations and the c vector to get the destinations. |
1355 | 1665 |
1356 int c_arg = method->is_static() ? 2 : 1 ; | 1666 int c_arg = is_critical_native ? 0 : (method->is_static() ? 2 : 1 ); |
1357 | 1667 |
1358 // Record rsp-based slot for receiver on stack for non-static methods | 1668 // Record rsp-based slot for receiver on stack for non-static methods |
1359 int receiver_offset = -1; | 1669 int receiver_offset = -1; |
1360 | 1670 |
1361 // This is a trick. We double the stack slots so we can claim | 1671 // This is a trick. We double the stack slots so we can claim |
1371 | 1681 |
1372 // We know that we only have args in at most two integer registers (rcx, rdx). So rax, rbx | 1682 // We know that we only have args in at most two integer registers (rcx, rdx). So rax, rbx |
1373 // Are free to temporaries if we have to do stack to steck moves. | 1683 // Are free to temporaries if we have to do stack to steck moves. |
1374 // All inbound args are referenced based on rbp, and all outbound args via rsp. | 1684 // All inbound args are referenced based on rbp, and all outbound args via rsp. |
1375 | 1685 |
1376 for (i = 0; i < total_in_args ; i++, c_arg++ ) { | 1686 for (int i = 0; i < total_in_args ; i++, c_arg++ ) { |
1377 switch (in_sig_bt[i]) { | 1687 switch (in_sig_bt[i]) { |
1378 case T_ARRAY: | 1688 case T_ARRAY: |
1689 if (is_critical_native) { | |
1690 unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]); | |
1691 c_arg++; | |
1692 break; | |
1693 } | |
1379 case T_OBJECT: | 1694 case T_OBJECT: |
1695 assert(!is_critical_native, "no oop arguments"); | |
1380 object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], | 1696 object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], |
1381 ((i == 0) && (!is_static)), | 1697 ((i == 0) && (!is_static)), |
1382 &receiver_offset); | 1698 &receiver_offset); |
1383 break; | 1699 break; |
1384 case T_VOID: | 1700 case T_VOID: |
1406 } | 1722 } |
1407 } | 1723 } |
1408 | 1724 |
1409 // Pre-load a static method's oop into rsi. Used both by locking code and | 1725 // Pre-load a static method's oop into rsi. Used both by locking code and |
1410 // the normal JNI call code. | 1726 // the normal JNI call code. |
1411 if (method->is_static()) { | 1727 if (method->is_static() && !is_critical_native) { |
1412 | 1728 |
1413 // load opp into a register | 1729 // load opp into a register |
1414 __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); | 1730 __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); |
1415 | 1731 |
1416 // Now handlize the static class mirror it's known not-null. | 1732 // Now handlize the static class mirror it's known not-null. |
1461 Label slow_path_lock; | 1777 Label slow_path_lock; |
1462 Label lock_done; | 1778 Label lock_done; |
1463 | 1779 |
1464 // Lock a synchronized method | 1780 // Lock a synchronized method |
1465 if (method->is_synchronized()) { | 1781 if (method->is_synchronized()) { |
1782 assert(!is_critical_native, "unhandled"); | |
1466 | 1783 |
1467 | 1784 |
1468 const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes(); | 1785 const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes(); |
1469 | 1786 |
1470 // Get the handle (the 2nd argument) | 1787 // Get the handle (the 2nd argument) |
1527 | 1844 |
1528 // Finally just about ready to make the JNI call | 1845 // Finally just about ready to make the JNI call |
1529 | 1846 |
1530 | 1847 |
1531 // get JNIEnv* which is first argument to native | 1848 // get JNIEnv* which is first argument to native |
1532 | 1849 if (!is_critical_native) { |
1533 __ lea(rdx, Address(thread, in_bytes(JavaThread::jni_environment_offset()))); | 1850 __ lea(rdx, Address(thread, in_bytes(JavaThread::jni_environment_offset()))); |
1534 __ movptr(Address(rsp, 0), rdx); | 1851 __ movptr(Address(rsp, 0), rdx); |
1852 } | |
1535 | 1853 |
1536 // Now set thread in native | 1854 // Now set thread in native |
1537 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native); | 1855 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native); |
1538 | 1856 |
1539 __ call(RuntimeAddress(method->native_function())); | 1857 __ call(RuntimeAddress(native_func)); |
1540 | 1858 |
1541 // WARNING - on Windows Java Natives use pascal calling convention and pop the | 1859 // WARNING - on Windows Java Natives use pascal calling convention and pop the |
1542 // arguments off of the stack. We could just re-adjust the stack pointer here | 1860 // arguments off of the stack. We could just re-adjust the stack pointer here |
1543 // and continue to do SP relative addressing but we instead switch to FP | 1861 // and continue to do SP relative addressing but we instead switch to FP |
1544 // relative addressing. | 1862 // relative addressing. |
1589 if (AlwaysRestoreFPU) { | 1907 if (AlwaysRestoreFPU) { |
1590 // Make sure the control word is correct. | 1908 // Make sure the control word is correct. |
1591 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | 1909 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); |
1592 } | 1910 } |
1593 | 1911 |
1912 Label after_transition; | |
1913 | |
1594 // check for safepoint operation in progress and/or pending suspend requests | 1914 // check for safepoint operation in progress and/or pending suspend requests |
1595 { Label Continue; | 1915 { Label Continue; |
1596 | 1916 |
1597 __ cmp32(ExternalAddress((address)SafepointSynchronize::address_of_state()), | 1917 __ cmp32(ExternalAddress((address)SafepointSynchronize::address_of_state()), |
1598 SafepointSynchronize::_not_synchronized); | 1918 SafepointSynchronize::_not_synchronized); |
1609 // preserved and correspond to the bcp/locals pointers. So we do a runtime call | 1929 // preserved and correspond to the bcp/locals pointers. So we do a runtime call |
1610 // by hand. | 1930 // by hand. |
1611 // | 1931 // |
1612 save_native_result(masm, ret_type, stack_slots); | 1932 save_native_result(masm, ret_type, stack_slots); |
1613 __ push(thread); | 1933 __ push(thread); |
1614 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, | 1934 if (!is_critical_native) { |
1615 JavaThread::check_special_condition_for_native_trans))); | 1935 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, |
1936 JavaThread::check_special_condition_for_native_trans))); | |
1937 } else { | |
1938 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, | |
1939 JavaThread::check_special_condition_for_native_trans_and_transition))); | |
1940 } | |
1616 __ increment(rsp, wordSize); | 1941 __ increment(rsp, wordSize); |
1617 // Restore any method result value | 1942 // Restore any method result value |
1618 restore_native_result(masm, ret_type, stack_slots); | 1943 restore_native_result(masm, ret_type, stack_slots); |
1619 | 1944 |
1945 if (is_critical_native) { | |
1946 // The call above performed the transition to thread_in_Java so | |
1947 // skip the transition logic below. | |
1948 __ jmpb(after_transition); | |
1949 } | |
1950 | |
1620 __ bind(Continue); | 1951 __ bind(Continue); |
1621 } | 1952 } |
1622 | 1953 |
1623 // change thread state | 1954 // change thread state |
1624 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java); | 1955 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java); |
1956 __ bind(after_transition); | |
1625 | 1957 |
1626 Label reguard; | 1958 Label reguard; |
1627 Label reguard_done; | 1959 Label reguard_done; |
1628 __ cmpl(Address(thread, JavaThread::stack_guard_state_offset()), JavaThread::stack_guard_yellow_disabled); | 1960 __ cmpl(Address(thread, JavaThread::stack_guard_state_offset()), JavaThread::stack_guard_yellow_disabled); |
1629 __ jcc(Assembler::equal, reguard); | 1961 __ jcc(Assembler::equal, reguard); |
1708 __ movptr(rax, Address(rax, 0)); | 2040 __ movptr(rax, Address(rax, 0)); |
1709 __ bind(L); | 2041 __ bind(L); |
1710 __ verify_oop(rax); | 2042 __ verify_oop(rax); |
1711 } | 2043 } |
1712 | 2044 |
1713 // reset handle block | 2045 if (!is_critical_native) { |
1714 __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); | 2046 // reset handle block |
1715 | 2047 __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); |
1716 __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); | 2048 __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); |
1717 | 2049 |
1718 // Any exception pending? | 2050 // Any exception pending? |
1719 __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); | 2051 __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); |
1720 __ jcc(Assembler::notEqual, exception_pending); | 2052 __ jcc(Assembler::notEqual, exception_pending); |
1721 | 2053 } |
1722 | 2054 |
1723 // no exception, we're almost done | 2055 // no exception, we're almost done |
1724 | 2056 |
1725 // check that only result value is on FPU stack | 2057 // check that only result value is on FPU stack |
1726 __ verify_FPU(ret_type == T_FLOAT || ret_type == T_DOUBLE ? 1 : 0, "native_wrapper normal exit"); | 2058 __ verify_FPU(ret_type == T_FLOAT || ret_type == T_DOUBLE ? 1 : 0, "native_wrapper normal exit"); |
1827 __ jmp(reguard_done); | 2159 __ jmp(reguard_done); |
1828 | 2160 |
1829 | 2161 |
1830 // BEGIN EXCEPTION PROCESSING | 2162 // BEGIN EXCEPTION PROCESSING |
1831 | 2163 |
1832 // Forward the exception | 2164 if (!is_critical_native) { |
1833 __ bind(exception_pending); | 2165 // Forward the exception |
1834 | 2166 __ bind(exception_pending); |
1835 // remove possible return value from FPU register stack | 2167 |
1836 __ empty_FPU_stack(); | 2168 // remove possible return value from FPU register stack |
1837 | 2169 __ empty_FPU_stack(); |
1838 // pop our frame | 2170 |
1839 __ leave(); | 2171 // pop our frame |
1840 // and forward the exception | 2172 __ leave(); |
1841 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); | 2173 // and forward the exception |
2174 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); | |
2175 } | |
1842 | 2176 |
1843 __ flush(); | 2177 __ flush(); |
1844 | 2178 |
1845 nmethod *nm = nmethod::new_native_nmethod(method, | 2179 nmethod *nm = nmethod::new_native_nmethod(method, |
1846 compile_id, | 2180 compile_id, |
1849 frame_complete, | 2183 frame_complete, |
1850 stack_slots / VMRegImpl::slots_per_word, | 2184 stack_slots / VMRegImpl::slots_per_word, |
1851 (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), | 2185 (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), |
1852 in_ByteSize(lock_slot_offset*VMRegImpl::stack_slot_size), | 2186 in_ByteSize(lock_slot_offset*VMRegImpl::stack_slot_size), |
1853 oop_maps); | 2187 oop_maps); |
2188 | |
2189 if (is_critical_native) { | |
2190 nm->set_lazy_critical_native(true); | |
2191 } | |
2192 | |
1854 return nm; | 2193 return nm; |
1855 | 2194 |
1856 } | 2195 } |
1857 | 2196 |
1858 #ifdef HAVE_DTRACE_H | 2197 #ifdef HAVE_DTRACE_H |