Mercurial > hg > truffle
view src/share/vm/adlc/formsopt.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 8c92982cbbc4 |
children |
line wrap: on
line source
/* * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ // FORMS.CPP - Definitions for ADL Parser Forms Classes #include "adlc.hpp" //==============================Register Allocation============================ int RegisterForm::_reg_ctr = 0; //------------------------------RegisterForm----------------------------------- // Constructor RegisterForm::RegisterForm() : _regDef(cmpstr,hashstr, Form::arena), _regClass(cmpstr,hashstr, Form::arena), _allocClass(cmpstr,hashstr, Form::arena) { } RegisterForm::~RegisterForm() { } // record a new register definition void RegisterForm::addRegDef(char *name, char *callingConv, char *c_conv, char *idealtype, char *encoding, char* concrete) { RegDef *regDef = new RegDef(name, callingConv, c_conv, idealtype, encoding, concrete); _rdefs.addName(name); _regDef.Insert(name,regDef); } // record a new register class RegClass *RegisterForm::addRegClass(const char *className) { RegClass *regClass = new RegClass(className); _rclasses.addName(className); _regClass.Insert(className,regClass); return regClass; } // record a new register class AllocClass *RegisterForm::addAllocClass(char *className) { AllocClass *allocClass = new AllocClass(className); _aclasses.addName(className); _allocClass.Insert(className,allocClass); return allocClass; } // Called after parsing the Register block. Record the register class // for spill-slots/regs. void RegisterForm::addSpillRegClass() { // Stack slots start at the next available even register number. _reg_ctr = (_reg_ctr+7) & ~7; const char *rc_name = "stack_slots"; RegClass *reg_class = new RegClass(rc_name); reg_class->_stack_or_reg = true; _rclasses.addName(rc_name); _regClass.Insert(rc_name,reg_class); } // Provide iteration over all register definitions // in the order used by the register allocator void RegisterForm::reset_RegDefs() { _current_ac = NULL; _aclasses.reset(); } RegDef *RegisterForm::iter_RegDefs() { // Check if we need to get the next AllocClass if ( _current_ac == NULL ) { const char *ac_name = _aclasses.iter(); if( ac_name == NULL ) return NULL; // No more allocation classes _current_ac = (AllocClass*)_allocClass[ac_name]; _current_ac->_regDefs.reset(); assert( _current_ac != NULL, "Name must match an allocation class"); } const char *rd_name = _current_ac->_regDefs.iter(); if( rd_name == NULL ) { // At end of this allocation class, check the next _current_ac = NULL; return iter_RegDefs(); } RegDef *reg_def = (RegDef*)_current_ac->_regDef[rd_name]; assert( reg_def != NULL, "Name must match a register definition"); return reg_def; } // return the register definition with name 'regName' RegDef *RegisterForm::getRegDef(const char *regName) { RegDef *regDef = (RegDef*)_regDef[regName]; return regDef; } // return the register class with name 'className' RegClass *RegisterForm::getRegClass(const char *className) { RegClass *regClass = (RegClass*)_regClass[className]; return regClass; } // Check that register classes are compatible with chunks bool RegisterForm::verify() { bool valid = true; // Verify Register Classes // check that each register class contains registers from one chunk const char *rc_name = NULL; _rclasses.reset(); while ( (rc_name = _rclasses.iter()) != NULL ) { // Check the chunk value for all registers in this class RegClass *reg_class = getRegClass(rc_name); assert( reg_class != NULL, "InternalError() no matching register class"); } // end of RegClasses // Verify that every register has been placed into an allocation class RegDef *reg_def = NULL; reset_RegDefs(); uint num_register_zero = 0; while ( (reg_def = iter_RegDefs()) != NULL ) { if( reg_def->register_num() == 0 ) ++num_register_zero; } if( num_register_zero > 1 ) { fprintf(stderr, "ERROR: More than one register has been assigned register-number 0.\n" "Probably because a register has not been entered into an allocation class.\n"); } return valid; } // Compute RegMask size int RegisterForm::RegMask_Size() { // Need at least this many words int words_for_regs = (_reg_ctr + 31)>>5; // The array of Register Mask bits should be large enough to cover // all the machine registers and all parameters that need to be passed // on the stack (stack registers) up to some interesting limit. Methods // that need more parameters will NOT be compiled. On Intel, the limit // is something like 90+ parameters. // Add a few (3 words == 96 bits) for incoming & outgoing arguments to calls. // Round up to the next doubleword size. return (words_for_regs + 3 + 1) & ~1; } void RegisterForm::dump() { // Debug printer output(stderr); } void RegisterForm::output(FILE *fp) { // Write info to output files const char *name; fprintf(fp,"\n"); fprintf(fp,"-------------------- Dump RegisterForm --------------------\n"); for(_rdefs.reset(); (name = _rdefs.iter()) != NULL;) { ((RegDef*)_regDef[name])->output(fp); } fprintf(fp,"\n"); for (_rclasses.reset(); (name = _rclasses.iter()) != NULL;) { ((RegClass*)_regClass[name])->output(fp); } fprintf(fp,"\n"); for (_aclasses.reset(); (name = _aclasses.iter()) != NULL;) { ((AllocClass*)_allocClass[name])->output(fp); } fprintf(fp,"-------------------- end RegisterForm --------------------\n"); } //------------------------------RegDef----------------------------------------- // Constructor RegDef::RegDef(char *regname, char *callconv, char *c_conv, char * idealtype, char * encode, char * concrete) : _regname(regname), _callconv(callconv), _c_conv(c_conv), _idealtype(idealtype), _register_encode(encode), _concrete(concrete), _register_num(0) { // Chunk and register mask are determined by the register number // _register_num is set when registers are added to an allocation class } RegDef::~RegDef() { // Destructor } void RegDef::set_register_num(uint32 register_num) { _register_num = register_num; } // Bit pattern used for generating machine code const char* RegDef::register_encode() const { return _register_encode; } // Register number used in machine-independent code uint32 RegDef::register_num() const { return _register_num; } void RegDef::dump() { output(stderr); } void RegDef::output(FILE *fp) { // Write info to output files fprintf(fp,"RegDef: %s (%s) encode as %s using number %d\n", _regname, (_callconv?_callconv:""), _register_encode, _register_num); fprintf(fp,"\n"); } //------------------------------RegClass--------------------------------------- // Construct a register class into which registers will be inserted RegClass::RegClass(const char *classid) : _stack_or_reg(false), _classid(classid), _regDef(cmpstr,hashstr, Form::arena), _user_defined(NULL) { } // record a register in this class void RegClass::addReg(RegDef *regDef) { _regDefs.addName(regDef->_regname); _regDef.Insert((void*)regDef->_regname, regDef); } // Number of registers in class uint RegClass::size() const { return _regDef.Size(); } const RegDef *RegClass::get_RegDef(const char *rd_name) const { return (const RegDef*)_regDef[rd_name]; } void RegClass::reset() { _regDefs.reset(); } const char *RegClass::rd_name_iter() { return _regDefs.iter(); } RegDef *RegClass::RegDef_iter() { const char *rd_name = rd_name_iter(); RegDef *reg_def = rd_name ? (RegDef*)_regDef[rd_name] : NULL; return reg_def; } const RegDef* RegClass::find_first_elem() { const RegDef* first = NULL; const RegDef* def = NULL; reset(); while ((def = RegDef_iter()) != NULL) { if (first == NULL || def->register_num() < first->register_num()) { first = def; } } assert(first != NULL, "empty mask?"); return first;; } // Collect all the registers in this register-word. One bit per register. int RegClass::regs_in_word( int wordnum, bool stack_also ) { int word = 0; const char *name; for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { int rnum = ((RegDef*)_regDef[name])->register_num(); if( (rnum >> 5) == wordnum ) word |= (1 << (rnum & 31)); } if( stack_also ) { // Now also collect stack bits for( int i = 0; i < 32; i++ ) if( wordnum*32+i >= RegisterForm::_reg_ctr ) word |= (1 << i); } return word; } void RegClass::dump() { output(stderr); } void RegClass::output(FILE *fp) { // Write info to output files fprintf(fp,"RegClass: %s\n",_classid); const char *name; for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { ((RegDef*)_regDef[name])->output(fp); } fprintf(fp,"--- done with entries for reg_class %s\n\n",_classid); } //------------------------------AllocClass------------------------------------- AllocClass::AllocClass(char *classid) : _classid(classid), _regDef(cmpstr,hashstr, Form::arena) { } // record a register in this class void AllocClass::addReg(RegDef *regDef) { assert( regDef != NULL, "Can not add a NULL to an allocation class"); regDef->set_register_num( RegisterForm::_reg_ctr++ ); // Add regDef to this allocation class _regDefs.addName(regDef->_regname); _regDef.Insert((void*)regDef->_regname, regDef); } void AllocClass::dump() { output(stderr); } void AllocClass::output(FILE *fp) { // Write info to output files fprintf(fp,"AllocClass: %s \n",_classid); const char *name; for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { ((RegDef*)_regDef[name])->output(fp); } fprintf(fp,"--- done with entries for alloc_class %s\n\n",_classid); } //==============================Frame Handling================================= //------------------------------FrameForm-------------------------------------- FrameForm::FrameForm() { _frame_pointer = NULL; _c_frame_pointer = NULL; _alignment = NULL; _return_addr = NULL; _c_return_addr = NULL; _in_preserve_slots = NULL; _varargs_C_out_slots_killed = NULL; _calling_convention = NULL; _c_calling_convention = NULL; _return_value = NULL; _c_return_value = NULL; _interpreter_frame_pointer_reg = NULL; } FrameForm::~FrameForm() { } void FrameForm::dump() { output(stderr); } void FrameForm::output(FILE *fp) { // Write info to output files fprintf(fp,"\nFrame:\n"); } //==============================Scheduling===================================== //------------------------------PipelineForm----------------------------------- PipelineForm::PipelineForm() : _reslist () , _resdict (cmpstr, hashstr, Form::arena) , _classdict (cmpstr, hashstr, Form::arena) , _rescount (0) , _maxcycleused (0) , _stages () , _stagecnt (0) , _classlist () , _classcnt (0) , _noplist () , _nopcnt (0) , _variableSizeInstrs (false) , _branchHasDelaySlot (false) , _maxInstrsPerBundle (0) , _maxBundlesPerCycle (1) , _instrUnitSize (0) , _bundleUnitSize (0) , _instrFetchUnitSize (0) , _instrFetchUnits (0) { } PipelineForm::~PipelineForm() { } void PipelineForm::dump() { output(stderr); } void PipelineForm::output(FILE *fp) { // Write info to output files const char *res; const char *stage; const char *cls; const char *nop; int count = 0; fprintf(fp,"\nPipeline:"); if (_variableSizeInstrs) if (_instrUnitSize > 0) fprintf(fp," variable-sized instructions in %d byte units", _instrUnitSize); else fprintf(fp," variable-sized instructions"); else if (_instrUnitSize > 0) fprintf(fp," fixed-sized instructions of %d bytes", _instrUnitSize); else if (_bundleUnitSize > 0) fprintf(fp," fixed-sized bundles of %d bytes", _bundleUnitSize); else fprintf(fp," fixed-sized instructions"); if (_branchHasDelaySlot) fprintf(fp,", branch has delay slot"); if (_maxInstrsPerBundle > 0) fprintf(fp,", max of %d instruction%s in parallel", _maxInstrsPerBundle, _maxInstrsPerBundle > 1 ? "s" : ""); if (_maxBundlesPerCycle > 0) fprintf(fp,", max of %d bundle%s in parallel", _maxBundlesPerCycle, _maxBundlesPerCycle > 1 ? "s" : ""); if (_instrFetchUnitSize > 0 && _instrFetchUnits) fprintf(fp, ", fetch %d x % d bytes per cycle", _instrFetchUnits, _instrFetchUnitSize); fprintf(fp,"\nResource:"); for ( _reslist.reset(); (res = _reslist.iter()) != NULL; ) fprintf(fp," %s(0x%08x)", res, _resdict[res]->is_resource()->mask()); fprintf(fp,"\n"); fprintf(fp,"\nDescription:\n"); for ( _stages.reset(); (stage = _stages.iter()) != NULL; ) fprintf(fp," %s(%d)", stage, count++); fprintf(fp,"\n"); fprintf(fp,"\nClasses:\n"); for ( _classlist.reset(); (cls = _classlist.iter()) != NULL; ) _classdict[cls]->is_pipeclass()->output(fp); fprintf(fp,"\nNop Instructions:"); for ( _noplist.reset(); (nop = _noplist.iter()) != NULL; ) fprintf(fp, " \"%s\"", nop); fprintf(fp,"\n"); } //------------------------------ResourceForm----------------------------------- ResourceForm::ResourceForm(unsigned resmask) : _resmask(resmask) { } ResourceForm::~ResourceForm() { } ResourceForm *ResourceForm::is_resource() const { return (ResourceForm *)(this); } void ResourceForm::dump() { output(stderr); } void ResourceForm::output(FILE *fp) { // Write info to output files fprintf(fp, "resource: 0x%08x;\n", mask()); } //------------------------------PipeClassOperandForm---------------------------------- void PipeClassOperandForm::dump() { output(stderr); } void PipeClassOperandForm::output(FILE *fp) { // Write info to output files fprintf(stderr,"PipeClassOperandForm: %s", _stage); fflush(stderr); if (_more_instrs > 0) fprintf(stderr,"+%d", _more_instrs); fprintf(stderr," (%s)\n", _iswrite ? "write" : "read"); fflush(stderr); fprintf(fp,"PipeClassOperandForm: %s", _stage); if (_more_instrs > 0) fprintf(fp,"+%d", _more_instrs); fprintf(fp," (%s)\n", _iswrite ? "write" : "read"); } //------------------------------PipeClassResourceForm---------------------------------- void PipeClassResourceForm::dump() { output(stderr); } void PipeClassResourceForm::output(FILE *fp) { // Write info to output files fprintf(fp,"PipeClassResourceForm: %s at stage %s for %d cycles\n", _resource, _stage, _cycles); } //------------------------------PipeClassForm---------------------------------- PipeClassForm::PipeClassForm(const char *id, int num) : _ident(id) , _num(num) , _localNames(cmpstr, hashstr, Form::arena) , _localUsage(cmpstr, hashstr, Form::arena) , _has_fixed_latency(0) , _fixed_latency(0) , _instruction_count(0) , _has_multiple_bundles(false) , _has_branch_delay_slot(false) , _force_serialization(false) , _may_have_no_code(false) { } PipeClassForm::~PipeClassForm() { } PipeClassForm *PipeClassForm::is_pipeclass() const { return (PipeClassForm *)(this); } void PipeClassForm::dump() { output(stderr); } void PipeClassForm::output(FILE *fp) { // Write info to output files fprintf(fp,"PipeClassForm: #%03d", _num); if (_ident) fprintf(fp," \"%s\":", _ident); if (_has_fixed_latency) fprintf(fp," latency %d", _fixed_latency); if (_force_serialization) fprintf(fp, ", force serialization"); if (_may_have_no_code) fprintf(fp, ", may have no code"); fprintf(fp, ", %d instruction%s\n", InstructionCount(), InstructionCount() != 1 ? "s" : ""); } //==============================Peephole Optimization========================== int Peephole::_peephole_counter = 0; //------------------------------Peephole--------------------------------------- Peephole::Peephole() : _match(NULL), _constraint(NULL), _replace(NULL), _next(NULL) { _peephole_number = _peephole_counter++; } Peephole::~Peephole() { } // Append a peephole rule with the same root instruction void Peephole::append_peephole(Peephole *next_peephole) { if( _next == NULL ) { _next = next_peephole; } else { _next->append_peephole( next_peephole ); } } // Store the components of this peephole rule void Peephole::add_match(PeepMatch *match) { assert( _match == NULL, "fatal()" ); _match = match; } void Peephole::append_constraint(PeepConstraint *next_constraint) { if( _constraint == NULL ) { _constraint = next_constraint; } else { _constraint->append( next_constraint ); } } void Peephole::add_replace(PeepReplace *replace) { assert( _replace == NULL, "fatal()" ); _replace = replace; } // class Peephole accessor methods are in the declaration. void Peephole::dump() { output(stderr); } void Peephole::output(FILE *fp) { // Write info to output files fprintf(fp,"Peephole:\n"); if( _match != NULL ) _match->output(fp); if( _constraint != NULL ) _constraint->output(fp); if( _replace != NULL ) _replace->output(fp); // Output the next entry if( _next ) _next->output(fp); } //------------------------------PeepMatch-------------------------------------- PeepMatch::PeepMatch(char *rule) : _max_position(0), _rule(rule) { } PeepMatch::~PeepMatch() { } // Insert info into the match-rule void PeepMatch::add_instruction(int parent, int position, const char *name, int input) { if( position > _max_position ) _max_position = position; _parent.addName((char*) (intptr_t) parent); _position.addName((char*) (intptr_t) position); _instrs.addName(name); _input.addName((char*) (intptr_t) input); } // Access info about instructions in the peep-match rule int PeepMatch::max_position() { return _max_position; } const char *PeepMatch::instruction_name(int position) { return _instrs.name(position); } // Iterate through all info on matched instructions void PeepMatch::reset() { _parent.reset(); _position.reset(); _instrs.reset(); _input.reset(); } void PeepMatch::next_instruction(int &parent, int &position, const char* &name, int &input) { parent = (int) (intptr_t) _parent.iter(); position = (int) (intptr_t) _position.iter(); name = _instrs.iter(); input = (int) (intptr_t) _input.iter(); } // 'true' if current position in iteration is a placeholder, not matched. bool PeepMatch::is_placeholder() { return _instrs.current_is_signal(); } void PeepMatch::dump() { output(stderr); } void PeepMatch::output(FILE *fp) { // Write info to output files fprintf(fp,"PeepMatch:\n"); } //------------------------------PeepConstraint--------------------------------- PeepConstraint::PeepConstraint(int left_inst, char* left_op, char* relation, int right_inst, char* right_op) : _left_inst(left_inst), _left_op(left_op), _relation(relation), _right_inst(right_inst), _right_op(right_op), _next(NULL) {} PeepConstraint::~PeepConstraint() { } // Check if constraints use instruction at position bool PeepConstraint::constrains_instruction(int position) { // Check local instruction constraints if( _left_inst == position ) return true; if( _right_inst == position ) return true; // Check remaining constraints in list if( _next == NULL ) return false; else return _next->constrains_instruction(position); } // Add another constraint void PeepConstraint::append(PeepConstraint *next_constraint) { if( _next == NULL ) { _next = next_constraint; } else { _next->append( next_constraint ); } } // Access the next constraint in the list PeepConstraint *PeepConstraint::next() { return _next; } void PeepConstraint::dump() { output(stderr); } void PeepConstraint::output(FILE *fp) { // Write info to output files fprintf(fp,"PeepConstraint:\n"); } //------------------------------PeepReplace------------------------------------ PeepReplace::PeepReplace(char *rule) : _rule(rule) { } PeepReplace::~PeepReplace() { } // Add contents of peepreplace void PeepReplace::add_instruction(char *root) { _instruction.addName(root); _operand_inst_num.add_signal(); _operand_op_name.add_signal(); } void PeepReplace::add_operand( int inst_num, char *inst_operand ) { _instruction.add_signal(); _operand_inst_num.addName((char*) (intptr_t) inst_num); _operand_op_name.addName(inst_operand); } // Access contents of peepreplace void PeepReplace::reset() { _instruction.reset(); _operand_inst_num.reset(); _operand_op_name.reset(); } void PeepReplace::next_instruction(const char* &inst){ inst = _instruction.iter(); int inst_num = (int) (intptr_t) _operand_inst_num.iter(); const char* inst_operand = _operand_op_name.iter(); } void PeepReplace::next_operand(int &inst_num, const char* &inst_operand) { const char* inst = _instruction.iter(); inst_num = (int) (intptr_t) _operand_inst_num.iter(); inst_operand = _operand_op_name.iter(); } void PeepReplace::dump() { output(stderr); } void PeepReplace::output(FILE *fp) { // Write info to output files fprintf(fp,"PeepReplace:\n"); }