< prev index next >

src/hotspot/share/opto/matcher.cpp

Print this page

        

*** 170,179 **** --- 170,225 ---- } } } #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");
*** 185,217 **** #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()); ! } // --------------- // Frame Layout // Need the method signature to determine the incoming argument types, // because the types determine which registers the incoming arguments are // in, and this affects the matched code. ! const TypeTuple *domain = C->tf()->domain(); uint argcnt = domain->cnt() - TypeFunc::Parms; BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, argcnt ); VMRegPair *vm_parm_regs = NEW_RESOURCE_ARRAY( VMRegPair, argcnt ); _parm_regs = NEW_RESOURCE_ARRAY( OptoRegPair, argcnt ); _calling_convention_mask = NEW_RESOURCE_ARRAY( RegMask, argcnt ); --- 231,252 ---- #ifdef _LP64 // Pointers take 2 slots in 64-bit land _return_addr_mask.Insert(OptoReg::add(return_addr(),1)); #endif ! // 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, // because the types determine which registers the incoming arguments are // in, and this affects the matched code. ! const TypeTuple *domain = C->tf()->domain_cc(); uint argcnt = domain->cnt() - TypeFunc::Parms; BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, argcnt ); VMRegPair *vm_parm_regs = NEW_RESOURCE_ARRAY( VMRegPair, argcnt ); _parm_regs = NEW_RESOURCE_ARRAY( OptoRegPair, argcnt ); _calling_convention_mask = NEW_RESOURCE_ARRAY( RegMask, argcnt );
*** 467,476 **** --- 502,530 ---- // Add in the incoming argument area OptoReg::Name init_in = OptoReg::add(_old_SP, C->out_preserve_stack_slots()); for (i = init_in; i < _in_arg_limit; i = OptoReg::add(i,1)) { C->FIRST_STACK_mask().Insert(i); } + + // Check if the method has a reserved entry in the argument stack area that + // should not be used for spilling because it may hold the return address. + if (C->method() != NULL && C->method()->has_scalarized_args()) { + ExtendedSignature sig_cc = ExtendedSignature(C->method()->get_sig_cc(), SigEntryFilter()); + for (int off = 0; !sig_cc.at_end(); ) { + BasicType bt = (*sig_cc)._bt; + off += type2size[bt]; + while (SigEntry::next_is_reserved(sig_cc, bt)) { + // Remove reserved stack slot from mask to avoid spilling + OptoRegPair reg = _parm_regs[off]; + assert(OptoReg::is_valid(reg.first()), "invalid reserved register"); + C->FIRST_STACK_mask().Remove(reg.first()); + C->FIRST_STACK_mask().Remove(reg.first()+1); // Always occupies two stack slots + off += type2size[bt]; + } + } + } + // Add in all bits past the outgoing argument area guarantee(RegMask::can_represent_arg(OptoReg::add(_out_arg_limit,-1)), "must be able to represent all call arguments in reg mask"); OptoReg::Name init = _out_arg_limit; for (i = init; RegMask::can_represent(i); i = OptoReg::add(i,1)) {
*** 659,674 **** 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); 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; // 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. --- 713,727 ---- 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 = C->tf()->range_cc()->cnt(); RegMask *ret_rms = init_input_masks( ret_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_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.
*** 731,741 **** default : ShouldNotReachHere(); } } // Next unused projection number from Start. ! int proj_cnt = C->tf()->domain()->cnt(); // Do all the save-on-entry registers. Make projections from Start for // them, and give them a use at the exit points. To the allocator, they // look like incoming register arguments. for( i = 0; i < _last_Mach_Reg; i++ ) { --- 784,794 ---- default : ShouldNotReachHere(); } } // Next unused projection number from Start. ! int proj_cnt = C->tf()->domain_cc()->cnt(); // Do all the save-on-entry registers. Make projections from Start for // them, and give them a use at the exit points. To the allocator, they // look like incoming register arguments. for( i = 0; i < _last_Mach_Reg; i++ ) {
*** 1012,1022 **** m->as_MachMemBar()->set_adr_type(n->adr_type()); } } else { // Nothing the matcher cares about if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Multi()) { // Projections? // Convert to machine-dependent projection ! m = n->in(0)->as_Multi()->match( n->as_Proj(), this ); #ifdef ASSERT _new2old_map.map(m->_idx, n); #endif if (m->in(0) != NULL) // m might be top collect_null_checks(m, n); --- 1065,1079 ---- m->as_MachMemBar()->set_adr_type(n->adr_type()); } } else { // Nothing the matcher cares about if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Multi()) { // Projections? // Convert to machine-dependent projection ! 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);
*** 1157,1167 **** const TypeTuple *domain; ciMethod* method = NULL; bool is_method_handle_invoke = false; // for special kill effects if( sfpt->is_Call() ) { call = sfpt->as_Call(); ! domain = call->tf()->domain(); cnt = domain->cnt(); // Match just the call, nothing else MachNode *m = match_tree(call); if (C->failing()) return NULL; --- 1214,1224 ---- const TypeTuple *domain; ciMethod* method = NULL; bool is_method_handle_invoke = false; // for special kill effects if( sfpt->is_Call() ) { call = sfpt->as_Call(); ! domain = call->tf()->domain_cc(); cnt = domain->cnt(); // Match just the call, nothing else MachNode *m = match_tree(call); if (C->failing()) return NULL;
*** 1232,1248 **** if( call != NULL && call->is_CallRuntime() ) out_arg_limit_per_call = OptoReg::add(out_arg_limit_per_call,C->varargs_C_out_slots_killed()); // Do the normal argument list (parameters) register masks ! int argcnt = cnt - TypeFunc::Parms; if( argcnt > 0 ) { // Skip it all if we have no args BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, argcnt ); VMRegPair *parm_regs = NEW_RESOURCE_ARRAY( VMRegPair, argcnt ); int i; for( i = 0; i < argcnt; i++ ) { ! sig_bt[i] = domain->field_at(i+TypeFunc::Parms)->basic_type(); } // V-call to pick proper calling convention call->calling_convention( sig_bt, parm_regs, argcnt ); #ifdef ASSERT --- 1289,1308 ---- if( call != NULL && call->is_CallRuntime() ) out_arg_limit_per_call = OptoReg::add(out_arg_limit_per_call,C->varargs_C_out_slots_killed()); // Do the normal argument list (parameters) register masks ! // Null entry point is a special cast where the target of the call ! // is in a register. ! int adj = (call != NULL && call->entry_point() == NULL) ? 1 : 0; ! int argcnt = cnt - TypeFunc::Parms - adj; if( argcnt > 0 ) { // Skip it all if we have no args BasicType *sig_bt = NEW_RESOURCE_ARRAY( BasicType, argcnt ); VMRegPair *parm_regs = NEW_RESOURCE_ARRAY( VMRegPair, argcnt ); int i; for( i = 0; i < argcnt; i++ ) { ! sig_bt[i] = domain->field_at(i+TypeFunc::Parms+adj)->basic_type(); } // V-call to pick proper calling convention call->calling_convention( sig_bt, parm_regs, argcnt ); #ifdef ASSERT
*** 1279,1301 **** // Return results now can have 2 bits returned. // Compute max over all outgoing arguments both per call-site // and over the entire method. for( i = 0; i < argcnt; i++ ) { // Address of incoming argument mask to fill in ! RegMask *rm = &mcall->_in_rms[i+TypeFunc::Parms]; if( !parm_regs[i].first()->is_valid() && !parm_regs[i].second()->is_valid() ) { continue; // Avoid Halves } // Grab first register, adjust stack slots and insert in mask. OptoReg::Name reg1 = warp_outgoing_stk_arg(parm_regs[i].first(), begin_out_arg_area, out_arg_limit_per_call ); ! if (OptoReg::is_valid(reg1)) rm->Insert( reg1 ); // Grab second register (if any), adjust stack slots and insert in mask. OptoReg::Name reg2 = warp_outgoing_stk_arg(parm_regs[i].second(), begin_out_arg_area, out_arg_limit_per_call ); ! if (OptoReg::is_valid(reg2)) rm->Insert( reg2 ); } // End of for all arguments // Compute number of stack slots needed to restore stack in case of // Pascal-style argument popping. mcall->_argsize = out_arg_limit_per_call - begin_out_arg_area; --- 1339,1363 ---- // Return results now can have 2 bits returned. // Compute max over all outgoing arguments both per call-site // and over the entire method. for( i = 0; i < argcnt; i++ ) { // Address of incoming argument mask to fill in ! RegMask *rm = &mcall->_in_rms[i+TypeFunc::Parms+adj]; if( !parm_regs[i].first()->is_valid() && !parm_regs[i].second()->is_valid() ) { continue; // Avoid Halves } // Grab first register, adjust stack slots and insert in mask. OptoReg::Name reg1 = warp_outgoing_stk_arg(parm_regs[i].first(), begin_out_arg_area, out_arg_limit_per_call ); ! if (OptoReg::is_valid(reg1)) { rm->Insert( reg1 ); + } // Grab second register (if any), adjust stack slots and insert in mask. OptoReg::Name reg2 = warp_outgoing_stk_arg(parm_regs[i].second(), begin_out_arg_area, out_arg_limit_per_call ); ! if (OptoReg::is_valid(reg2)) { rm->Insert( reg2 ); + } } // End of for all arguments // Compute number of stack slots needed to restore stack in case of // Pascal-style argument popping. mcall->_argsize = out_arg_limit_per_call - begin_out_arg_area;
*** 1311,1321 **** // 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(); 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++) --- 1373,1383 ---- // 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_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++)
*** 1332,1342 **** jvms->set_map(sfpt); } // Debug inputs begin just after the last incoming parameter assert((mcall == NULL) || (mcall->jvms() == NULL) || ! (mcall->jvms()->debug_start() + mcall->_jvmadj == mcall->tf()->domain()->cnt()), ""); // Move the OopMap msfpt->_oop_map = sfpt->_oop_map; // Add additional edges. --- 1394,1404 ---- jvms->set_map(sfpt); } // Debug inputs begin just after the last incoming parameter assert((mcall == NULL) || (mcall->jvms() == NULL) || ! (mcall->jvms()->debug_start() + mcall->_jvmadj == mcall->tf()->domain_cc()->cnt()), ""); // Move the OopMap msfpt->_oop_map = sfpt->_oop_map; // Add additional edges.
*** 2366,2375 **** --- 2428,2444 ---- n->set_req(2, pair2); n->del_req(4); n->del_req(3); break; } + case Op_ClearArray: { + Node* pair = new BinaryNode(n->in(2), n->in(3)); + n->set_req(2, pair); + n->set_req(3, n->in(4)); + n->del_req(4); + break; + } default: break; } }
< prev index next >