< prev index next >

src/hotspot/share/opto/parse1.cpp

Print this page

        

@@ -35,10 +35,11 @@
 #include "opto/memnode.hpp"
 #include "opto/opaquenode.hpp"
 #include "opto/parse.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
+#include "opto/valuetypenode.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/safepointMechanism.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/copy.hpp"

@@ -99,14 +100,20 @@
 
 //------------------------------ON STACK REPLACEMENT---------------------------
 
 // Construct a node which can be used to get incoming state for
 // on stack replacement.
-Node *Parse::fetch_interpreter_state(int index,
-                                     BasicType bt,
-                                     Node *local_addrs,
-                                     Node *local_addrs_base) {
+Node* Parse::fetch_interpreter_state(int index,
+                                     const Type* type,
+                                     Node* local_addrs,
+                                     Node* local_addrs_base) {
+  BasicType bt = type->basic_type();
+  if (type == TypePtr::NULL_PTR) {
+    // Ptr types are mixed together with T_ADDRESS but NULL is
+    // really for T_OBJECT types so correct it.
+    bt = T_OBJECT;
+  }
   Node *mem = memory(Compile::AliasIdxRaw);
   Node *adr = basic_plus_adr( local_addrs_base, local_addrs, -index*wordSize );
   Node *ctl = control();
 
   // Very similar to LoadNode::make, except we handle un-aligned longs and

@@ -114,10 +121,11 @@
   Node *l = NULL;
   switch (bt) {                // Signature is flattened
   case T_INT:     l = new LoadINode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInt::INT,        MemNode::unordered); break;
   case T_FLOAT:   l = new LoadFNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::FLOAT,         MemNode::unordered); break;
   case T_ADDRESS: l = new LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM,  MemNode::unordered); break;
