JDK-8261137 : Optimization of Box nodes in uncommon_trap
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 17
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2021-02-04
  • Updated: 2022-04-28
  • Resolved: 2021-04-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17
17 b17Fixed
Related Reports
Cloners :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
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.
Comments
This optimization introduced a regression and will be disabled by JDK-8276112.
10-11-2021

Changeset: eab84554 Author: Wang Huang <whuang@openjdk.org> Committer: Vladimir Ivanov <vlivanov@openjdk.org> Date: 2021-04-07 10:48:17 +0000 URL: https://git.openjdk.java.net/jdk/commit/eab84554
07-04-2021