Skip to content

Commit a5ccd3b

Browse files
committedNov 28, 2023
8267532: C2: Profile and prune untaken exception handlers
8310011: Arena with try-with-resources is slower than it should be Reviewed-by: thartmann, vlivanov
1 parent 464dc3d commit a5ccd3b

26 files changed

+755
-110
lines changed
 

‎src/hotspot/share/c1/c1_GraphBuilder.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -3506,7 +3506,6 @@ int GraphBuilder::recursive_inline_level(ciMethod* cur_callee) const {
35063506
return recur_level;
35073507
}
35083508

3509-
35103509
bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc, Value receiver) {
35113510
const char* msg = nullptr;
35123511

‎src/hotspot/share/ci/ciMethodData.cpp

+51-13
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
ciMethodData::ciMethodData(MethodData* md)
4343
: ciMetadata(md),
4444
_data_size(0), _extra_data_size(0), _data(nullptr),
45+
_parameters_data_offset(0),
46+
_exception_handlers_data_offset(0),
4547
// Set an initial hint. Don't use set_hint_di() because
4648
// first_di() may be out of bounds if data_size is 0.
4749
_hint_di(first_di()),
@@ -50,8 +52,7 @@ ciMethodData::ciMethodData(MethodData* md)
5052
// Initialize the escape information (to "don't know.");
5153
_eflags(0), _arg_local(0), _arg_stack(0), _arg_returned(0),
5254
_invocation_counter(0),
53-
_orig(),
54-
_parameters(nullptr) {}
55+
_orig() {}
5556

5657
// Check for entries that reference an unloaded method
5758
class PrepareExtraDataClosure : public CleanExtraDataClosure {
@@ -134,8 +135,16 @@ void ciMethodData::load_remaining_extra_data() {
134135

135136
// Copy the extra data once it is prepared (i.e. cache populated, no release of extra data lock anymore)
136137
Copy::disjoint_words_atomic((HeapWord*) mdo->extra_data_base(),
137-
(HeapWord*)((address) _data + _data_size),
138-
(_extra_data_size - mdo->parameters_size_in_bytes()) / HeapWordSize);
138+
(HeapWord*) extra_data_base(),
139+
// copy everything from extra_data_base() up to parameters_data_base()
140+
pointer_delta(parameters_data_base(), extra_data_base(), HeapWordSize));
141+
142+
// skip parameter data copying. Already done in 'load_data'
143+
144+
// copy exception handler data
145+
Copy::disjoint_words_atomic((HeapWord*) mdo->exception_handler_data_base(),
146+
(HeapWord*) exception_handler_data_base(),
147+
exception_handler_data_size() / HeapWordSize);
139148

140149
// speculative trap entries also hold a pointer to a Method so need to be translated
141150
DataLayout* dp_src = mdo->extra_data_base();
@@ -195,12 +204,17 @@ bool ciMethodData::load_data() {
195204
// args_data_limit: ---------------------------
196205
// | parameter data entries |
197206
// | ... |
207+
// param_data_limit: ---------------------------
208+
// | ex handler data entries |
209+
// | ... |
198210
// extra_data_limit: ---------------------------
199211
//
200212
// _data_size = extra_data_base - data_base
201213
// _extra_data_size = extra_data_limit - extra_data_base
202214
// total_size = _data_size + _extra_data_size
203-
// args_data_limit = data_base + total_size - parameter_data_size
215+
// args_data_limit = param_data_base
216+
// param_data_limit = exception_handler_data_base
217+
// extra_data_limit = extra_data_limit
204218

205219
#ifndef ZERO
206220
// Some Zero platforms do not have expected alignment, and do not use
@@ -218,12 +232,15 @@ bool ciMethodData::load_data() {
218232
Copy::disjoint_words_atomic((HeapWord*) mdo->data_base(),
219233
(HeapWord*) _data,
220234
_data_size / HeapWordSize);
235+
// Copy offsets. This is used below
236+
_parameters_data_offset = mdo->parameters_type_data_di();
237+
_exception_handlers_data_offset = mdo->exception_handlers_data_di();
221238

222239
int parameters_data_size = mdo->parameters_size_in_bytes();
223240
if (parameters_data_size > 0) {
224241
// Snapshot the parameter data
225-
Copy::disjoint_words_atomic((HeapWord*) mdo->args_data_limit(),
226-
(HeapWord*) ((address)_data + total_size - parameters_data_size),
242+
Copy::disjoint_words_atomic((HeapWord*) mdo->parameters_data_base(),
243+
(HeapWord*) parameters_data_base(),
227244
parameters_data_size / HeapWordSize);
228245
}
229246
// Traverse the profile data, translating any oops into their
@@ -237,12 +254,12 @@ bool ciMethodData::load_data() {
237254
data = mdo->next_data(data);
238255
}
239256
if (mdo->parameters_type_data() != nullptr) {
240-
_parameters = data_layout_at(mdo->parameters_type_data_di());
241-
ciParametersTypeData* parameters = new ciParametersTypeData(_parameters);
257+
DataLayout* parameters_data = data_layout_at(_parameters_data_offset);
258+
ciParametersTypeData* parameters = new ciParametersTypeData(parameters_data);
242259
parameters->translate_from(mdo->parameters_type_data());
243260
}
244261

245-
assert((DataLayout*) ((address)_data + total_size - parameters_data_size) == args_data_limit(),
262+
assert((DataLayout*) ((address)_data + total_size - parameters_data_size - exception_handler_data_size()) == args_data_limit(),
246263
"sanity - parameter data starts after the argument data of the single ArgInfoData entry");
247264
load_remaining_extra_data();
248265

@@ -367,16 +384,24 @@ ciProfileData* ciMethodData::next_data(ciProfileData* current) {
367384
return next;
368385
}
369386

370-
DataLayout* ciMethodData::next_data_layout(DataLayout* current) {
387+
DataLayout* ciMethodData::next_data_layout_helper(DataLayout* current, bool extra) {
371388
int current_index = dp_to_di((address)current);
372389
int next_index = current_index + current->size_in_bytes();
373-
if (out_of_bounds(next_index)) {
390+
if (extra ? out_of_bounds_extra(next_index) : out_of_bounds(next_index)) {
374391
return nullptr;
375392
}
376393
DataLayout* next = data_layout_at(next_index);
377394
return next;
378395
}
379396

397+
DataLayout* ciMethodData::next_data_layout(DataLayout* current) {
398+
return next_data_layout_helper(current, false);
399+
}
400+
401+
DataLayout* ciMethodData::next_extra_data_layout(DataLayout* current) {
402+
return next_data_layout_helper(current, true);
403+
}
404+
380405
ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) {
381406
DataLayout* dp = extra_data_base();
382407
DataLayout* end = args_data_limit();
@@ -438,6 +463,19 @@ ciProfileData* ciMethodData::bci_to_data(int bci, ciMethod* m) {
438463
return nullptr;
439464
}
440465

466+
ciBitData ciMethodData::exception_handler_bci_to_data(int bci) {
467+
assert(ProfileExceptionHandlers, "not profiling");
468+
assert(_data != nullptr, "must be initialized");
469+
for (DataLayout* data = exception_handler_data_base(); data < exception_handler_data_limit(); data = next_extra_data_layout(data)) {
470+
assert(data != nullptr, "out of bounds?");
471+
if (data->bci() == bci) {
472+
return ciBitData(data);
473+
}
474+
}
475+
// called with invalid bci or wrong Method/MethodData
476+
ShouldNotReachHere();
477+
}
478+
441479
// Conservatively decode the trap_state of a ciProfileData.
442480
int ciMethodData::has_trap_at(ciProfileData* data, int reason) {
443481
typedef Deoptimization::DeoptReason DR_t;
@@ -612,7 +650,7 @@ uint ciMethodData::arg_modified(int arg) const {
612650
}
613651

614652
ciParametersTypeData* ciMethodData::parameters_type_data() const {
615-
return _parameters != nullptr ? new ciParametersTypeData(_parameters) : nullptr;
653+
return parameter_data_size() != 0 ? new ciParametersTypeData(data_layout_at(_parameters_data_offset)) : nullptr;
616654
}
617655

618656
ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) {

‎src/hotspot/share/ci/ciMethodData.hpp

+27-10
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,10 @@ class ciMethodData : public ciMetadata {
379379
// Data entries
380380
intptr_t* _data;
381381

382+
// layout of _data
383+
int _parameters_data_offset;
384+
int _exception_handlers_data_offset;
385+
382386
// Cached hint for data_layout_before()
383387
int _hint_di;
384388

@@ -403,17 +407,13 @@ class ciMethodData : public ciMetadata {
403407
// Coherent snapshot of original header.
404408
MethodData::CompilerCounters _orig;
405409

406-
// Area dedicated to parameters. null if no parameter profiling for this method.
407-
DataLayout* _parameters;
408-
int parameters_size() const {
409-
return _parameters == nullptr ? 0 : parameters_type_data()->size_in_bytes();
410-
}
411-
412410
ciMethodData(MethodData* md = nullptr);
413411

414412
// Accessors
415413
int data_size() const { return _data_size; }
416414
int extra_data_size() const { return _extra_data_size; }
415+
int parameter_data_size() const { return _exception_handlers_data_offset - _parameters_data_offset; }
416+
int exception_handler_data_size() const { return dp_to_di((address) exception_handler_data_limit()) - _exception_handlers_data_offset; }
417417
intptr_t * data() const { return _data; }
418418

419419
MethodData* get_MethodData() const {
@@ -425,14 +425,20 @@ class ciMethodData : public ciMetadata {
425425
void print_impl(outputStream* st);
426426

427427
DataLayout* data_layout_at(int data_index) const {
428-
assert(data_index % sizeof(intptr_t) == 0, "unaligned");
428+
assert(data_index % sizeof(intptr_t) == 0, "unaligned: %d", data_index);
429429
return (DataLayout*) (((address)_data) + data_index);
430430
}
431431

432432
bool out_of_bounds(int data_index) {
433433
return data_index >= data_size();
434434
}
435435

436+
bool out_of_bounds_extra(int data_index) {
437+
return data_index < data_size() || data_index >= data_size() + extra_data_size();
438+
}
439+
440+
DataLayout* next_data_layout_helper(DataLayout* current, bool extra);
441+
436442
// hint accessors
437443
int hint_di() const { return _hint_di; }
438444
void set_hint_di(int di) {
@@ -500,7 +506,7 @@ class ciMethodData : public ciMetadata {
500506
bool load_data();
501507

502508
// Convert a dp (data pointer) to a di (data index).
503-
int dp_to_di(address dp) {
509+
int dp_to_di(address dp) const {
504510
return pointer_delta_as_int(dp, ((address)_data));
505511
}
506512

@@ -511,17 +517,28 @@ class ciMethodData : public ciMetadata {
511517
ciProfileData* first_data() { return data_at(first_di()); }
512518
ciProfileData* next_data(ciProfileData* current);
513519
DataLayout* next_data_layout(DataLayout* current);
520+
DataLayout* next_extra_data_layout(DataLayout* current);
514521
bool is_valid(ciProfileData* current) { return current != nullptr; }
515522
bool is_valid(DataLayout* current) { return current != nullptr; }
516523

524+
// pointers to sections in _data
525+
// NOTE: these may be called before ciMethodData::load_data
526+
// this works out since everything is initialized to 0 (i.e. there will appear to be no data)
517527
DataLayout* extra_data_base() const { return data_layout_at(data_size()); }
518-
DataLayout* args_data_limit() const { return data_layout_at(data_size() + extra_data_size() -
519-
parameters_size()); }
528+
DataLayout* extra_data_limit() const { return data_layout_at(data_size() + extra_data_size()); }
529+
// pointers to sections in extra data
530+
DataLayout* args_data_limit() const { return parameters_data_base(); }
531+
DataLayout* parameters_data_base() const { return data_layout_at(_parameters_data_offset); }
532+
DataLayout* parameters_data_limit() const { return exception_handler_data_base(); }
533+
DataLayout* exception_handler_data_base() const { return data_layout_at(_exception_handlers_data_offset); }
534+
DataLayout* exception_handler_data_limit() const { return extra_data_limit(); }
520535

521536
// Get the data at an arbitrary bci, or null if there is none. If m
522537
// is not null look for a SpeculativeTrapData if any first.
523538
ciProfileData* bci_to_data(int bci, ciMethod* m = nullptr);
524539

540+
ciBitData exception_handler_bci_to_data(int bci);
541+
525542
uint overflow_trap_count() const {
526543
return _orig.overflow_trap_count();
527544
}

‎src/hotspot/share/interpreter/interpreterRuntime.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ JRT_END
460460
// bci where the exception happened. If the exception was propagated back
461461
// from a call, the expression stack contains the values for the bci at the
462462
// invoke w/o arguments (i.e., as if one were inside the call).
463+
// Note that the implementation of this method assumes it's only called when an exception has actually occured
463464
JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThread* current, oopDesc* exception))
464465
// We get here after we have unwound from a callee throwing an exception
465466
// into the interpreter. Any deferred stack processing is notified of
@@ -574,6 +575,7 @@ JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
574575
} else {
575576
// handler in this method => change bci/bcp to handler bci/bcp and continue there
576577
handler_pc = h_method->code_base() + handler_bci;
578+
h_method->set_exception_handler_entered(handler_bci); // profiling
577579
#ifndef ZERO
578580
set_bcp_and_mdp(handler_pc, current);
579581
continuation = Interpreter::dispatch_table(vtos)[*handler_pc];

‎src/hotspot/share/oops/method.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,16 @@ bool Method::init_method_counters(MethodCounters* counters) {
648648
return Atomic::replace_if_null(&_method_counters, counters);
649649
}
650650

651+
void Method::set_exception_handler_entered(int handler_bci) {
652+
if (ProfileExceptionHandlers) {
653+
MethodData* mdo = method_data();
654+
if (mdo != nullptr) {
655+
BitData handler_data = mdo->exception_handler_bci_to_data(handler_bci);
656+
handler_data.set_exception_handler_entered();
657+
}
658+
}
659+
}
660+
651661
int Method::extra_stack_words() {
652662
// not an inline function, to avoid a header dependency on Interpreter
653663
return extra_stack_entries() * Interpreter::stackElementSize;

‎src/hotspot/share/oops/method.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ class Method : public Metadata {
308308
return _method_data;
309309
}
310310

311+
// mark an exception handler as entered (used to prune dead catch blocks in C2)
312+
void set_exception_handler_entered(int handler_bci);
313+
311314
MethodCounters* method_counters() const {
312315
return _method_counters;
313316
}

‎src/hotspot/share/oops/methodData.cpp

+42-1
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,12 @@ int MethodData::compute_allocation_size_in_bytes(const methodHandle& method) {
965965
if (args_cell > 0) {
966966
object_size += DataLayout::compute_size_in_bytes(args_cell);
967967
}
968+
969+
if (ProfileExceptionHandlers && method()->has_exception_handler()) {
970+
int num_exception_handlers = method()->exception_table_length();
971+
object_size += num_exception_handlers * single_exception_handler_data_size();
972+
}
973+
968974
return object_size;
969975
}
970976

@@ -1275,15 +1281,28 @@ void MethodData::initialize() {
12751281
// for method entry so they don't fit with the framework for the
12761282
// profiling of bytecodes). We store the offset within the MDO of
12771283
// this area (or -1 if no parameter is profiled)
1284+
int parm_data_size = 0;
12781285
if (parms_cell > 0) {
1279-
object_size += DataLayout::compute_size_in_bytes(parms_cell);
1286+
parm_data_size = DataLayout::compute_size_in_bytes(parms_cell);
1287+
object_size += parm_data_size;
12801288
_parameters_type_data_di = data_size + extra_size + arg_data_size;
12811289
DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
12821290
dp->initialize(DataLayout::parameters_type_data_tag, 0, parms_cell);
12831291
} else {
12841292
_parameters_type_data_di = no_parameters;
12851293
}
12861294

1295+
_exception_handler_data_di = data_size + extra_size + arg_data_size + parm_data_size;
1296+
if (ProfileExceptionHandlers && method()->has_exception_handler()) {
1297+
int num_exception_handlers = method()->exception_table_length();
1298+
object_size += num_exception_handlers * single_exception_handler_data_size();
1299+
ExceptionTableElement* exception_handlers = method()->exception_table_start();
1300+
for (int i = 0; i < num_exception_handlers; i++) {
1301+
DataLayout *dp = exception_handler_data_at(i);
1302+
dp->initialize(DataLayout::bit_data_tag, exception_handlers[i].handler_pc, single_exception_handler_data_cell_count());
1303+
}
1304+
}
1305+
12871306
// Set an initial hint. Don't use set_hint_di() because
12881307
// first_di() may be out of bounds if data_size is 0.
12891308
// In that situation, _hint_di is never used, but at
@@ -1378,6 +1397,28 @@ ProfileData* MethodData::bci_to_data(int bci) {
13781397
return bci_to_extra_data(bci, nullptr, false);
13791398
}
13801399

1400+
DataLayout* MethodData::exception_handler_bci_to_data_helper(int bci) {
1401+
assert(ProfileExceptionHandlers, "not profiling");
1402+
for (int i = 0; i < num_exception_handler_data(); i++) {
1403+
DataLayout* exception_handler_data = exception_handler_data_at(i);
1404+
if (exception_handler_data->bci() == bci) {
1405+
return exception_handler_data;
1406+
}
1407+
}
1408+
return nullptr;
1409+
}
1410+
1411+
BitData* MethodData::exception_handler_bci_to_data_or_null(int bci) {
1412+
DataLayout* data = exception_handler_bci_to_data_helper(bci);
1413+
return data != nullptr ? new BitData(data) : nullptr;
1414+
}
1415+
1416+
BitData MethodData::exception_handler_bci_to_data(int bci) {
1417+
DataLayout* data = exception_handler_bci_to_data_helper(bci);
1418+
assert(data != nullptr, "invalid bci");
1419+
return BitData(data);
1420+
}
1421+
13811422
DataLayout* MethodData::next_extra(DataLayout* dp) {
13821423
int nb_cells = 0;
13831424
switch(dp->tag()) {

0 commit comments

Comments
 (0)
Please sign in to comment.