+  case T_VALUETYPE:
   case T_OBJECT:  l = new LoadPNode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM, MemNode::unordered); break;
   case T_LONG:
   case T_DOUBLE: {
     // Since arguments are in reverse order, the argument address 'adr'
     // refers to the back half of the long/double.  Recompute adr.

@@ -144,12 +152,16 @@
 // The type is the type predicted by ciTypeFlow.  Note that it is
 // not a general type, but can only come from Type::get_typeflow_type.
 // The safepoint is a map which will feed an uncommon trap.
 Node* Parse::check_interpreter_type(Node* l, const Type* type,
                                     SafePointNode* &bad_type_exit) {
-
   const TypeOopPtr* tp = type->isa_oopptr();
+  if (type->isa_valuetype() != NULL) {
+    // The interpreter passes value types as oops
+    tp = TypeOopPtr::make_from_klass(type->value_klass());
+    tp = tp->join_speculative(TypePtr::NOTNULL)->is_oopptr();
+  }
 
   // TypeFlow may assert null-ness if a type appears unloaded.
   if (type == TypePtr::NULL_PTR ||
       (tp != NULL && !tp->klass()->is_loaded())) {
     // Value must be null, not a real oop.

@@ -168,16 +180,19 @@
   // toward more specific classes.  Make sure these specific classes
   // are still in effect.
   if (tp != NULL && tp->klass() != C->env()->Object_klass()) {
     // TypeFlow asserted a specific object type.  Value must have that type.
     Node* bad_type_ctrl = NULL;
+    if (tp->is_valuetypeptr() && !tp->maybe_null()) {
+      // Check value types for null here to prevent checkcast from adding an
+      // exception state before the bytecode entry (use 'bad_type_ctrl' instead).
+      l = null_check_oop(l, &bad_type_ctrl);
+      bad_type_exit->control()->add_req(bad_type_ctrl);
+    }
     l = gen_checkcast(l, makecon(TypeKlassPtr::make(tp->klass())), &bad_type_ctrl);
     bad_type_exit->control()->add_req(bad_type_ctrl);
   }
-
-  BasicType bt_l = _gvn.type(l)->basic_type();
-  BasicType bt_t = type->basic_type();
   assert(_gvn.type(l)->higher_equal(type), "must constrain OSR typestate");
   return l;
 }
 
 // Helper routine which sets up elements of the initial parser map when

@@ -186,11 +201,10 @@
 void Parse::load_interpreter_state(Node* osr_buf) {
   int index;
   int max_locals = jvms()->loc_size();
   int max_stack  = jvms()->stk_size();
 
-
   // Mismatch between method and jvms can occur since map briefly held
   // an OSR entry state (which takes up one RawPtr word).
   assert(max_locals == method()->max_locals(), "sanity");
   assert(max_stack  >= method()->max_stack(),  "sanity");
   assert((int)jvms()->endoff() == TypeFunc::Parms + max_locals + max_stack, "sanity");

@@ -224,18 +238,16 @@
   Node *monitors_addr = basic_plus_adr(osr_buf, osr_buf, (max_locals+mcnt*2-1)*wordSize);
   for (index = 0; index < mcnt; index++) {
     // Make a BoxLockNode for the monitor.
     Node *box = _gvn.transform(new BoxLockNode(next_monitor()));
 
-
     // Displaced headers and locked objects are interleaved in the
     // temp OSR buffer.  We only copy the locked objects out here.
     // Fetch the locked object from the OSR temp buffer and copy to our fastlock node.
-    Node *lock_object = fetch_interpreter_state(index*2, T_OBJECT, monitors_addr, osr_buf);
+    Node* lock_object = fetch_interpreter_state(index*2, Type::get_const_basic_type(T_OBJECT), monitors_addr, osr_buf);
     // Try and copy the displaced header to the BoxNode
-    Node *displaced_hdr = fetch_interpreter_state((index*2) + 1, T_ADDRESS, monitors_addr, osr_buf);
-
+    Node* displaced_hdr = fetch_interpreter_state((index*2) + 1, Type::get_const_basic_type(T_ADDRESS), monitors_addr, osr_buf);
 
     store_to_memory(control(), box, displaced_hdr, T_ADDRESS, Compile::AliasIdxRaw, MemNode::unordered);
 
     // Build a bogus FastLockNode (no code will be generated) and push the
     // monitor into our debug info.

@@ -298,17 +310,11 @@
     // makes it go dead.
     if (type == Type::BOTTOM) {
       continue;
     }
     // Construct code to access the appropriate local.
-    BasicType bt = type->basic_type();
-    if (type == TypePtr::NULL_PTR) {
-      // Ptr types are mixed together with T_ADDRESS but NULL is
-      // really for T_OBJECT types so correct it.
-      bt = T_OBJECT;
-    }
-    Node *value = fetch_interpreter_state(index, bt, locals_addr, osr_buf);
+    Node* value = fetch_interpreter_state(index, type, locals_addr, osr_buf);
     set_local(index, value);
   }
 
   // Extract the needed stack entries from the interpreter frame.
   for (index = 0; index < sp(); index++) {

@@ -598,10 +604,31 @@
     if (log)  log->done("parse");
     C->set_default_node_notes(caller_nn);
     return;
   }
 
+  // Handle value type arguments
+  int arg_size_sig = tf()->domain_sig()->cnt();
+  for (uint i = 0; i < (uint)arg_size_sig; i++) {
+    Node* parm = map()->in(i);
+    const Type* t = _gvn.type(parm);
+    if (t->is_valuetypeptr() && t->value_klass()->is_scalarizable() && !t->maybe_null()) {
+      // Create ValueTypeNode from the oop and replace the parameter
+      Node* vt = ValueTypeNode::make_from_oop(this, parm, t->value_klass());
+      map()->replace_edge(parm, vt);
+    } else if (i == (uint)(arg_size_sig - 1) && !is_osr_parse() && method()->has_vararg() &&
+               t->isa_aryptr() != NULL && !t->is_aryptr()->is_not_null_free()) {
+      // Speculate on varargs Object array being not null-free (and therefore also not flattened)
+      const TypePtr* spec_type = t->speculative();
+      spec_type = (spec_type != NULL && spec_type->isa_aryptr() != NULL) ? spec_type : t->is_aryptr();
+      spec_type = spec_type->remove_speculative()->is_aryptr()->cast_to_not_null_free();
+      spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::Offset::bottom, TypeOopPtr::InstanceBot, spec_type);
+      Node* cast = _gvn.transform(new CheckCastPPNode(control(), parm, t->join_speculative(spec_type)));
+      replace_in_map(parm, cast);
+    }
+  }
+
   entry_map = map();  // capture any changes performed by method setup code
   assert(jvms()->endoff() == map()->req(), "map matches JVMS layout");
 
   // We begin parsing as if we have just encountered a jump to the
   // method entry.

@@ -780,12 +807,12 @@
   gvn().set_type_bottom(memphi);
   _exits.set_i_o(iophi);
   _exits.set_all_memory(memphi);
 
   // Add a return value to the exit state.  (Do not push it yet.)
-  if (tf()->range()->cnt() > TypeFunc::Parms) {
-    const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
+  if (tf()->range_sig()->cnt() > TypeFunc::Parms) {
+    const Type* ret_type = tf()->range_sig()->field_at(TypeFunc::Parms);
     if (ret_type->isa_int()) {
       BasicType ret_bt = method()->return_type()->basic_type();
       if (ret_bt == T_BOOLEAN ||
           ret_bt == T_CHAR ||
           ret_bt == T_BYTE ||

@@ -799,30 +826,36 @@
     // types will not join when we transform and push in do_exits().
     const TypeOopPtr* ret_oop_type = ret_type->isa_oopptr();
     if (ret_oop_type && !ret_oop_type->klass()->is_loaded()) {
       ret_type = TypeOopPtr::BOTTOM;
     }
+    if ((_caller->has_method() || tf()->returns_value_type_as_fields()) &&
+        ret_type->is_valuetypeptr() && ret_type->value_klass()->is_scalarizable() && !ret_type->maybe_null()) {
+      // Scalarize value type return when inlining or with multiple return values
+      ret_type = TypeValueType::make(ret_type->value_klass());
+    }
     int         ret_size = type2size[ret_type->basic_type()];
     Node*       ret_phi  = new PhiNode(region, ret_type);
     gvn().set_type_bottom(ret_phi);
     _exits.ensure_stack(ret_size);
-    assert((int)(tf()->range()->cnt() - TypeFunc::Parms) == ret_size, "good tf range");
+    assert((int)(tf()->range_sig()->cnt() - TypeFunc::Parms) == ret_size, "good tf range");
     assert(method()->return_type()->size() == ret_size, "tf agrees w/ method");
     _exits.set_argument(0, ret_phi);  // here is where the parser finds it
     // Note:  ret_phi is not yet pushed, until do_exits.
   }
 }
 
-
 //----------------------------build_start_state-------------------------------
 // Construct a state which contains only the incoming arguments from an
 // unknown caller.  The method & bci will be NULL & InvocationEntryBci.
 JVMState* Compile::build_start_state(StartNode* start, const TypeFunc* tf) {
-  int        arg_size = tf->domain()->cnt();
-  int        max_size = MAX2(arg_size, (int)tf->range()->cnt());
+  int        arg_size = tf->domain_sig()->cnt();
+  int        max_size = MAX2(arg_size, (int)tf->range_cc()->cnt());
   JVMState*  jvms     = new (this) JVMState(max_size - TypeFunc::Parms);
   SafePointNode* map  = new SafePointNode(max_size, NULL);
+  map->set_jvms(jvms);
+  jvms->set_map(map);
   record_for_igvn(map);
   assert(arg_size == TypeFunc::Parms + (is_osr_compilation() ? 1 : method()->arg_size()), "correct arg_size");
   Node_Notes* old_nn = default_node_notes();
   if (old_nn != NULL && has_method()) {
     Node_Notes* entry_nn = old_nn->clone(this);

@@ -830,24 +863,44 @@
     entry_jvms->set_offsets(0);
     entry_jvms->set_bci(entry_bci());
     entry_nn->set_jvms(entry_jvms);
     set_default_node_notes(entry_nn);
   }
-  uint i;
-  for (i = 0; i < (uint)arg_size; i++) {
-    Node* parm = initial_gvn()->transform(new ParmNode(start, i));
+  PhaseGVN& gvn = *initial_gvn();
+  uint j = 0;
+  ExtendedSignature sig_cc = ExtendedSignature(method()->get_sig_cc(), SigEntryFilter());
+  for (uint i = 0; i < (uint)arg_size; i++) {
+    const Type* t = tf->domain_sig()->field_at(i);
+    Node* parm = NULL;
+    if (has_scalarized_args() && t->is_valuetypeptr() && !t->maybe_null()) {
+      // Value type arguments are not passed by reference: we get an argument per
+      // field of the value type. Build ValueTypeNodes from the value type arguments.
+      GraphKit kit(jvms, &gvn);
+      kit.set_control(map->control());
+      Node* old_mem = map->memory();
+      // Use immutable memory for value type loads and restore it below
+      // TODO make sure value types are always loaded from immutable memory
+      kit.set_all_memory(C->immutable_memory());
+      parm = ValueTypeNode::make_from_multi(&kit, start, sig_cc, t->value_klass(), j, true);
+      map->set_control(kit.control());
+      map->set_memory(old_mem);
+    } else {
+      parm = gvn.transform(new ParmNode(start, j++));
+      BasicType bt = t->basic_type();
+      while (i >= TypeFunc::Parms && !is_osr_compilation() && SigEntry::next_is_reserved(sig_cc, bt, true)) {
+        j += type2size[bt]; // Skip reserved arguments
+      }
+    }
     map->init_req(i, parm);
     // Record all these guys for later GVN.
     record_for_igvn(parm);
   }
-  for (; i < map->req(); i++) {
-    map->init_req(i, top());
+  for (; j < map->req(); j++) {
+    map->init_req(j, top());
   }
   assert(jvms->argoff() == TypeFunc::Parms, "parser gets arguments here");
   set_default_node_notes(old_nn);
-  map->set_jvms(jvms);
-  jvms->set_map(map);
   return jvms;
 }
 
 //-----------------------------make_node_notes---------------------------------
 Node_Notes* Parse::make_node_notes(Node_Notes* caller_nn) {

@@ -870,16 +923,36 @@
                              kit.i_o(),
                              kit.reset_memory(),
                              kit.frameptr(),
                              kit.returnadr());
   // Add zero or 1 return values
-  int ret_size = tf()->range()->cnt() - TypeFunc::Parms;
+  int ret_size = tf()->range_sig()->cnt() - TypeFunc::Parms;
   if (ret_size > 0) {
     kit.inc_sp(-ret_size);  // pop the return value(s)
     kit.sync_jvms();
-    ret->add_req(kit.argument(0));
-    // Note:  The second dummy edge is not needed by a ReturnNode.
+    Node* res = kit.argument(0);
+    if (tf()->returns_value_type_as_fields()) {
+      // Multiple return values (value type fields): add as many edges
+      // to the Return node as returned values.
+      assert(res->is_ValueType(), "what else supports multi value return?");
+      ValueTypeNode* vt = res->as_ValueType();
+      ret->add_req_batch(NULL, tf()->range_cc()->cnt() - TypeFunc::Parms);
+      if (vt->is_allocated(&kit.gvn()) && !StressValueTypeReturnedAsFields) {
+        ret->init_req(TypeFunc::Parms, vt->get_oop());
+      } else {
+        ret->init_req(TypeFunc::Parms, vt->tagged_klass(kit.gvn()));
+      }
+      const Array<SigEntry>* sig_array = vt->type()->value_klass()->extended_sig();
+      GrowableArray<SigEntry> sig = GrowableArray<SigEntry>(sig_array->length());
+      sig.appendAll(sig_array);
+      ExtendedSignature sig_cc = ExtendedSignature(&sig, SigEntryFilter());
+      uint idx = TypeFunc::Parms+1;
+      vt->pass_fields(&kit, ret, sig_cc, idx);
+    } else {
+      ret->add_req(res);
+      // Note:  The second dummy edge is not needed by a ReturnNode.
+    }
   }
   // bind it to root
   root()->add_req(ret);
   record_for_igvn(ret);
   initial_gvn()->transform_no_reclaim(ret);

@@ -996,11 +1069,11 @@
   // "All bets are off" unless the first publication occurs after a
   // normal return from the constructor.  We do not attempt to detect
   // such unusual early publications.  But no barrier is needed on
   // exceptional returns, since they cannot publish normally.
   //
-  if (method()->is_initializer() &&
+  if (method()->is_object_constructor_or_class_initializer() &&
         (wrote_final() ||
            PPC64_ONLY(wrote_volatile() ||)
            (AlwaysSafeConstructors && wrote_fields()))) {
     _exits.insert_mem_bar(Op_MemBarRelease, alloc_with_final());
 

@@ -1034,12 +1107,12 @@
     mms.set_memory(_gvn.transform(mms.memory()));
   }
   // Clean up input MergeMems created by transforming the slices
   _gvn.transform(_exits.merged_memory());
 
-  if (tf()->range()->cnt() > TypeFunc::Parms) {
-    const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
+  if (tf()->range_sig()->cnt() > TypeFunc::Parms) {
+    const Type* ret_type = tf()->range_sig()->field_at(TypeFunc::Parms);
     Node*       ret_phi  = _gvn.transform( _exits.argument(0) );
     if (!_exits.control()->is_top() && _gvn.type(ret_phi)->empty()) {
       // In case of concurrent class loading, the type we set for the
       // ret_phi in build_exits() may have been too optimistic and the
       // ret_phi may be top now.

@@ -1137,11 +1210,11 @@
   _caller->map()->delete_replaced_nodes();
 
   // If this is an inlined method, we may have to do a receiver null check.
   if (_caller->has_method() && is_normal_parse() && !method()->is_static()) {
     GraphKit kit(_caller);
-    kit.null_check_receiver_before_call(method());
+    kit.null_check_receiver_before_call(method(), false);
     _caller = kit.transfer_exceptions_into_jvms();
     if (kit.stopped()) {
       _exits.add_exception_states_from(_caller);
       _exits.set_jvms(_caller);
       return NULL;

@@ -1175,11 +1248,11 @@
     set_all_memory(reset_memory());
   }
   assert(merged_memory(), "");
 
   // Now add the locals which are initially bound to arguments:
-  uint arg_size = tf()->domain()->cnt();
+  uint arg_size = tf()->domain_sig()->cnt();
   ensure_stack(arg_size - TypeFunc::Parms);  // OSR methods have funny args
   for (i = TypeFunc::Parms; i < arg_size; i++) {
     map()->init_req(i, inmap->argument(_caller, i - TypeFunc::Parms));
   }
 

@@ -1634,10 +1707,43 @@
 
   // Zap extra stack slots to top
   assert(sp() == target->start_sp(), "");
   clean_stack(sp());
 
+  // Check for merge conflicts involving value types
+  JVMState* old_jvms = map()->jvms();
+  int old_bci = bci();
+  JVMState* tmp_jvms = old_jvms->clone_shallow(C);
+  tmp_jvms->set_should_reexecute(true);
+  map()->set_jvms(tmp_jvms);
+  // Execution needs to restart a the next bytecode (entry of next
+  // block)
+  if (target->is_merged() ||
+      pnum > PhiNode::Input ||
+      target->is_handler() ||
+      target->is_loop_head()) {
+    set_parse_bci(target->start());
+    for (uint j = TypeFunc::Parms; j < map()->req(); j++) {
+      Node* n = map()->in(j);                 // Incoming change to target state.
+      const Type* t = NULL;
+      if (tmp_jvms->is_loc(j)) {
+        t = target->local_type_at(j - tmp_jvms->locoff());
+      } else if (tmp_jvms->is_stk(j) && j < (uint)sp() + tmp_jvms->stkoff()) {
+        t = target->stack_type_at(j - tmp_jvms->stkoff());
+      }
+      if (t != NULL && t != Type::BOTTOM) {
+        if (n->is_ValueType() && !t->isa_valuetype()) {
+          // Allocate value type in src block to be able to merge it with oop in target block
+          map()->set_req(j, ValueTypePtrNode::make_from_value_type(this, n->as_ValueType(), true));
+        }
+        assert(!t->isa_valuetype() || n->is_ValueType(), "inconsistent typeflow info");
+      }
+    }
+  }
+  map()->set_jvms(old_jvms);
+  set_parse_bci(old_bci);
+
   if (!target->is_merged()) {   // No prior mapping at this bci
     if (TraceOptoParse) { tty->print(" with empty state");  }
 
     // If this path is dead, do not bother capturing it as a merge.
     // It is "as if" we had 1 fewer predecessors from the beginning.

@@ -1687,10 +1793,11 @@
 #ifdef ASSERT
     if (target->is_SEL_head()) {
       target->mark_merged_backedge(block());
     }
 #endif
+
     // We must not manufacture more phis if the target is already parsed.
     bool nophi = target->is_parsed();
 
     SafePointNode* newin = map();// Hang on to incoming mapping
     Block* save_block = block(); // Hang on to incoming block;

@@ -1722,18 +1829,22 @@
     }
 
     // Update all the non-control inputs to map:
     assert(TypeFunc::Parms == newin->jvms()->locoff(), "parser map should contain only youngest jvms");
     bool check_elide_phi = target->is_SEL_backedge(save_block);
+    bool last_merge = (pnum == PhiNode::Input);
     for (uint j = 1; j < newin->req(); j++) {
       Node* m = map()->in(j);   // Current state of target.
       Node* n = newin->in(j);   // Incoming change to target state.
       PhiNode* phi;
-      if (m->is_Phi() && m->as_Phi()->region() == r)
+      if (m->is_Phi() && m->as_Phi()->region() == r) {
         phi = m->as_Phi();
-      else
+      } else if (m->is_ValueType() && m->as_ValueType()->has_phi_inputs(r)){
+        phi = m->as_ValueType()->get_oop()->as_Phi();
+      } else {
         phi = NULL;
+      }
       if (m != n) {             // Different; must merge
         switch (j) {
         // Frame pointer and Return Address never changes
         case TypeFunc::FramePtr:// Drop m, use the original value
         case TypeFunc::ReturnAdr:

@@ -1763,15 +1874,38 @@
       // At this point, n might be top if:
       //  - there is no phi (because TypeFlow detected a conflict), or
       //  - the corresponding control edges is top (a dead incoming path)
       // It is a bug if we create a phi which sees a garbage value on a live path.
 
-      if (phi != NULL) {
+      // Merging two value types?
+      if (phi != NULL && n->is_ValueType()) {
+        // Reload current state because it may have been updated by ensure_phi
+        m = map()->in(j);
+        ValueTypeNode* vtm = m->as_ValueType(); // Current value type
+        ValueTypeNode* vtn = n->as_ValueType(); // Incoming value type
+        assert(vtm->get_oop() == phi, "Value type should have Phi input");
+        if (TraceOptoParse) {
+#ifdef ASSERT
+          tty->print_cr("\nMerging value types");
+          tty->print_cr("Current:");
+          vtm->dump(2);
+          tty->print_cr("Incoming:");
+          vtn->dump(2);
+          tty->cr();
+#endif
+        }
+        // Do the merge
+        vtm->merge_with(&_gvn, vtn, pnum, last_merge);
+        if (last_merge) {
+          map()->set_req(j, _gvn.transform_no_reclaim(vtm));
+          record_for_igvn(vtm);
+        }
+      } else if (phi != NULL) {
         assert(n != top() || r->in(pnum) == top(), "live value must not be garbage");
         assert(phi->region() == r, "");
         phi->set_req(pnum, n);  // Then add 'n' to the merge
-        if (pnum == PhiNode::Input) {
+        if (last_merge) {
           // Last merge for this Phi.
           // So far, Phis have had a reasonable type from ciTypeFlow.
           // Now _gvn will join that with the meet of current inputs.
           // BOTTOM is never permissible here, 'cause pessimistically
           // Phis of pointers cannot lose the basic pointer type.

@@ -1783,12 +1917,11 @@
           record_for_igvn(phi);
         }
       }
     } // End of for all values to be merged
 
-    if (pnum == PhiNode::Input &&
-        !r->in(0)) {         // The occasional useless Region
+    if (last_merge && !r->in(0)) {         // The occasional useless Region
       assert(control() == r, "");
       set_control(r->nonnull_req());
     }
 
     map()->merge_replaced_nodes_with(newin);

@@ -1936,10 +2069,12 @@
       }
     } else {
       if (n->is_Phi() && n->as_Phi()->region() == r) {
         assert(n->req() == pnum, "must be same size as region");
         n->add_req(NULL);
+      } else if (n->is_ValueType() && n->as_ValueType()->has_phi_inputs(r)) {
+        n->as_ValueType()->add_new_path(r);
       }
     }
   }
 
   return pnum;

@@ -1958,10 +2093,14 @@
   if (o == top())  return NULL; // TOP always merges into TOP
 
   if (o->is_Phi() && o->as_Phi()->region() == region) {
     return o->as_Phi();
   }
+  ValueTypeBaseNode* vt = o->isa_ValueType();
+  if (vt != NULL && vt->has_phi_inputs(region)) {
+    return vt->get_oop()->as_Phi();
+  }
 
   // Now use a Phi here for merging
   assert(!nocreate, "Cannot build a phi for a block already parsed.");
   const JVMState* jvms = map->jvms();
   const Type* t = NULL;

@@ -1977,12 +2116,12 @@
   } else {
     assert(false, "no type information for this phi");
   }
 
   // If the type falls to bottom, then this must be a local that
-  // is mixing ints and oops or some such.  Forcing it to top
-  // makes it go dead.
+  // is already dead or is mixing ints and oops or some such.
+  // Forcing it to top makes it go dead.
   if (t == Type::BOTTOM) {
     map->set_req(idx, top());
     return NULL;
   }
 

@@ -1991,15 +2130,24 @@
   if (t == Type::TOP || t == Type::HALF) {
     map->set_req(idx, top());
     return NULL;
   }
 
-  PhiNode* phi = PhiNode::make(region, o, t);
-  gvn().set_type(phi, t);
-  if (C->do_escape_analysis()) record_for_igvn(phi);
-  map->set_req(idx, phi);
-  return phi;
+  if (vt != NULL) {
+    // Value types are merged by merging their field values.
+    // Create a cloned ValueTypeNode with phi inputs that
+    // represents the merged value type and update the map.
+    vt = vt->clone_with_phis(&_gvn, region);
+    map->set_req(idx, vt);
+    return vt->get_oop()->as_Phi();
+  } else {
+    PhiNode* phi = PhiNode::make(region, o, t);
+    gvn().set_type(phi, t);
+    if (C->do_escape_analysis()) record_for_igvn(phi);
+    map->set_req(idx, phi);
+    return phi;
+  }
 }
 
 //--------------------------ensure_memory_phi----------------------------------
 // Turn the idx'th slice of the current memory into a Phi
 PhiNode *Parse::ensure_memory_phi(int idx, bool nocreate) {

@@ -2188,64 +2336,81 @@
       method()->intrinsic_id() == vmIntrinsics::_Object_init) {
     call_register_finalizer();
   }
 
   // Do not set_parse_bci, so that return goo is credited to the return insn.
-  set_bci(InvocationEntryBci);
+  // vreturn can trigger an allocation so vreturn can throw. Setting
+  // the bci here breaks exception handling. Commenting this out
+  // doesn't seem to break anything.
+  //  set_bci(InvocationEntryBci);
   if (method()->is_synchronized() && GenerateSynchronizationCode) {
     shared_unlock(_synch_lock->box_node(), _synch_lock->obj_node());
   }
   if (C->env()->dtrace_method_probes()) {
     make_dtrace_method_exit(method());
   }
-  SafePointNode* exit_return = _exits.map();
-  exit_return->in( TypeFunc::Control  )->add_req( control() );
-  exit_return->in( TypeFunc::I_O      )->add_req( i_o    () );
-  Node *mem = exit_return->in( TypeFunc::Memory   );
-  for (MergeMemStream mms(mem->as_MergeMem(), merged_memory()); mms.next_non_empty2(); ) {
-    if (mms.is_empty()) {
-      // get a copy of the base memory, and patch just this one input
-      const TypePtr* adr_type = mms.adr_type(C);
-      Node* phi = mms.force_memory()->as_Phi()->slice_memory(adr_type);
-      assert(phi->as_Phi()->region() == mms.base_memory()->in(0), "");
-      gvn().set_type_bottom(phi);
-      phi->del_req(phi->req()-1);  // prepare to re-patch
-      mms.set_memory(phi);
-    }
-    mms.memory()->add_req(mms.memory2());
-  }
-
   // frame pointer is always same, already captured
   if (value != NULL) {
-    // If returning oops to an interface-return, there is a silent free
-    // cast from oop to interface allowed by the Verifier.  Make it explicit
-    // here.
     Node* phi = _exits.argument(0);
-    const TypeInstPtr *tr = phi->bottom_type()->isa_instptr();
-    if (tr && tr->klass()->is_loaded() &&
-        tr->klass()->is_interface()) {
-      const TypeInstPtr *tp = value->bottom_type()->isa_instptr();
-      if (tp && tp->klass()->is_loaded() &&
-          !tp->klass()->is_interface()) {
+    const Type* return_type = phi->bottom_type();
+    const TypeOopPtr* tr = return_type->isa_oopptr();
+    if (return_type->isa_valuetype()) {
+      // Value type is returned as fields, make sure it is scalarized
+      if (!value->is_ValueType()) {
+        value = ValueTypeNode::make_from_oop(this, value, return_type->value_klass());
+      }
+      if (!_caller->has_method()) {
+        // Value type is returned as fields from root method, make
+        // sure all non-flattened value type fields are allocated.
+        assert(tf()->returns_value_type_as_fields(), "must be returned as fields");
+        value = value->as_ValueType()->allocate_fields(this);
+      }
+    } else if (value->is_ValueType()) {
+      // Value type is returned as oop, make sure it is allocated
+      assert(tr && tr->can_be_value_type(), "must return a value type pointer");
+      value = ValueTypePtrNode::make_from_value_type(this, value->as_ValueType());
+    } else if (tr && tr->isa_instptr() && tr->klass()->is_loaded() && tr->klass()->is_interface()) {
+      // If returning oops to an interface-return, there is a silent free
+      // cast from oop to interface allowed by the Verifier. Make it explicit here.
+      const TypeInstPtr* tp = value->bottom_type()->isa_instptr();
+      if (tp && tp->klass()->is_loaded() && !tp->klass()->is_interface()) {
         // sharpen the type eagerly; this eases certain assert checking
-        if (tp->higher_equal(TypeInstPtr::NOTNULL))
+        if (tp->higher_equal(TypeInstPtr::NOTNULL)) {
           tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr();
+        }
         value = _gvn.transform(new CheckCastPPNode(0, value, tr));
       }
     } else {
-      // Also handle returns of oop-arrays to an arrays-of-interface return
+      // Handle returns of oop-arrays to an arrays-of-interface return
       const TypeInstPtr* phi_tip;
       const TypeInstPtr* val_tip;
-      Type::get_arrays_base_elements(phi->bottom_type(), value->bottom_type(), &phi_tip, &val_tip);
+      Type::get_arrays_base_elements(return_type, value->bottom_type(), &phi_tip, &val_tip);
       if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->klass()->is_interface() &&
           val_tip != NULL && val_tip->is_loaded() && !val_tip->klass()->is_interface()) {
-        value = _gvn.transform(new CheckCastPPNode(0, value, phi->bottom_type()));
+        value = _gvn.transform(new CheckCastPPNode(0, value, return_type));
       }
     }
     phi->add_req(value);
   }
 
+  SafePointNode* exit_return = _exits.map();
+  exit_return->in( TypeFunc::Control  )->add_req( control() );
+  exit_return->in( TypeFunc::I_O      )->add_req( i_o    () );
+  Node *mem = exit_return->in( TypeFunc::Memory   );
+  for (MergeMemStream mms(mem->as_MergeMem(), merged_memory()); mms.next_non_empty2(); ) {
+    if (mms.is_empty()) {
+      // get a copy of the base memory, and patch just this one input
+      const TypePtr* adr_type = mms.adr_type(C);
+      Node* phi = mms.force_memory()->as_Phi()->slice_memory(adr_type);
+      assert(phi->as_Phi()->region() == mms.base_memory()->in(0), "");
+      gvn().set_type_bottom(phi);
+      phi->del_req(phi->req()-1);  // prepare to re-patch
+      mms.set_memory(phi);
+    }
+    mms.memory()->add_req(mms.memory2());
+  }
+
   if (_first_return) {
     _exits.map()->transfer_replaced_nodes_from(map(), _new_idx);
     _first_return = false;
   } else {
     _exits.map()->merge_replaced_nodes_with(map());
< prev index next >