< prev index next >
src/share/vm/opto/matcher.cpp
Print this page
@@ -166,10 +166,56 @@
}
}
}
#endif
+// Array of RegMask, one per returned values (value type instances can
+// be returned as multiple return values, one per field)
+RegMask* Matcher::return_values_mask(const TypeTuple *range) {
+ uint cnt = range->cnt() - TypeFunc::Parms;
+ if (cnt == 0) {
+ return NULL;
+ }
+ RegMask* mask = NEW_RESOURCE_ARRAY(RegMask, cnt);
+
+ if (!ValueTypeReturnedAsFields) {
+ // Get ideal-register return type
+ uint ireg = range->field_at(TypeFunc::Parms)->ideal_reg();
+ // Get machine return register
+ OptoRegPair regs = return_value(ireg, false);
+
+ // And mask for same
+ mask[0].Clear();
+ mask[0].Insert(regs.first());
+ if (OptoReg::is_valid(regs.second())) {
+ mask[0].Insert(regs.second());
+ }
+ } else {
+ BasicType *sig_bt = NEW_RESOURCE_ARRAY(BasicType, cnt);
+ VMRegPair *vm_parm_regs = NEW_RESOURCE_ARRAY(VMRegPair, cnt);
+
+ for (uint i = 0; i < cnt; i++) {
+ sig_bt[i] = range->field_at(i+TypeFunc::Parms)->basic_type();
+ }
+
+ int regs = SharedRuntime::java_return_convention(sig_bt, vm_parm_regs, cnt);
+ assert(regs > 0, "should have been tested during graph construction");
+ for (uint i = 0; i < cnt; i++) {
+ mask[i].Clear();
+
+ OptoReg::Name reg1 = OptoReg::as_OptoReg(vm_parm_regs[i].first());
+ if (OptoReg::is_valid(reg1)) {
+ mask[i].Insert(reg1);
+ }
+ OptoReg::Name reg2 = OptoReg::as_OptoReg(vm_parm_regs[i].second());
+ if (OptoReg::is_valid(reg2)) {
+ mask[i].Insert(reg2);
+ }
+ }
+ }
+ return mask;
+}
//---------------------------match---------------------------------------------
void Matcher::match( ) {
if( MaxLabelRootDepth < 100 ) { // Too small?
assert(false, "invalid MaxLabelRootDepth, increase it to 100 minimum");
@@ -181,25 +227,14 @@
#ifdef _LP64
// Pointers take 2 slots in 64-bit land
_return_addr_mask.Insert(OptoReg::add(return_addr(),1));
#endif
- // Map a Java-signature return type into return register-value
- // machine registers for 0, 1 and 2 returned values.
- const TypeTuple *range = C->tf()->range();
- if( range->cnt() > TypeFunc::Parms ) { // If not a void function
- // Get ideal-register return type
- uint ireg = range->field_at(TypeFunc::Parms)->ideal_reg();
- // Get machine return register
- uint sop = C->start()->Opcode();
- OptoRegPair regs = return_value(ireg, false);
-
- // And mask for same
- _return_value_mask = RegMask(regs.first());
- if( OptoReg::is_valid(regs.second()) )
- _return_value_mask.Insert(regs.second());
- }
+ // Map Java-signature return types into return register-value
+ // machine registers.
+ const TypeTuple *range = C->tf()->range_cc();
+ _return_values_mask = return_values_mask(range);
// ---------------
// Frame Layout
// Need the method signature to determine the incoming argument types,
@@ -649,16 +684,15 @@
soe_cnt++;
// Input RegMask array shared by all Returns.
// The type for doubles and longs has a count of 2, but
// there is only 1 returned value
- uint ret_edge_cnt = TypeFunc::Parms + ((C->tf()->range()->cnt() == TypeFunc::Parms) ? 0 : 1);
+ uint ret_edge_cnt = C->tf()->range_cc()->cnt();
RegMask *ret_rms = init_input_masks( ret_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask );
- // Returns have 0 or 1 returned values depending on call signature.
- // Return register is specified by return_value in the AD file.
- if (ret_edge_cnt > TypeFunc::Parms)
- ret_rms[TypeFunc::Parms+0] = _return_value_mask;
+ for (i = TypeFunc::Parms; i < ret_edge_cnt; i++) {
+ ret_rms[i] = _return_values_mask[i-TypeFunc::Parms];
+ }
// Input RegMask array shared by all Rethrows.
uint reth_edge_cnt = TypeFunc::Parms+1;
RegMask *reth_rms = init_input_masks( reth_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask );
// Rethrow takes exception oop only, but in the argument 0 slot.
@@ -1000,11 +1034,15 @@
if (C->failing()) return NULL;
if (m == NULL) { Matcher::soft_match_failure(); return NULL; }
} else { // Nothing the matcher cares about
if( n->is_Proj() && n->in(0)->is_Multi()) { // Projections?
// Convert to machine-dependent projection
- m = n->in(0)->as_Multi()->match( n->as_Proj(), this );
+ RegMask* mask = NULL;
+ if (n->in(0)->is_Call()) {
+ mask = return_values_mask(n->in(0)->as_Call()->tf()->range_cc());
+ }
+ m = n->in(0)->as_Multi()->match(n->as_Proj(), this, mask);
#ifdef ASSERT
_new2old_map.map(m->_idx, n);
#endif
if (m->in(0) != NULL) // m might be top
collect_null_checks(m, n);
@@ -1300,11 +1338,11 @@
// Kill the outgoing argument area, including any non-argument holes and
// any legacy C-killed slots. Use Fat-Projections to do the killing.
// Since the max-per-method covers the max-per-call-site and debug info
// is excluded on the max-per-method basis, debug info cannot land in
// this killed area.
- uint r_cnt = mcall->tf()->range()->cnt();
+ uint r_cnt = mcall->tf()->range_sig()->cnt();
MachProjNode *proj = new MachProjNode( mcall, r_cnt+10000, RegMask::Empty, MachProjNode::fat_proj );
if (!RegMask::can_represent_arg(OptoReg::Name(out_arg_limit_per_call-1))) {
C->record_method_not_compilable("unsupported outgoing calling sequence");
} else {
for (int i = begin_out_arg_area; i < out_arg_limit_per_call; i++)
< prev index next >