Mercurial > hg > graal-jvmci-8
comparison src/share/vm/prims/methodHandles.cpp @ 1138:dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
Summary: C2 needs some additional optimizations to be able to handle MethodHandle invokes and invokedynamic instructions at the best performance.
Reviewed-by: kvn, never
author | twisti |
---|---|
date | Tue, 05 Jan 2010 15:21:25 +0100 |
parents | 389049f3f393 |
children | 4ce7240d622c |
comparison
equal
deleted
inserted
replaced
1137:97125851f396 | 1138:dd57230ba8fe |
---|---|
130 } else { | 130 } else { |
131 assert(vmindex == methodOopDesc::invalid_vtable_index, "random vmindex?"); | 131 assert(vmindex == methodOopDesc::invalid_vtable_index, "random vmindex?"); |
132 } | 132 } |
133 return m; | 133 return m; |
134 } else { | 134 } else { |
135 assert(vmtarget->is_klass(), "must be class or interface"); | |
135 decode_flags_result |= MethodHandles::_dmf_does_dispatch; | 136 decode_flags_result |= MethodHandles::_dmf_does_dispatch; |
136 assert(vmtarget->is_klass(), "must be class or interface"); | 137 decode_flags_result |= MethodHandles::_dmf_has_receiver; |
137 receiver_limit_result = (klassOop)vmtarget; | 138 receiver_limit_result = (klassOop)vmtarget; |
138 Klass* tk = Klass::cast((klassOop)vmtarget); | 139 Klass* tk = Klass::cast((klassOop)vmtarget); |
139 if (tk->is_interface()) { | 140 if (tk->is_interface()) { |
140 // an itable linkage is <interface, itable index> | 141 // an itable linkage is <interface, itable index> |
141 decode_flags_result |= MethodHandles::_dmf_from_interface; | 142 decode_flags_result |= MethodHandles::_dmf_from_interface; |
177 } else { | 178 } else { |
178 // Optimized case: binding a receiver to a non-dispatched DMH | 179 // Optimized case: binding a receiver to a non-dispatched DMH |
179 // short-circuits directly to the methodOop. | 180 // short-circuits directly to the methodOop. |
180 // (It might be another argument besides a receiver also.) | 181 // (It might be another argument besides a receiver also.) |
181 assert(target->is_method(), "must be a simple method"); | 182 assert(target->is_method(), "must be a simple method"); |
183 decode_flags_result |= MethodHandles::_dmf_binds_method; | |
182 methodOop m = (methodOop) target; | 184 methodOop m = (methodOop) target; |
183 decode_flags_result |= MethodHandles::_dmf_binds_method; | 185 if (!m->is_static()) |
186 decode_flags_result |= MethodHandles::_dmf_has_receiver; | |
184 return m; | 187 return m; |
185 } | 188 } |
186 } | 189 } |
187 } | 190 } |
188 } | 191 } |
231 // check that signature begins '(L' or '([' (not '(I', '()', etc.) | 234 // check that signature begins '(L' or '([' (not '(I', '()', etc.) |
232 symbolOop sig = m->signature(); | 235 symbolOop sig = m->signature(); |
233 BasicType recv_bt = char2type(sig->byte_at(1)); | 236 BasicType recv_bt = char2type(sig->byte_at(1)); |
234 // Note: recv_bt might be T_ILLEGAL if byte_at(2) is ')' | 237 // Note: recv_bt might be T_ILLEGAL if byte_at(2) is ')' |
235 assert(sig->byte_at(0) == '(', "must be method sig"); | 238 assert(sig->byte_at(0) == '(', "must be method sig"); |
236 if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) | 239 // if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) |
237 decode_flags_result |= _dmf_has_receiver; | 240 // decode_flags_result |= _dmf_has_receiver; |
238 } else { | 241 } else { |
239 // non-static method | 242 // non-static method |
240 decode_flags_result |= _dmf_has_receiver; | 243 decode_flags_result |= _dmf_has_receiver; |
241 if (!m->can_be_statically_bound() && !m->is_initializer()) { | 244 if (!m->can_be_statically_bound() && !m->is_initializer()) { |
242 decode_flags_result |= _dmf_does_dispatch; | 245 decode_flags_result |= _dmf_does_dispatch; |
816 // Check the name. | 819 // Check the name. |
817 symbolOop name = ik->name(); | 820 symbolOop name = ik->name(); |
818 for (int i = 0; ; i++) { | 821 for (int i = 0; ; i++) { |
819 const char* test_name = always_null_names[i]; | 822 const char* test_name = always_null_names[i]; |
820 if (test_name == NULL) break; | 823 if (test_name == NULL) break; |
821 if (name->equals(test_name, (int) strlen(test_name))) | 824 if (name->equals(test_name)) |
822 return true; | 825 return true; |
823 } | 826 } |
824 return false; | 827 return false; |
825 } | 828 } |
826 | 829 |
1485 assert(slots_pushed <= MethodHandlePushLimit, ""); | 1488 assert(slots_pushed <= MethodHandlePushLimit, ""); |
1486 } else { | 1489 } else { |
1487 int target_pushes = decode_MethodHandle_stack_pushes(target()); | 1490 int target_pushes = decode_MethodHandle_stack_pushes(target()); |
1488 assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct"); | 1491 assert(this_pushes == slots_pushed + target_pushes, "BMH stack motion must be correct"); |
1489 // do not blow the stack; use a Java-based adapter if this limit is exceeded | 1492 // do not blow the stack; use a Java-based adapter if this limit is exceeded |
1490 if (slots_pushed + target_pushes > MethodHandlePushLimit) | 1493 // FIXME |
1491 err = "too many bound parameters"; | 1494 // if (slots_pushed + target_pushes > MethodHandlePushLimit) |
1495 // err = "too many bound parameters"; | |
1492 } | 1496 } |
1493 } | 1497 } |
1494 | 1498 |
1495 if (err == NULL) { | 1499 if (err == NULL) { |
1496 // Verify the rest of the method type. | 1500 // Verify the rest of the method type. |
1515 if (VerifyMethodHandles) { | 1519 if (VerifyMethodHandles) { |
1516 int insert_after = argnum - 1; | 1520 int insert_after = argnum - 1; |
1517 verify_vmargslot(mh, insert_after, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); | 1521 verify_vmargslot(mh, insert_after, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); |
1518 verify_vmslots(mh, CHECK); | 1522 verify_vmslots(mh, CHECK); |
1519 } | 1523 } |
1524 | |
1525 // Get bound type and required slots. | |
1526 oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); | |
1527 BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); | |
1528 int slots_pushed = type2size[ptype]; | |
1520 | 1529 |
1521 // If (a) the target is a direct non-dispatched method handle, | 1530 // If (a) the target is a direct non-dispatched method handle, |
1522 // or (b) the target is a dispatched direct method handle and we | 1531 // or (b) the target is a dispatched direct method handle and we |
1523 // are binding the receiver, cut out the middle-man. | 1532 // are binding the receiver, cut out the middle-man. |
1524 // Do this by decoding the DMH and using its methodOop directly as vmtarget. | 1533 // Do this by decoding the DMH and using its methodOop directly as vmtarget. |
1527 target->klass() == SystemDictionary::DirectMethodHandle_klass() && | 1536 target->klass() == SystemDictionary::DirectMethodHandle_klass() && |
1528 (argnum == 0 || sun_dyn_DirectMethodHandle::vmindex(target()) < 0)) { | 1537 (argnum == 0 || sun_dyn_DirectMethodHandle::vmindex(target()) < 0)) { |
1529 int decode_flags = 0; klassOop receiver_limit_oop = NULL; | 1538 int decode_flags = 0; klassOop receiver_limit_oop = NULL; |
1530 methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags)); | 1539 methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags)); |
1531 if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); } | 1540 if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); } |
1532 DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - 1); // pos. of 1st arg. | 1541 DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - slots_pushed); // pos. of 1st arg. |
1533 assert(sun_dyn_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); | 1542 assert(sun_dyn_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); |
1534 if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) { | 1543 if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) { |
1535 KlassHandle receiver_limit(THREAD, receiver_limit_oop); | 1544 KlassHandle receiver_limit(THREAD, receiver_limit_oop); |
1536 init_BoundMethodHandle_with_receiver(mh, m, | 1545 init_BoundMethodHandle_with_receiver(mh, m, |
1537 receiver_limit, decode_flags, | 1546 receiver_limit, decode_flags, |
1552 if (VerifyMethodHandles) { | 1561 if (VerifyMethodHandles) { |
1553 verify_BoundMethodHandle(mh, target, argnum, direct_to_method, CHECK); | 1562 verify_BoundMethodHandle(mh, target, argnum, direct_to_method, CHECK); |
1554 } | 1563 } |
1555 | 1564 |
1556 // Next question: Is this a ref, int, or long bound value? | 1565 // Next question: Is this a ref, int, or long bound value? |
1557 oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); | |
1558 BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); | |
1559 int slots_pushed = type2size[ptype]; | |
1560 | |
1561 MethodHandleEntry* me = NULL; | 1566 MethodHandleEntry* me = NULL; |
1562 if (ptype == T_OBJECT) { | 1567 if (ptype == T_OBJECT) { |
1563 if (direct_to_method) me = MethodHandles::entry(_bound_ref_direct_mh); | 1568 if (direct_to_method) me = MethodHandles::entry(_bound_ref_direct_mh); |
1564 else me = MethodHandles::entry(_bound_ref_mh); | 1569 else me = MethodHandles::entry(_bound_ref_mh); |
1565 } else if (slots_pushed == 2) { | 1570 } else if (slots_pushed == 2) { |