< prev index next >

src/share/vm/opto/callGenerator.cpp

Print this page
rev 10513 : fix incremental inlining with value types

@@ -370,15 +370,11 @@
   if (call == NULL || call->outcnt() == 0 ||
       call->in(0) == NULL || call->in(0)->is_top()) {
     return;
   }
   
-  // FIXME: late inlining of methods that take value type arguments is
-  // broken: arguments at the call are set up so fields of value type
-  // arguments are passed but code here expects a single argument per
-  // value type (a ValueTypeNode) instead.
-  const TypeTuple *r = call->tf()->domain_sig();
+  const TypeTuple *r = call->tf()->domain_cc();
   for (int i1 = 0; i1 < method()->arg_size(); i1++) {
     if (call->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) {
       assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
       return;
     }

@@ -402,30 +398,52 @@
   SafePointNode* map = new SafePointNode(size, jvms);
   for (uint i1 = 0; i1 < size; i1++) {
     map->init_req(i1, call->in(i1));
   }
 
+  PhaseGVN& gvn = *C->initial_gvn();
   // Make sure the state is a MergeMem for parsing.
   if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
     Node* mem = MergeMemNode::make(map->in(TypeFunc::Memory));
-    C->initial_gvn()->set_type_bottom(mem);
+    gvn.set_type_bottom(mem);
     map->set_req(TypeFunc::Memory, mem);
   }
 
-  uint nargs = method()->arg_size();
   // blow away old call arguments
   Node* top = C->top();
-  for (uint i1 = 0; i1 < nargs; i1++) {
-    map->set_req(TypeFunc::Parms + i1, top);
+  for (uint i1 = TypeFunc::Parms; i1 < call->_tf->domain_cc()->cnt(); i1++) {
+    map->set_req(i1, top);
   }
   jvms->set_map(map);
 
   // Make enough space in the expression stack to transfer
   // the incoming arguments and return value.
   map->ensure_stack(jvms, jvms->method()->max_stack());
+  const TypeTuple *domain_sig = call->_tf->domain_sig();
+  uint nargs = method()->arg_size();
+  assert(domain_sig->cnt() - TypeFunc::Parms == nargs, "inconsistent signature");
+
+  uint j = TypeFunc::Parms;
   for (uint i1 = 0; i1 < nargs; i1++) {
-    map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1));
+    const Type* t = domain_sig->field_at(TypeFunc::Parms + i1);
+    if (!ValueTypePassFieldsAsArgs) {
+      Node* arg = call->in(TypeFunc::Parms + i1);
+      if (t->isa_valuetypeptr()) {
+        arg = ValueTypeNode::make(gvn, map->memory(), arg);
+      }
+      map->set_argument(jvms, i1, arg);
+    } else {
+      if (t->isa_valuetypeptr()) {
+        ciValueKlass* vk = t->is_valuetypeptr()->value_type()->value_klass();
+        Node* vt = C->create_vt_node(call, vk, vk, 0, j);
+        map->set_argument(jvms, i1, gvn.transform(vt));
+        j += vk->value_arg_slots();
+      } else {
+        map->set_argument(jvms, i1, call->in(j));
+        j++;
+      }
+    }
   }
 
   C->print_inlining_assert_ready();
 
   C->print_inlining_move_to(this);

@@ -464,10 +482,14 @@
 
   C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops());
   C->env()->notice_inlined_method(_inline_cg->method());
   C->set_inlining_progress(true);
 
+  if (result->is_ValueType()) {
+    result = result->as_ValueType()->store_to_memory(&kit);
+  }
+
   kit.replace_call(call, result, true);
 }
 
 
 CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) {
< prev index next >