Mercurial > hg > truffle
comparison src/cpu/x86/vm/sharedRuntime_x86_64.cpp @ 6275:957c266d8bc5
Merge with http://hg.openjdk.java.net/hsx/hsx24/hotspot/
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 21 Aug 2012 10:39:19 +0200 |
parents | 422c979ff392 1d7922586cf6 |
children | 2dfab5607b3d |
comparison
equal
deleted
inserted
replaced
5891:fd8832ae511d | 6275:957c266d8bc5 |
---|---|
589 // Schedule the branch target address early. | 589 // Schedule the branch target address early. |
590 __ movptr(rcx, Address(rbx, in_bytes(methodOopDesc::interpreter_entry_offset()))); | 590 __ movptr(rcx, Address(rbx, in_bytes(methodOopDesc::interpreter_entry_offset()))); |
591 __ jmp(rcx); | 591 __ jmp(rcx); |
592 } | 592 } |
593 | 593 |
594 static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg, | |
595 address code_start, address code_end, | |
596 Label& L_ok) { | |
597 Label L_fail; | |
598 __ lea(temp_reg, ExternalAddress(code_start)); | |
599 __ cmpptr(pc_reg, temp_reg); | |
600 __ jcc(Assembler::belowEqual, L_fail); | |
601 __ lea(temp_reg, ExternalAddress(code_end)); | |
602 __ cmpptr(pc_reg, temp_reg); | |
603 __ jcc(Assembler::below, L_ok); | |
604 __ bind(L_fail); | |
605 } | |
606 | |
594 static void gen_i2c_adapter(MacroAssembler *masm, | 607 static void gen_i2c_adapter(MacroAssembler *masm, |
595 int total_args_passed, | 608 int total_args_passed, |
596 int comp_args_on_stack, | 609 int comp_args_on_stack, |
597 const BasicType *sig_bt, | 610 const BasicType *sig_bt, |
598 const VMRegPair *regs) { | 611 const VMRegPair *regs) { |
604 // we must align the stack to 16 bytes on an i2c entry else we | 617 // we must align the stack to 16 bytes on an i2c entry else we |
605 // lose alignment we expect in all compiled code and register | 618 // lose alignment we expect in all compiled code and register |
606 // save code can segv when fxsave instructions find improperly | 619 // save code can segv when fxsave instructions find improperly |
607 // aligned stack pointer. | 620 // aligned stack pointer. |
608 | 621 |
622 // Adapters can be frameless because they do not require the caller | |
623 // to perform additional cleanup work, such as correcting the stack pointer. | |
624 // An i2c adapter is frameless because the *caller* frame, which is interpreted, | |
625 // routinely repairs its own stack pointer (from interpreter_frame_last_sp), | |
626 // even if a callee has modified the stack pointer. | |
627 // A c2i adapter is frameless because the *callee* frame, which is interpreted, | |
628 // routinely repairs its caller's stack pointer (from sender_sp, which is set | |
629 // up via the senderSP register). | |
630 // In other words, if *either* the caller or callee is interpreted, we can | |
631 // get the stack pointer repaired after a call. | |
632 // This is why c2i and i2c adapters cannot be indefinitely composed. | |
633 // In particular, if a c2i adapter were to somehow call an i2c adapter, | |
634 // both caller and callee would be compiled methods, and neither would | |
635 // clean up the stack pointer changes performed by the two adapters. | |
636 // If this happens, control eventually transfers back to the compiled | |
637 // caller, but with an uncorrected stack, causing delayed havoc. | |
638 | |
609 // Pick up the return address | 639 // Pick up the return address |
610 __ movptr(rax, Address(rsp, 0)); | 640 __ movptr(rax, Address(rsp, 0)); |
641 | |
642 if (VerifyAdapterCalls && | |
643 (Interpreter::code() != NULL || StubRoutines::code1() != NULL)) { | |
644 // So, let's test for cascading c2i/i2c adapters right now. | |
645 // assert(Interpreter::contains($return_addr) || | |
646 // StubRoutines::contains($return_addr), | |
647 // "i2c adapter must return to an interpreter frame"); | |
648 __ block_comment("verify_i2c { "); | |
649 Label L_ok; | |
650 if (Interpreter::code() != NULL) | |
651 range_check(masm, rax, r11, | |
652 Interpreter::code()->code_start(), Interpreter::code()->code_end(), | |
653 L_ok); | |
654 if (StubRoutines::code1() != NULL) | |
655 range_check(masm, rax, r11, | |
656 StubRoutines::code1()->code_begin(), StubRoutines::code1()->code_end(), | |
657 L_ok); | |
658 if (StubRoutines::code2() != NULL) | |
659 range_check(masm, rax, r11, | |
660 StubRoutines::code2()->code_begin(), StubRoutines::code2()->code_end(), | |
661 L_ok); | |
662 const char* msg = "i2c adapter must return to an interpreter frame"; | |
663 __ block_comment(msg); | |
664 __ stop(msg); | |
665 __ bind(L_ok); | |
666 __ block_comment("} verify_i2ce "); | |
667 } | |
611 | 668 |
612 // Must preserve original SP for loading incoming arguments because | 669 // Must preserve original SP for loading incoming arguments because |
613 // we need to align the outgoing SP for compiled code. | 670 // we need to align the outgoing SP for compiled code. |
614 __ movptr(r11, rsp); | 671 __ movptr(r11, rsp); |
615 | 672 |
1190 OopMap* map, | 1247 OopMap* map, |
1191 VMRegPair* in_regs, | 1248 VMRegPair* in_regs, |
1192 BasicType* in_sig_bt) { | 1249 BasicType* in_sig_bt) { |
1193 // if map is non-NULL then the code should store the values, | 1250 // if map is non-NULL then the code should store the values, |
1194 // otherwise it should load them. | 1251 // otherwise it should load them. |
1195 int handle_index = 0; | 1252 int slot = arg_save_area; |
1196 // Save down double word first | 1253 // Save down double word first |
1197 for ( int i = 0; i < total_in_args; i++) { | 1254 for ( int i = 0; i < total_in_args; i++) { |
1198 if (in_regs[i].first()->is_XMMRegister() && in_sig_bt[i] == T_DOUBLE) { | 1255 if (in_regs[i].first()->is_XMMRegister() && in_sig_bt[i] == T_DOUBLE) { |
1199 int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; | |
1200 int offset = slot * VMRegImpl::stack_slot_size; | 1256 int offset = slot * VMRegImpl::stack_slot_size; |
1201 handle_index += 2; | 1257 slot += VMRegImpl::slots_per_word; |
1202 assert(handle_index <= stack_slots, "overflow"); | 1258 assert(slot <= stack_slots, "overflow"); |
1203 if (map != NULL) { | 1259 if (map != NULL) { |
1204 __ movdbl(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); | 1260 __ movdbl(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); |
1205 } else { | 1261 } else { |
1206 __ movdbl(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); | 1262 __ movdbl(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); |
1207 } | 1263 } |
1208 } | 1264 } |
1209 if (in_regs[i].first()->is_Register() && | 1265 if (in_regs[i].first()->is_Register() && |
1210 (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_ARRAY)) { | 1266 (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_ARRAY)) { |
1211 int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; | |
1212 int offset = slot * VMRegImpl::stack_slot_size; | 1267 int offset = slot * VMRegImpl::stack_slot_size; |
1213 handle_index += 2; | |
1214 assert(handle_index <= stack_slots, "overflow"); | |
1215 if (map != NULL) { | 1268 if (map != NULL) { |
1216 __ movq(Address(rsp, offset), in_regs[i].first()->as_Register()); | 1269 __ movq(Address(rsp, offset), in_regs[i].first()->as_Register()); |
1217 if (in_sig_bt[i] == T_ARRAY) { | 1270 if (in_sig_bt[i] == T_ARRAY) { |
1218 map->set_oop(VMRegImpl::stack2reg(slot));; | 1271 map->set_oop(VMRegImpl::stack2reg(slot));; |
1219 } | 1272 } |
1220 } else { | 1273 } else { |
1221 __ movq(in_regs[i].first()->as_Register(), Address(rsp, offset)); | 1274 __ movq(in_regs[i].first()->as_Register(), Address(rsp, offset)); |
1222 } | 1275 } |
1276 slot += VMRegImpl::slots_per_word; | |
1223 } | 1277 } |
1224 } | 1278 } |
1225 // Save or restore single word registers | 1279 // Save or restore single word registers |
1226 for ( int i = 0; i < total_in_args; i++) { | 1280 for ( int i = 0; i < total_in_args; i++) { |
1227 if (in_regs[i].first()->is_Register()) { | 1281 if (in_regs[i].first()->is_Register()) { |
1228 int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; | |
1229 int offset = slot * VMRegImpl::stack_slot_size; | 1282 int offset = slot * VMRegImpl::stack_slot_size; |
1230 assert(handle_index <= stack_slots, "overflow"); | 1283 slot++; |
1284 assert(slot <= stack_slots, "overflow"); | |
1231 | 1285 |
1232 // Value is in an input register pass we must flush it to the stack | 1286 // Value is in an input register pass we must flush it to the stack |
1233 const Register reg = in_regs[i].first()->as_Register(); | 1287 const Register reg = in_regs[i].first()->as_Register(); |
1234 switch (in_sig_bt[i]) { | 1288 switch (in_sig_bt[i]) { |
1235 case T_BOOLEAN: | 1289 case T_BOOLEAN: |
1250 case T_OBJECT: | 1304 case T_OBJECT: |
1251 default: ShouldNotReachHere(); | 1305 default: ShouldNotReachHere(); |
1252 } | 1306 } |
1253 } else if (in_regs[i].first()->is_XMMRegister()) { | 1307 } else if (in_regs[i].first()->is_XMMRegister()) { |
1254 if (in_sig_bt[i] == T_FLOAT) { | 1308 if (in_sig_bt[i] == T_FLOAT) { |
1255 int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; | |
1256 int offset = slot * VMRegImpl::stack_slot_size; | 1309 int offset = slot * VMRegImpl::stack_slot_size; |
1257 assert(handle_index <= stack_slots, "overflow"); | 1310 slot++; |
1311 assert(slot <= stack_slots, "overflow"); | |
1258 if (map != NULL) { | 1312 if (map != NULL) { |
1259 __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); | 1313 __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); |
1260 } else { | 1314 } else { |
1261 __ movflt(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); | 1315 __ movflt(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); |
1262 } | 1316 } |
1377 move_ptr(masm, tmp, body_arg); | 1431 move_ptr(masm, tmp, body_arg); |
1378 move32_64(masm, tmp, length_arg); | 1432 move32_64(masm, tmp, length_arg); |
1379 __ bind(done); | 1433 __ bind(done); |
1380 } | 1434 } |
1381 | 1435 |
1436 | |
1437 // Different signatures may require very different orders for the move | |
1438 // to avoid clobbering other arguments. There's no simple way to | |
1439 // order them safely. Compute a safe order for issuing stores and | |
1440 // break any cycles in those stores. This code is fairly general but | |
1441 // it's not necessary on the other platforms so we keep it in the | |
1442 // platform dependent code instead of moving it into a shared file. | |
1443 // (See bugs 7013347 & 7145024.) | |
1444 // Note that this code is specific to LP64. | |
1445 class ComputeMoveOrder: public StackObj { | |
1446 class MoveOperation: public ResourceObj { | |
1447 friend class ComputeMoveOrder; | |
1448 private: | |
1449 VMRegPair _src; | |
1450 VMRegPair _dst; | |
1451 int _src_index; | |
1452 int _dst_index; | |
1453 bool _processed; | |
1454 MoveOperation* _next; | |
1455 MoveOperation* _prev; | |
1456 | |
1457 static int get_id(VMRegPair r) { | |
1458 return r.first()->value(); | |
1459 } | |
1460 | |
1461 public: | |
1462 MoveOperation(int src_index, VMRegPair src, int dst_index, VMRegPair dst): | |
1463 _src(src) | |
1464 , _src_index(src_index) | |
1465 , _dst(dst) | |
1466 , _dst_index(dst_index) | |
1467 , _next(NULL) | |
1468 , _prev(NULL) | |
1469 , _processed(false) { | |
1470 } | |
1471 | |
1472 VMRegPair src() const { return _src; } | |
1473 int src_id() const { return get_id(src()); } | |
1474 int src_index() const { return _src_index; } | |
1475 VMRegPair dst() const { return _dst; } | |
1476 void set_dst(int i, VMRegPair dst) { _dst_index = i, _dst = dst; } | |
1477 int dst_index() const { return _dst_index; } | |
1478 int dst_id() const { return get_id(dst()); } | |
1479 MoveOperation* next() const { return _next; } | |
1480 MoveOperation* prev() const { return _prev; } | |
1481 void set_processed() { _processed = true; } | |
1482 bool is_processed() const { return _processed; } | |
1483 | |
1484 // insert | |
1485 void break_cycle(VMRegPair temp_register) { | |
1486 // create a new store following the last store | |
1487 // to move from the temp_register to the original | |
1488 MoveOperation* new_store = new MoveOperation(-1, temp_register, dst_index(), dst()); | |
1489 | |
1490 // break the cycle of links and insert new_store at the end | |
1491 // break the reverse link. | |
1492 MoveOperation* p = prev(); | |
1493 assert(p->next() == this, "must be"); | |
1494 _prev = NULL; | |
1495 p->_next = new_store; | |
1496 new_store->_prev = p; | |
1497 | |
1498 // change the original store to save it's value in the temp. | |
1499 set_dst(-1, temp_register); | |
1500 } | |
1501 | |
1502 void link(GrowableArray<MoveOperation*>& killer) { | |
1503 // link this store in front the store that it depends on | |
1504 MoveOperation* n = killer.at_grow(src_id(), NULL); | |
1505 if (n != NULL) { | |
1506 assert(_next == NULL && n->_prev == NULL, "shouldn't have been set yet"); | |
1507 _next = n; | |
1508 n->_prev = this; | |
1509 } | |
1510 } | |
1511 }; | |
1512 | |
1513 private: | |
1514 GrowableArray<MoveOperation*> edges; | |
1515 | |
1516 public: | |
1517 ComputeMoveOrder(int total_in_args, VMRegPair* in_regs, int total_c_args, VMRegPair* out_regs, | |
1518 BasicType* in_sig_bt, GrowableArray<int>& arg_order, VMRegPair tmp_vmreg) { | |
1519 // Move operations where the dest is the stack can all be | |
1520 // scheduled first since they can't interfere with the other moves. | |
1521 for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) { | |
1522 if (in_sig_bt[i] == T_ARRAY) { | |
1523 c_arg--; | |
1524 if (out_regs[c_arg].first()->is_stack() && | |
1525 out_regs[c_arg + 1].first()->is_stack()) { | |
1526 arg_order.push(i); | |
1527 arg_order.push(c_arg); | |
1528 } else { | |
1529 if (out_regs[c_arg].first()->is_stack() || | |
1530 in_regs[i].first() == out_regs[c_arg].first()) { | |
1531 add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg + 1]); | |
1532 } else { | |
1533 add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg]); | |
1534 } | |
1535 } | |
1536 } else if (in_sig_bt[i] == T_VOID) { | |
1537 arg_order.push(i); | |
1538 arg_order.push(c_arg); | |
1539 } else { | |
1540 if (out_regs[c_arg].first()->is_stack() || | |
1541 in_regs[i].first() == out_regs[c_arg].first()) { | |
1542 arg_order.push(i); | |
1543 arg_order.push(c_arg); | |
1544 } else { | |
1545 add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg]); | |
1546 } | |
1547 } | |
1548 } | |
1549 // Break any cycles in the register moves and emit the in the | |
1550 // proper order. | |
1551 GrowableArray<MoveOperation*>* stores = get_store_order(tmp_vmreg); | |
1552 for (int i = 0; i < stores->length(); i++) { | |
1553 arg_order.push(stores->at(i)->src_index()); | |
1554 arg_order.push(stores->at(i)->dst_index()); | |
1555 } | |
1556 } | |
1557 | |
1558 // Collected all the move operations | |
1559 void add_edge(int src_index, VMRegPair src, int dst_index, VMRegPair dst) { | |
1560 if (src.first() == dst.first()) return; | |
1561 edges.append(new MoveOperation(src_index, src, dst_index, dst)); | |
1562 } | |
1563 | |
1564 // Walk the edges breaking cycles between moves. The result list | |
1565 // can be walked in order to produce the proper set of loads | |
1566 GrowableArray<MoveOperation*>* get_store_order(VMRegPair temp_register) { | |
1567 // Record which moves kill which values | |
1568 GrowableArray<MoveOperation*> killer; | |
1569 for (int i = 0; i < edges.length(); i++) { | |
1570 MoveOperation* s = edges.at(i); | |
1571 assert(killer.at_grow(s->dst_id(), NULL) == NULL, "only one killer"); | |
1572 killer.at_put_grow(s->dst_id(), s, NULL); | |
1573 } | |
1574 assert(killer.at_grow(MoveOperation::get_id(temp_register), NULL) == NULL, | |
1575 "make sure temp isn't in the registers that are killed"); | |
1576 | |
1577 // create links between loads and stores | |
1578 for (int i = 0; i < edges.length(); i++) { | |
1579 edges.at(i)->link(killer); | |
1580 } | |
1581 | |
1582 // at this point, all the move operations are chained together | |
1583 // in a doubly linked list. Processing it backwards finds | |
1584 // the beginning of the chain, forwards finds the end. If there's | |
1585 // a cycle it can be broken at any point, so pick an edge and walk | |
1586 // backward until the list ends or we end where we started. | |
1587 GrowableArray<MoveOperation*>* stores = new GrowableArray<MoveOperation*>(); | |
1588 for (int e = 0; e < edges.length(); e++) { | |
1589 MoveOperation* s = edges.at(e); | |
1590 if (!s->is_processed()) { | |
1591 MoveOperation* start = s; | |
1592 // search for the beginning of the chain or cycle | |
1593 while (start->prev() != NULL && start->prev() != s) { | |
1594 start = start->prev(); | |
1595 } | |
1596 if (start->prev() == s) { | |
1597 start->break_cycle(temp_register); | |
1598 } | |
1599 // walk the chain forward inserting to store list | |
1600 while (start != NULL) { | |
1601 stores->append(start); | |
1602 start->set_processed(); | |
1603 start = start->next(); | |
1604 } | |
1605 } | |
1606 } | |
1607 return stores; | |
1608 } | |
1609 }; | |
1610 | |
1611 static void verify_oop_args(MacroAssembler* masm, | |
1612 int total_args_passed, | |
1613 const BasicType* sig_bt, | |
1614 const VMRegPair* regs) { | |
1615 Register temp_reg = rbx; // not part of any compiled calling seq | |
1616 if (VerifyOops) { | |
1617 for (int i = 0; i < total_args_passed; i++) { | |
1618 if (sig_bt[i] == T_OBJECT || | |
1619 sig_bt[i] == T_ARRAY) { | |
1620 VMReg r = regs[i].first(); | |
1621 assert(r->is_valid(), "bad oop arg"); | |
1622 if (r->is_stack()) { | |
1623 __ movptr(temp_reg, Address(rsp, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize)); | |
1624 __ verify_oop(temp_reg); | |
1625 } else { | |
1626 __ verify_oop(r->as_Register()); | |
1627 } | |
1628 } | |
1629 } | |
1630 } | |
1631 } | |
1632 | |
1633 static void gen_special_dispatch(MacroAssembler* masm, | |
1634 int total_args_passed, | |
1635 int comp_args_on_stack, | |
1636 vmIntrinsics::ID special_dispatch, | |
1637 const BasicType* sig_bt, | |
1638 const VMRegPair* regs) { | |
1639 verify_oop_args(masm, total_args_passed, sig_bt, regs); | |
1640 | |
1641 // Now write the args into the outgoing interpreter space | |
1642 bool has_receiver = false; | |
1643 Register receiver_reg = noreg; | |
1644 int member_arg_pos = -1; | |
1645 Register member_reg = noreg; | |
1646 int ref_kind = MethodHandles::signature_polymorphic_intrinsic_ref_kind(special_dispatch); | |
1647 if (ref_kind != 0) { | |
1648 member_arg_pos = total_args_passed - 1; // trailing MemberName argument | |
1649 member_reg = rbx; // known to be free at this point | |
1650 has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind); | |
1651 } else if (special_dispatch == vmIntrinsics::_invokeBasic) { | |
1652 has_receiver = true; | |
1653 } else { | |
1654 guarantee(false, err_msg("special_dispatch=%d", special_dispatch)); | |
1655 } | |
1656 | |
1657 if (member_reg != noreg) { | |
1658 // Load the member_arg into register, if necessary. | |
1659 assert(member_arg_pos >= 0 && member_arg_pos < total_args_passed, "oob"); | |
1660 assert(sig_bt[member_arg_pos] == T_OBJECT, "dispatch argument must be an object"); | |
1661 VMReg r = regs[member_arg_pos].first(); | |
1662 assert(r->is_valid(), "bad member arg"); | |
1663 if (r->is_stack()) { | |
1664 __ movptr(member_reg, Address(rsp, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize)); | |
1665 } else { | |
1666 // no data motion is needed | |
1667 member_reg = r->as_Register(); | |
1668 } | |
1669 } | |
1670 | |
1671 if (has_receiver) { | |
1672 // Make sure the receiver is loaded into a register. | |
1673 assert(total_args_passed > 0, "oob"); | |
1674 assert(sig_bt[0] == T_OBJECT, "receiver argument must be an object"); | |
1675 VMReg r = regs[0].first(); | |
1676 assert(r->is_valid(), "bad receiver arg"); | |
1677 if (r->is_stack()) { | |
1678 // Porting note: This assumes that compiled calling conventions always | |
1679 // pass the receiver oop in a register. If this is not true on some | |
1680 // platform, pick a temp and load the receiver from stack. | |
1681 assert(false, "receiver always in a register"); | |
1682 receiver_reg = j_rarg0; // known to be free at this point | |
1683 __ movptr(receiver_reg, Address(rsp, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize)); | |
1684 } else { | |
1685 // no data motion is needed | |
1686 receiver_reg = r->as_Register(); | |
1687 } | |
1688 } | |
1689 | |
1690 // Figure out which address we are really jumping to: | |
1691 MethodHandles::generate_method_handle_dispatch(masm, special_dispatch, | |
1692 receiver_reg, member_reg, /*for_compiler_entry:*/ true); | |
1693 } | |
1694 | |
1382 // --------------------------------------------------------------------------- | 1695 // --------------------------------------------------------------------------- |
1383 // Generate a native wrapper for a given method. The method takes arguments | 1696 // Generate a native wrapper for a given method. The method takes arguments |
1384 // in the Java compiled code convention, marshals them to the native | 1697 // in the Java compiled code convention, marshals them to the native |
1385 // convention (handlizes oops, etc), transitions to native, makes the call, | 1698 // convention (handlizes oops, etc), transitions to native, makes the call, |
1386 // returns to java state (possibly blocking), unhandlizes any result and | 1699 // returns to java state (possibly blocking), unhandlizes any result and |
1387 // returns. | 1700 // returns. |
1388 nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, | 1701 // |
1702 // Critical native functions are a shorthand for the use of | |
1703 // GetPrimtiveArrayCritical and disallow the use of any other JNI | |
1704 // functions. The wrapper is expected to unpack the arguments before | |
1705 // passing them to the callee and perform checks before and after the | |
1706 // native call to ensure that they GC_locker | |
1707 // lock_critical/unlock_critical semantics are followed. Some other | |
1708 // parts of JNI setup are skipped like the tear down of the JNI handle | |
1709 // block and the check for pending exceptions it's impossible for them | |
1710 // to be thrown. | |
1711 // | |
1712 // They are roughly structured like this: | |
1713 // if (GC_locker::needs_gc()) | |
1714 // SharedRuntime::block_for_jni_critical(); | |
1715 // tranistion to thread_in_native | |
1716 // unpack arrray arguments and call native entry point | |
1717 // check for safepoint in progress | |
1718 // check if any thread suspend flags are set | |
1719 // call into JVM and possible unlock the JNI critical | |
1720 // if a GC was suppressed while in the critical native. | |
1721 // transition back to thread_in_Java | |
1722 // return to caller | |
1723 // | |
1724 nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, | |
1389 methodHandle method, | 1725 methodHandle method, |
1390 int compile_id, | 1726 int compile_id, |
1391 int total_in_args, | 1727 int total_in_args, |
1392 int comp_args_on_stack, | 1728 int comp_args_on_stack, |
1393 BasicType *in_sig_bt, | 1729 BasicType* in_sig_bt, |
1394 VMRegPair *in_regs, | 1730 VMRegPair* in_regs, |
1395 BasicType ret_type) { | 1731 BasicType ret_type) { |
1732 if (method->is_method_handle_intrinsic()) { | |
1733 vmIntrinsics::ID iid = method->intrinsic_id(); | |
1734 intptr_t start = (intptr_t)__ pc(); | |
1735 int vep_offset = ((intptr_t)__ pc()) - start; | |
1736 gen_special_dispatch(masm, | |
1737 total_in_args, | |
1738 comp_args_on_stack, | |
1739 method->intrinsic_id(), | |
1740 in_sig_bt, | |
1741 in_regs); | |
1742 int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period | |
1743 __ flush(); | |
1744 int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually | |
1745 return nmethod::new_native_nmethod(method, | |
1746 compile_id, | |
1747 masm->code(), | |
1748 vep_offset, | |
1749 frame_complete, | |
1750 stack_slots / VMRegImpl::slots_per_word, | |
1751 in_ByteSize(-1), | |
1752 in_ByteSize(-1), | |
1753 (OopMapSet*)NULL); | |
1754 } | |
1396 bool is_critical_native = true; | 1755 bool is_critical_native = true; |
1397 address native_func = method->critical_native_function(); | 1756 address native_func = method->critical_native_function(); |
1398 if (native_func == NULL) { | 1757 if (native_func == NULL) { |
1399 native_func = method->native_function(); | 1758 native_func = method->native_function(); |
1400 is_critical_native = false; | 1759 is_critical_native = false; |
1497 int single_slots = 0; | 1856 int single_slots = 0; |
1498 for ( int i = 0; i < total_in_args; i++) { | 1857 for ( int i = 0; i < total_in_args; i++) { |
1499 if (in_regs[i].first()->is_Register()) { | 1858 if (in_regs[i].first()->is_Register()) { |
1500 const Register reg = in_regs[i].first()->as_Register(); | 1859 const Register reg = in_regs[i].first()->as_Register(); |
1501 switch (in_sig_bt[i]) { | 1860 switch (in_sig_bt[i]) { |
1502 case T_ARRAY: | |
1503 case T_BOOLEAN: | 1861 case T_BOOLEAN: |
1504 case T_BYTE: | 1862 case T_BYTE: |
1505 case T_SHORT: | 1863 case T_SHORT: |
1506 case T_CHAR: | 1864 case T_CHAR: |
1507 case T_INT: single_slots++; break; | 1865 case T_INT: single_slots++; break; |
1866 case T_ARRAY: // specific to LP64 (7145024) | |
1508 case T_LONG: double_slots++; break; | 1867 case T_LONG: double_slots++; break; |
1509 default: ShouldNotReachHere(); | 1868 default: ShouldNotReachHere(); |
1510 } | 1869 } |
1511 } else if (in_regs[i].first()->is_XMMRegister()) { | 1870 } else if (in_regs[i].first()->is_XMMRegister()) { |
1512 switch (in_sig_bt[i]) { | 1871 switch (in_sig_bt[i]) { |
1699 freg_destroyed[f] = false; | 2058 freg_destroyed[f] = false; |
1700 } | 2059 } |
1701 | 2060 |
1702 #endif /* ASSERT */ | 2061 #endif /* ASSERT */ |
1703 | 2062 |
1704 if (is_critical_native) { | |
1705 // The mapping of Java and C arguments passed in registers are | |
1706 // rotated by one, which helps when passing arguments to regular | |
1707 // Java method but for critical natives that creates a cycle which | |
1708 // can cause arguments to be killed before they are used. Break | |
1709 // the cycle by moving the first argument into a temporary | |
1710 // register. | |
1711 for (int i = 0; i < total_c_args; i++) { | |
1712 if (in_regs[i].first()->is_Register() && | |
1713 in_regs[i].first()->as_Register() == rdi) { | |
1714 __ mov(rbx, rdi); | |
1715 in_regs[i].set1(rbx->as_VMReg()); | |
1716 } | |
1717 } | |
1718 } | |
1719 | |
1720 // This may iterate in two different directions depending on the | 2063 // This may iterate in two different directions depending on the |
1721 // kind of native it is. The reason is that for regular JNI natives | 2064 // kind of native it is. The reason is that for regular JNI natives |
1722 // the incoming and outgoing registers are offset upwards and for | 2065 // the incoming and outgoing registers are offset upwards and for |
1723 // critical natives they are offset down. | 2066 // critical natives they are offset down. |
1724 int c_arg = total_c_args - 1; | 2067 GrowableArray<int> arg_order(2 * total_in_args); |
1725 int stride = -1; | 2068 VMRegPair tmp_vmreg; |
1726 int init = total_in_args - 1; | 2069 tmp_vmreg.set1(rbx->as_VMReg()); |
1727 if (is_critical_native) { | 2070 |
1728 // stride forwards | 2071 if (!is_critical_native) { |
1729 c_arg = 0; | 2072 for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) { |
1730 stride = 1; | 2073 arg_order.push(i); |
1731 init = 0; | 2074 arg_order.push(c_arg); |
1732 } | 2075 } |
1733 for (int i = init, count = 0; count < total_in_args; i += stride, c_arg += stride, count++ ) { | 2076 } else { |
2077 // Compute a valid move order, using tmp_vmreg to break any cycles | |
2078 ComputeMoveOrder cmo(total_in_args, in_regs, total_c_args, out_regs, in_sig_bt, arg_order, tmp_vmreg); | |
2079 } | |
2080 | |
2081 int temploc = -1; | |
2082 for (int ai = 0; ai < arg_order.length(); ai += 2) { | |
2083 int i = arg_order.at(ai); | |
2084 int c_arg = arg_order.at(ai + 1); | |
2085 __ block_comment(err_msg("move %d -> %d", i, c_arg)); | |
2086 if (c_arg == -1) { | |
2087 assert(is_critical_native, "should only be required for critical natives"); | |
2088 // This arg needs to be moved to a temporary | |
2089 __ mov(tmp_vmreg.first()->as_Register(), in_regs[i].first()->as_Register()); | |
2090 in_regs[i] = tmp_vmreg; | |
2091 temploc = i; | |
2092 continue; | |
2093 } else if (i == -1) { | |
2094 assert(is_critical_native, "should only be required for critical natives"); | |
2095 // Read from the temporary location | |
2096 assert(temploc != -1, "must be valid"); | |
2097 i = temploc; | |
2098 temploc = -1; | |
2099 } | |
1734 #ifdef ASSERT | 2100 #ifdef ASSERT |
1735 if (in_regs[i].first()->is_Register()) { | 2101 if (in_regs[i].first()->is_Register()) { |
1736 assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!"); | 2102 assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!"); |
1737 } else if (in_regs[i].first()->is_XMMRegister()) { | 2103 } else if (in_regs[i].first()->is_XMMRegister()) { |
1738 assert(!freg_destroyed[in_regs[i].first()->as_XMMRegister()->encoding()], "destroyed reg!"); | 2104 assert(!freg_destroyed[in_regs[i].first()->as_XMMRegister()->encoding()], "destroyed reg!"); |
1788 } | 2154 } |
1789 } | 2155 } |
1790 | 2156 |
1791 // point c_arg at the first arg that is already loaded in case we | 2157 // point c_arg at the first arg that is already loaded in case we |
1792 // need to spill before we call out | 2158 // need to spill before we call out |
1793 c_arg++; | 2159 int c_arg = total_c_args - total_in_args; |
1794 | 2160 |
1795 // Pre-load a static method's oop into r14. Used both by locking code and | 2161 // Pre-load a static method's oop into r14. Used both by locking code and |
1796 // the normal JNI call code. | 2162 // the normal JNI call code. |
1797 if (method->is_static() && !is_critical_native) { | 2163 if (method->is_static() && !is_critical_native) { |
1798 | 2164 |
3665 // If not, it prepares for stack-unwinding, restoring the callee-save | 4031 // If not, it prepares for stack-unwinding, restoring the callee-save |
3666 // registers of the frame being removed. | 4032 // registers of the frame being removed. |
3667 // | 4033 // |
3668 // address OptoRuntime::handle_exception_C(JavaThread* thread) | 4034 // address OptoRuntime::handle_exception_C(JavaThread* thread) |
3669 | 4035 |
3670 __ set_last_Java_frame(noreg, noreg, NULL); | 4036 // At a method handle call, the stack may not be properly aligned |
4037 // when returning with an exception. | |
4038 address the_pc = __ pc(); | |
4039 __ set_last_Java_frame(noreg, noreg, the_pc); | |
3671 __ mov(c_rarg0, r15_thread); | 4040 __ mov(c_rarg0, r15_thread); |
4041 __ andptr(rsp, -(StackAlignmentInBytes)); // Align stack | |
3672 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); | 4042 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); |
3673 | 4043 |
3674 // Set an oopmap for the call site. This oopmap will only be used if we | 4044 // Set an oopmap for the call site. This oopmap will only be used if we |
3675 // are unwinding the stack. Hence, all locations will be dead. | 4045 // are unwinding the stack. Hence, all locations will be dead. |
3676 // Callee-saved registers will be the same as the frame above (i.e., | 4046 // Callee-saved registers will be the same as the frame above (i.e., |
3677 // handle_exception_stub), since they were restored when we got the | 4047 // handle_exception_stub), since they were restored when we got the |
3678 // exception. | 4048 // exception. |
3679 | 4049 |
3680 OopMapSet* oop_maps = new OopMapSet(); | 4050 OopMapSet* oop_maps = new OopMapSet(); |
3681 | 4051 |
3682 oop_maps->add_gc_map( __ pc()-start, new OopMap(SimpleRuntimeFrame::framesize, 0)); | 4052 oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); |
3683 | 4053 |
3684 __ reset_last_Java_frame(false, false); | 4054 __ reset_last_Java_frame(false, true); |
3685 | 4055 |
3686 // Restore callee-saved registers | 4056 // Restore callee-saved registers |
3687 | 4057 |
3688 // rbp is an implicitly saved callee saved register (i.e. the calling | 4058 // rbp is an implicitly saved callee saved register (i.e. the calling |
3689 // convention will save restore it in prolog/epilog) Other than that | 4059 // convention will save restore it in prolog/epilog) Other than that |