src/share/vm/prims/methodHandleWalk.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
7071307 Cdiff src/share/vm/prims/methodHandleWalk.cpp
src/share/vm/prims/methodHandleWalk.cpp
Print this page
*** 180,193 ****
void MethodHandleChain::print(oopDesc* m) {
HandleMark hm;
ResourceMark rm;
Handle mh(m);
- print(mh);
- }
-
- void MethodHandleChain::print(Handle mh) {
EXCEPTION_MARK;
MethodHandleChain mhc(mh, THREAD);
if (HAS_PENDING_EXCEPTION) {
oop ex = THREAD->pending_exception();
CLEAR_PENDING_EXCEPTION;
--- 180,189 ----
*** 220,239 ****
--- 216,252 ----
chain.bound_arg_slot());
oop o = chain.bound_arg_oop();
if (o != NULL) {
if (o->is_instance()) {
tty->print(" instance %s", o->klass()->klass_part()->internal_name());
+ if (java_lang_invoke_CountingMethodHandle::is_instance(o)) {
+ tty->print(" vmcount: %d", java_lang_invoke_CountingMethodHandle::vmcount(o));
+ }
} else {
o->print();
}
}
+ oop vmt = chain.vmtarget_oop();
+ if (vmt != NULL) {
+ if (vmt->is_method()) {
+ tty->print(" ");
+ methodOop(vmt)->print_short_name(tty);
+ } else if (java_lang_invoke_MethodHandle::is_instance(vmt)) {
+ tty->print(" method handle " INTPTR_FORMAT, vmt);
+ } else {
+ ShouldNotReachHere();
+ }
+ }
} else if (chain.is_adapter()) {
tty->print("adapter: arg_slot %d conversion op %s",
chain.adapter_arg_slot(),
adapter_op_to_string(chain.adapter_conversion_op()));
switch (chain.adapter_conversion_op()) {
case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY:
+ if (java_lang_invoke_CountingMethodHandle::is_instance(chain.method_handle_oop())) {
+ tty->print(" vmcount: %d", java_lang_invoke_CountingMethodHandle::vmcount(chain.method_handle_oop()));
+ }
case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW:
case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST:
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM:
case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM:
break;
*** 905,915 ****
_bytecode(THREAD, 50),
_constants(THREAD, 10),
_non_bcp_klasses(THREAD, 5),
_cur_stack(0),
_max_stack(0),
! _rtype(T_ILLEGAL)
{
// Element zero is always the null constant.
(void) _constants.append(NULL);
--- 918,931 ----
_bytecode(THREAD, 50),
_constants(THREAD, 10),
_non_bcp_klasses(THREAD, 5),
_cur_stack(0),
_max_stack(0),
! _rtype(T_ILLEGAL),
! _selectAlternative_bci(-1),
! _taken_count(0),
! _not_taken_count(0)
{
// Element zero is always the null constant.
(void) _constants.append(NULL);
*** 1113,1128 ****
--- 1129,1183 ----
_bytecode.push(index);
_bytecode.push(args_size);
_bytecode.push(0);
break;
+ case Bytecodes::_ifeq:
+ assert((unsigned short) index == index, "index does not fit in 16-bit");
+ _bytecode.push(op);
+ _bytecode.push(index >> 8);
+ _bytecode.push(index);
+ break;
+
default:
ShouldNotReachHere();
}
}
+ void MethodHandleCompiler::update_branch_dest(int src, int dst) {
+ switch (_bytecode.at(src)) {
+ case Bytecodes::_ifeq:
+ dst -= src; // compute the offset
+ assert((unsigned short) dst == dst, "index does not fit in 16-bit");
+ _bytecode.at_put(src + 1, dst >> 8);
+ _bytecode.at_put(src + 2, dst);
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+ }
+ void MethodHandleCompiler::emit_load(ArgToken arg) {
+ TokenType tt = arg.token_type();
+ BasicType bt = arg.basic_type();
+
+ switch (tt) {
+ case tt_parameter:
+ case tt_temporary:
+ emit_load(bt, arg.index());
+ break;
+ case tt_constant:
+ emit_load_constant(arg);
+ break;
+ case tt_illegal:
+ case tt_void:
+ default:
+ ShouldNotReachHere();
+ }
+ }
+
+
void MethodHandleCompiler::emit_load(BasicType bt, int index) {
if (index <= 3) {
switch (bt) {
case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT:
case T_INT: emit_bc(Bytecodes::cast(Bytecodes::_iload_0 + index)); break;
*** 1316,1325 ****
--- 1371,1403 ----
// Values used by the compiler.
jvalue MethodHandleCompiler::zero_jvalue = { 0 };
jvalue MethodHandleCompiler::one_jvalue = { 1 };
+ // Fetch any values from CountingMethodHandles and capture them for profiles
+ bool MethodHandleCompiler::fetch_counts(ArgToken arg1, ArgToken arg2) {
+ int count1 = -1, count2 = -1;
+ if (arg1.token_type() == tt_constant && arg1.basic_type() == T_OBJECT &&
+ java_lang_invoke_CountingMethodHandle::is_instance(arg1.object()())) {
+ count1 = java_lang_invoke_CountingMethodHandle::vmcount(arg1.object()());
+ }
+ if (arg2.token_type() == tt_constant && arg2.basic_type() == T_OBJECT &&
+ java_lang_invoke_CountingMethodHandle::is_instance(arg2.object()())) {
+ count2 = java_lang_invoke_CountingMethodHandle::vmcount(arg2.object()());
+ }
+ int total = count1 + count2;
+ if (count1 != -1 && count2 != -1 && total != 0) {
+ // Normalize the collect counts to the invoke_count
+ tty->print("counts %d %d scaled by %d = ", count2, count1, _invoke_count);
+ if (count1 != 0) _not_taken_count = (int)(_invoke_count * count1 / (double)total);
+ if (count2 != 0) _taken_count = (int)(_invoke_count * count2 / (double)total);
+ tty->print_cr("%d %d", _taken_count, _not_taken_count);
+ return true;
+ }
+ return false;
+ }
+
// Emit bytecodes for the given invoke instruction.
MethodHandleWalker::ArgToken
MethodHandleCompiler::make_invoke(methodHandle m, vmIntrinsics::ID iid,
Bytecodes::Code op, bool tailcall,
int argc, MethodHandleWalker::ArgToken* argv,
*** 1365,1374 ****
--- 1443,1475 ----
m = m2;
signature = m->signature();
}
}
+ if (m->intrinsic_id() == vmIntrinsics::_selectAlternative &&
+ fetch_counts(argv[1], argv[2])) {
+ assert(argc == 3, "three arguments");
+ assert(tailcall, "only");
+
+ // do inline bytecodes so we can drop profile data into it,
+ // 0: iload_0
+ emit_load(argv[0]);
+ // 1: ifeq 8
+ _selectAlternative_bci = _bytecode.length();
+ emit_bc(Bytecodes::_ifeq, 0); // emit placeholder offset
+ // 4: aload_1
+ emit_load(argv[1]);
+ // 5: areturn;
+ emit_bc(Bytecodes::_areturn);
+ // 8: aload_2
+ update_branch_dest(_selectAlternative_bci, cur_bci());
+ emit_load(argv[2]);
+ // 9: areturn
+ emit_bc(Bytecodes::_areturn);
+ return ArgToken(); // Dummy return value.
+ }
+
check_non_bcp_klass(klass, CHECK_(zero));
if (m->is_method_handle_invoke()) {
check_non_bcp_klasses(m->method_handle_type(), CHECK_(zero));
}
*** 1375,1388 ****
// Count the number of arguments, not the size
ArgumentCount asc(signature);
assert(argc == asc.size() + ((op == Bytecodes::_invokestatic || op == Bytecodes::_invokedynamic) ? 0 : 1),
"argc mismatch");
- // Inline the method.
- InvocationCounter* ic = m->invocation_counter();
- ic->set_carry_flag();
-
for (int i = 0; i < argc; i++) {
ArgToken arg = argv[i];
TokenType tt = arg.token_type();
BasicType bt = arg.basic_type();
--- 1476,1485 ----
*** 1684,1694 ****
return cpool;
}
! methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
methodHandle empty;
// Create a method that holds the generated bytecode. invokedynamic
// has no receiver, normal MH calls do.
int flags_bits;
if (for_invokedynamic())
--- 1781,1791 ----
return cpool;
}
! methodHandle MethodHandleCompiler::get_method_oop(TRAPS) {
methodHandle empty;
// Create a method that holds the generated bytecode. invokedynamic
// has no receiver, normal MH calls do.
int flags_bits;
if (for_invokedynamic())
*** 1763,1783 ****
--- 1860,1889 ----
{
methodDataOop mdo = oopFactory::new_methodData(m, CHECK_(empty));
assert(m->method_data() == NULL, "there should not be an MDO yet");
m->set_method_data(mdo);
+ bool found_selectAlternative = false;
// Iterate over all profile data and set the count of the counter
// data entries to the original call site counter.
for (ProfileData* profile_data = mdo->first_data();
mdo->is_valid(profile_data);
profile_data = mdo->next_data(profile_data)) {
if (profile_data->is_CounterData()) {
CounterData* counter_data = profile_data->as_CounterData();
counter_data->set_count(_invoke_count);
}
+ if (profile_data->is_BranchData() &&
+ profile_data->bci() == _selectAlternative_bci) {
+ BranchData* bd = profile_data->as_BranchData();
+ bd->set_taken(_taken_count);
+ bd->set_not_taken(_not_taken_count);
+ found_selectAlternative = true;
}
}
+ assert(_selectAlternative_bci == -1 || found_selectAlternative, "must have found profile entry");
+ }
#ifndef PRODUCT
if (TraceMethodHandles) {
m->print();
m->print_codes();
src/share/vm/prims/methodHandleWalk.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File