Other |
---|
tbdUnresolved |
Cloners :
|
|
Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
JDK-8075052 has removed useless autobox. However, in some cases, the box is still saved. For instance: @Benchmark public void testMethod(Blackhole bh) { int sum = 0; for (int i = 0; i < data.length; i++) { Integer ii = Integer.valueOf(data[i]); if (i < data.length) { sum += ii.intValue(); } } bh.consume(sum); } Although the variable ii is only used at ii.intValue(), it cannot be eliminated as a result of being used by a hidden uncommon_trap. The uncommon_trap is generated by the optimized "if", because its condition is always true. We can postpone box in uncommon_trap in this situation. We treat box as a scalarized object by adding a SafePointScalarObjectNode in the uncommon_trap node, and deleting the use of box: ``` @@ -603,6 +603,51 @@ void CallGenerator::do_late_inline_helper() { C->remove_macro_node(call); } + if (callprojs.resproj != NULL && call->is_CallStaticJava() && + call->as_CallStaticJava()->is_boxing_method()) { + GraphKit kit(call->jvms()); + PhaseGVN& gvn = kit.gvn(); + + Node_List delay_boxes; + bool no_use = true; + for (DUIterator_Fast imax, i = callprojs.resproj->fast_outs(imax); i < imax; i++) { + Node* m = callprojs.resproj->fast_out(i); + if (m->is_CallStaticJava() && + m->as_CallStaticJava()->uncommon_trap_request() != 0) { + delay_boxes.push(m); + } else { + no_use = false; + break; + } + } + + if (no_use) { + // delay box node in uncommon_trap runtime, treat box as a scalarized object + while (delay_boxes.size() > 0) { + ProjNode* res = callprojs.resproj->as_Proj(); + Node* uncommon_trap_node = delay_boxes.pop(); + int in_edge = uncommon_trap_node->find_edge(res); + assert(in_edge > 0, "sanity"); + + ciInstanceKlass* klass = call->as_CallStaticJava()->method()->holder(); + int n_fields = klass->nof_nonstatic_fields(); + assert(n_fields == 1, "sanity"); + + uint first_ind = (uncommon_trap_node->req() - uncommon_trap_node->jvms()->scloff()); + Node* sobj = new SafePointScalarObjectNode(gvn.type(res)->isa_oopptr(), +#ifdef ASSERT + NULL, +#endif // ASSERT + first_ind, n_fields); + sobj->init_req(0, C->root()); + uncommon_trap_node->add_req(call->in(res->_con)); + sobj = gvn.transform(sobj); + uncommon_trap_node->jvms()->set_endoff(uncommon_trap_node->req()); + uncommon_trap_node->set_req(in_edge, sobj); + } + } + } + ``` It is shown in the following table that the patch improves the performance on x64 and aarch64. The following table shows results of the performance test on x64 and aarch64: x64: base: Benchmark Mode Samples Score Score error Units o.s.MyBenchmark.testMethod avgt 30 50.374 3.927 us/op delay box in uncommon_trap: Benchmark Mode Samples Score Score error Units o.s.MyBenchmark.testMethod avgt 30 4.571 0.004 us/op aarch64: base: Benchmark Mode Samples Score Score error Units o.s.MyBenchmark.testMethod avgt 30 51.782 0.357 us/op delay box in uncommon_trap: Benchmark Mode Samples Score Score error Units o.s.MyBenchmark.testMethod avgt 30 3.876 0.002 us/op There is no additional fail/error(s) of jtreg after this patch.
|