//-----------------------------profile_receiver_type--------------------------- void Parse::profile_receiver_type(Node* receiver) { assert(method_data_update(), "must be generating profile code"); ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(bci()); assert(data->is_ReceiverTypeData(), "need ReceiverTypeData here"); // Skip if we aren't tracking receivers if (TypeProfileWidth < 1) { increment_md_counter_at(md, data, CounterData::count_offset()); return; } ciReceiverTypeData* rdata = (ciReceiverTypeData*)data->as_ReceiverTypeData(); Node* method_data = method_data_addressing(md, rdata, in_ByteSize(0)); // Using an adr_type of TypePtr::BOTTOM to work around anti-dep problems. // A better solution might be to use TypeRawPtr::BOTTOM with RC_NARROW_MEM. make_runtime_call(RC_LEAF, OptoRuntime::profile_receiver_type_Type(), CAST_FROM_FN_PTR(address, OptoRuntime::profile_receiver_type_C), "profile_receiver_type_C", TypePtr::BOTTOM, method_data, receiver); }
//---------------------------------profile_ret--------------------------------- void Parse::profile_ret(int target_bci) { if (!method_data_update()) return; // Skip if we aren't tracking ret targets if (TypeProfileWidth < 1) return; ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(bci()); assert(data->is_RetData(), "need RetData for ret"); ciRetData* ret_data = (ciRetData*)data->as_RetData(); // Look for the target_bci is already in the table uint row; bool table_full = true; for (row = 0; row < ret_data->row_limit(); row++) { int key = ret_data->bci(row); table_full &= (key != RetData::no_bci); if (key == target_bci) break; } if (row >= ret_data->row_limit()) { // The target_bci was not found in the table. if (!table_full) { // XXX: Make slow call to update RetData } return; } // the target_bci is already in the table increment_md_counter_at(md, data, RetData::bci_count_offset(row)); }
//------------------------------profile_virtual_call--------------------------- void Parse::profile_virtual_call(Node* receiver) { assert(method_data_update(), "must be generating profile code"); // Skip if we aren't tracking receivers if (TypeProfileWidth < 1) return; ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(bci()); assert(data->is_VirtualCallData(), "need VirtualCallData at call site"); ciVirtualCallData* call_data = (ciVirtualCallData*)data->as_VirtualCallData(); Node* method_data = method_data_addressing(md, call_data, in_ByteSize(0)); // The following construction of the CallLeafNode is almost identical to // make_slow_call(). However, with make_slow_call(), the merge mem // characteristics were causing incorrect anti-deps to be added. CallRuntimeNode *call = new CallLeafNode(OptoRuntime::profile_virtual_call_Type(), CAST_FROM_FN_PTR(address, OptoRuntime::profile_virtual_call_C), "profile_virtual_call_C"); set_predefined_input_for_runtime_call(call); call->set_req( TypeFunc::Parms+0, method_data ); call->set_req( TypeFunc::Parms+1, receiver ); Node* c = _gvn.transform(call); set_predefined_output_for_runtime_call(c); }
//------------------------------profile_generic_call--------------------------- void Parse::profile_generic_call() { assert(method_data_update(), "must be generating profile code"); ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(bci()); assert(data->is_CounterData(), "need CounterData for not taken branch"); increment_md_counter_at(md, data, CounterData::count_offset()); }
//--------------------------profile_not_taken_branch--------------------------- void Parse::profile_not_taken_branch() { if (!method_data_update()) return; ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(bci()); assert(data->is_BranchData(), "need BranchData for not taken branch"); increment_md_counter_at(md, data, BranchData::not_taken_offset()); }
//----------------------------profile_taken_branch----------------------------- void Parse::profile_taken_branch(int target_bci, bool force_update) { // This is a potential osr_site if we have a backedge. int cur_bci = bci(); bool osr_site = (target_bci <= cur_bci) && count_invocations() && UseOnStackReplacement; // If we are going to OSR, restart at the target bytecode. set_bci(target_bci); // To do: factor out the the limit calculations below. These duplicate // the similar limit calculations in the interpreter. if (method_data_update() || force_update) { ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(cur_bci); assert(data->is_JumpData(), "need JumpData for taken branch"); increment_md_counter_at(md, data, JumpData::taken_offset()); } // In the new tiered system this is all we need to do. In the old // (c2 based) tiered sytem we must do the code below. #ifndef TIERED if (method_data_update()) { ciMethodData* md = method()->method_data(); if (osr_site) { ciProfileData* data = md->bci_to_data(cur_bci); int limit = (CompileThreshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100; test_for_osr_md_counter_at(md, data, JumpData::taken_offset(), limit); } } else { // With method data update off, use the invocation counter to trigger an // OSR compilation, as done in the interpreter. if (osr_site) { int limit = (CompileThreshold * OnStackReplacePercentage) / 100; increment_and_test_invocation_counter(limit); } } #endif // TIERED // Restore the original bytecode. set_bci(cur_bci); }
//--------------------------profile_null_checkcast---------------------------- void Parse::profile_null_checkcast() { // Set the null-seen flag, done in conjunction with the usual null check. We // never unset the flag, so this is a one-way switch. if (!method_data_update()) return; ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(bci()); assert(data->is_BitData(), "need BitData for checkcast"); set_md_flag_at(md, data, BitData::null_seen_byte_constant()); }
//-----------------------------profile_switch_case----------------------------- void Parse::profile_switch_case(int table_index) { if (!method_data_update()) return; ciMethodData* md = method()->method_data(); assert(md != NULL, "expected valid ciMethodData"); ciProfileData* data = md->bci_to_data(bci()); assert(data->is_MultiBranchData(), "need MultiBranchData for switch case"); if (table_index >= 0) { increment_md_counter_at(md, data, MultiBranchData::case_count_offset(table_index)); } else { increment_md_counter_at(md, data, MultiBranchData::default_count_offset()); } }
//---------------------------------profile_call-------------------------------- void Parse::profile_call(Node* receiver) { if (!method_data_update()) return; switch (bc()) { case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: profile_receiver_type(receiver); break; case Bytecodes::_invokestatic: case Bytecodes::_invokedynamic: case Bytecodes::_invokespecial: profile_generic_call(); break; default: fatal("unexpected call bytecode"); } }