ssssssss3

void ArchDesc::build_map(OutputMap &map) {
  FILE         *fp_hpp = map.decl_file();
  FILE         *fp_cpp = map.def_file();
  int           idx    = 0;
  OperandForm  *op;
  OpClassForm  *opc;
  InstructForm *inst;
  map.declaration();
  fprintf(fp_cpp,"\n");
  map.definition();
  map.record_position(OutputMap::BEGIN_OPERANDS, idx );
  _operands.reset();
  for(; (op = (OperandForm*)_operands.iter()) != NULL; ) {
    if ( op->ideal_only() )  continue;
    fprintf(fp_cpp, "  /* %4d */", idx); map.map(*op); fprintf(fp_cpp, ",\n");
    ++idx;
  };
  fprintf(fp_cpp, "  // last operand\n");
  map.record_position(OutputMap::BEGIN_OPCLASSES, idx );
  _opclass.reset();
  for(; (opc = (OpClassForm*)_opclass.iter()) != NULL; ) {
    fprintf(fp_cpp, "  /* %4d */", idx); map.map(*opc); fprintf(fp_cpp, ",\n");
    ++idx;
  };
  fprintf(fp_cpp, "  // last operand class\n");
  map.record_position(OutputMap::BEGIN_INTERNALS, idx );
  _internalOpNames.reset();
  char *name = NULL;
  for(; (name = (char *)_internalOpNames.iter()) != NULL; ) {
    fprintf(fp_cpp, "  /* %4d */", idx); map.map(name); fprintf(fp_cpp, ",\n");
    ++idx;
  };
  fprintf(fp_cpp, "  // last internally defined operand\n");
  if( map.do_instructions() ) {
    map.record_position(OutputMap::BEGIN_INSTRUCTIONS, idx );
    map.record_position(OutputMap::BEGIN_INST_CHAIN_RULES, idx );
    {
      _instructions.reset();
      for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) {
        if ( inst->ideal_only() )  continue;
        if ( ! inst->is_simple_chain_rule(_globalNames) ) continue;
        if ( inst->rematerialize(_globalNames, get_registers()) ) continue;
        fprintf(fp_cpp, "  /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
        ++idx;
      };
      map.record_position(OutputMap::BEGIN_REMATERIALIZE, idx );
      _instructions.reset();
      for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) {
        if ( inst->ideal_only() )  continue;
        if ( ! inst->is_simple_chain_rule(_globalNames) ) continue;
        if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue;
        fprintf(fp_cpp, "  /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
        ++idx;
      };
      map.record_position(OutputMap::END_INST_CHAIN_RULES, idx );
    }
    {
      _instructions.reset();
      for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) {
        if ( inst->ideal_only() )  continue;
        if ( inst->is_simple_chain_rule(_globalNames) ) continue;
        if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue;
        fprintf(fp_cpp, "  /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
        ++idx;
      };
      map.record_position(OutputMap::END_REMATERIALIZE, idx );
      _instructions.reset();
      for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) {
        if ( inst->ideal_only() )  continue;
        if ( inst->is_simple_chain_rule(_globalNames) ) continue;
        if ( inst->rematerialize(_globalNames, get_registers()) ) continue;
        fprintf(fp_cpp, "  /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
        ++idx;
      };
    }
    fprintf(fp_cpp, "  // last instruction\n");
    map.record_position(OutputMap::END_INSTRUCTIONS, idx );
  }
  map.closing();
};
char reg_save_policy(const char *calling_convention) {
  char callconv;
  if      (!strcmp(calling_convention, "NS"))  callconv = 'N';
  else if (!strcmp(calling_convention, "SOE")) callconv = 'E';
  else if (!strcmp(calling_convention, "SOC")) callconv = 'C';
  else if (!strcmp(calling_convention, "AS"))  callconv = 'A';
  else                                         callconv = 'Z';
  return callconv;
}
void ArchDesc::generate_needs_clone_jvms(FILE *fp_cpp) {
  fprintf(fp_cpp, "bool Compile::needs_clone_jvms() { return %s; }\n\n",
          _needs_clone_jvms ? "true" : "false");
}
void ArchDesc::generate_adlc_verification(FILE *fp_cpp) {
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp, "#ifndef PRODUCT\n");
  fprintf(fp_cpp, "void Compile::adlc_verification() {\n");
  globalDefs().print_asserts(fp_cpp);
  fprintf(fp_cpp, "}\n");
  fprintf(fp_cpp, "#endif\n");
  fprintf(fp_cpp, "\n");
}
void ArchDesc::addSourceBlocks(FILE *fp_cpp) {
  if (_source.count() > 0)
    _source.output(fp_cpp);
  generate_adlc_verification(fp_cpp);
}
void ArchDesc::addHeaderBlocks(FILE *fp_hpp) {
  if (_header.count() > 0)
    _header.output(fp_hpp);
}
void ArchDesc::addPreHeaderBlocks(FILE *fp_hpp) {
  globalDefs().print_defines(fp_hpp);
  if (_pre_header.count() > 0)
    _pre_header.output(fp_hpp);
}
void ArchDesc::buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp) {
  RegDef       *rdef;
  RegDef       *next;
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "extern const char  register_save_policy[];\n");
  fprintf(fp_hpp, "extern const char  c_reg_save_policy[];\n");
  fprintf(fp_hpp, "extern const int   register_save_type[];\n");
  fprintf(fp_hpp, "\n");
  fprintf(fp_cpp, "// Map from machine-independent register number to register_save_policy\n");
  fprintf(fp_cpp, "const        char register_save_policy[] = {\n");
  _register->reset_RegDefs();
  for( rdef = _register->iter_RegDefs(); rdef != NULL; rdef = next ) {
    next              = _register->iter_RegDefs();
    char policy       = reg_save_policy(rdef->_callconv);
    const char *comma = (next != NULL) ? "," : " // no trailing comma";
    fprintf(fp_cpp, "  '%c'%s // %s\n", policy, comma, rdef->_regname);
  }
  fprintf(fp_cpp, "};\n\n");
  fprintf(fp_cpp, "// Map from machine-independent register number to c_reg_save_policy\n");
  fprintf(fp_cpp, "const        char c_reg_save_policy[] = {\n");
  _register->reset_RegDefs();
  for( rdef = _register->iter_RegDefs(); rdef != NULL; rdef = next ) {
    next        = _register->iter_RegDefs();
    char policy = reg_save_policy(rdef->_c_conv);
    const char *comma = (next != NULL) ? "," : " // no trailing comma";
    fprintf(fp_cpp, "  '%c'%s // %s\n", policy, comma, rdef->_regname);
  }
  fprintf(fp_cpp, "};\n\n");
  fprintf(fp_cpp, "// Map from machine-independent register number to register_save_type\n");
  fprintf(fp_cpp, "const        int register_save_type[] = {\n");
  _register->reset_RegDefs();
  for( rdef = _register->iter_RegDefs(); rdef != NULL; rdef = next ) {
    next = _register->iter_RegDefs();
    const char *comma = (next != NULL) ? "," : " // no trailing comma";
    fprintf(fp_cpp, "  %s%s\n", rdef->_idealtype, comma);
  }
  fprintf(fp_cpp, "};\n\n");
  OutputReduceOp output_reduce_op(fp_hpp, fp_cpp, _globalNames, *this);
  build_map(output_reduce_op);
  OutputLeftOp output_left_op(fp_hpp, fp_cpp, _globalNames, *this);
  build_map(output_left_op);
  OutputRightOp output_right_op(fp_hpp, fp_cpp, _globalNames, *this);
  build_map(output_right_op);
  OutputRuleName output_rule_name(fp_hpp, fp_cpp, _globalNames, *this);
  build_map(output_rule_name);
  OutputSwallowed output_swallowed(fp_hpp, fp_cpp, _globalNames, *this);
  build_map(output_swallowed);
}
static void path_to_constant(FILE *fp, FormDict &globals,
                             MatchNode *mnode, uint idx) {
  if ( ! mnode) return;
  unsigned    position = 0;
  const char *result   = NULL;
  const char *name     = NULL;
  const char *optype   = NULL;
  if ( (mnode->_lChild == NULL) && (mnode->_rChild == NULL)
       && mnode->base_operand(position, globals, result, name, optype) ) {
    if (         strcmp(optype,"ConI") == 0 ) {
      fprintf(fp, "_leaf->get_int()");
    } else if ( (strcmp(optype,"ConP") == 0) ) {
      fprintf(fp, "_leaf->bottom_type()->is_ptr()");
    } else if ( (strcmp(optype,"ConN") == 0) ) {
      fprintf(fp, "_leaf->bottom_type()->is_narrowoop()");
    } else if ( (strcmp(optype,"ConNKlass") == 0) ) {
      fprintf(fp, "_leaf->bottom_type()->is_narrowklass()");
    } else if ( (strcmp(optype,"ConF") == 0) ) {
      fprintf(fp, "_leaf->getf()");
    } else if ( (strcmp(optype,"ConD") == 0) ) {
      fprintf(fp, "_leaf->getd()");
    } else if ( (strcmp(optype,"ConL") == 0) ) {
      fprintf(fp, "_leaf->get_long()");
    } else if ( (strcmp(optype,"Con")==0) ) {
      fprintf(fp, "_leaf->get_int()");
      assert( false, "Unsupported constant type, pointer or indefinite");
    } else if ( (strcmp(optype,"Bool") == 0) ) {
      fprintf(fp, "_leaf->as_Bool()->_test._test");
    } else {
      assert( false, "Unsupported constant type");
    }
    return;
  }
  uint lConsts = (mnode->_lChild) ? (mnode->_lChild->num_consts(globals) ) : 0;
  uint rConsts = (mnode->_rChild) ? (mnode->_rChild->num_consts(globals) ) : 0;
  if ( (mnode->_lChild) && (lConsts > idx) ) {
    fprintf(fp, "_kids[0]->");
    path_to_constant(fp, globals, mnode->_lChild, idx);
    return;
  }
  if ( (mnode->_rChild) && (rConsts > (idx - lConsts) ) ) {
    idx = idx - lConsts;
    fprintf(fp, "_kids[1]->");
    path_to_constant(fp, globals, mnode->_rChild, idx);
    return;
  }
  assert( false, "ShouldNotReachHere()");
}
static void genMachOperCase(FILE *fp, FormDict &globalNames, ArchDesc &AD,
                            OperandForm &op) {
  const char *opName         = op._ident;
  const char *opEnumName     = AD.machOperEnum(opName);
  uint        num_consts     = op.num_consts(globalNames);
  fprintf(fp, "  case %s:", opEnumName);
  fprintf(fp, "\n    return new (C) %sOper(", opName);
  if ( (num_consts > 0) ) {
    uint i = 0;
    path_to_constant(fp, globalNames, op._matrule, i);
    for ( i = 1; i < num_consts; ++i ) {
      fprintf(fp, ", ");
      path_to_constant(fp, globalNames, op._matrule, i);
    }
  }
  fprintf(fp, " );\n");
}
void ArchDesc::buildMachOperGenerator(FILE *fp_cpp) {
  int idx = 0;
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp,
          "//------------------------- MachOper Generator ---------------\n");
  fprintf(fp_cpp,
          "// A switch statement on the dense-packed user-defined type system\n"
          "// that invokes 'new' on the corresponding class constructor.\n");
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp, "MachOper *State::MachOperGenerator");
  fprintf(fp_cpp, "(int opcode, Compile* C)");
  fprintf(fp_cpp, "{\n");
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp, "  switch(opcode) {\n");
  _operands.reset();
  int  opIndex = 0;
  OperandForm *op;
  for( ; (op =  (OperandForm*)_operands.iter()) != NULL; ) {
    if ( op->ideal_only() )  continue;
    genMachOperCase(fp_cpp, _globalNames, *this, *op);
  };
  _internalOpNames.reset();
  const char *iopn;
  for( ; (iopn =  _internalOpNames.iter()) != NULL; ) {
    const char *opEnumName = machOperEnum(iopn);
    fprintf(fp_cpp, "  case %s:", opEnumName);
    fprintf(fp_cpp, "    return NULL;\n");
  };
  fprintf(fp_cpp, "  \n");
  fprintf(fp_cpp, "  default:\n");
  fprintf(fp_cpp, "    fprintf(stderr, \"Default MachOper Generator invoked for: \\n\");\n");
  fprintf(fp_cpp, "    fprintf(stderr, \"   opcode = %cd\\n\", opcode);\n", '%');
  fprintf(fp_cpp, "    break;\n");
  fprintf(fp_cpp, "  }\n");
  fprintf(fp_cpp, "  return NULL;\n");
  fprintf(fp_cpp, "};\n");
}
void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *indent) {
  const char *opType  = NULL;
  const char *opClass = inst->_ident;
  fprintf(fp_cpp, "%s %sNode *node = new (C) %sNode();\n",indent, opClass,opClass);
  if ( (inst->num_post_match_opnds() != 0) ) {
    bool           dont_care = false;
    ComponentList &comp_list = inst->_components;
    Component     *comp      = NULL;
    comp_list.reset();
    if ( comp_list.match_iter() != NULL )    dont_care = true;
    comp_list.reset();
    while ( comp = comp_list.post_match_iter() ) {
      if ( dont_care && (! comp->isa(Component::USE)) ) {
        continue;
      }
      dont_care = true;
      ComponentList clist = inst->_components;
      int         index  = clist.operand_position(comp->_name, comp->_usedef, inst);
      const char *opcode = machOperEnum(comp->_type);
      fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index);
      fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode);
      }
  }
  else if ( inst->is_chain_of_constant(_globalNames, opType) ) {
    fprintf(fp_cpp, "%s node->_opnd_array[%d] = ", indent,
            inst->oper_input_base(_globalNames));
    const char *opName = inst->_matrule->_rChild->_opType;
    fprintf(fp_cpp, "new (C) %sOper(", opName);
    OperandForm *op = (_globalNames[opName])->is_operand();
    uint num_consts = op->num_consts(_globalNames);
    if ( (num_consts > 0) ) {
      uint i = 0;
      path_to_constant(fp_cpp, _globalNames, op->_matrule, i);
      for ( i = 1; i < num_consts; ++i ) {
        fprintf(fp_cpp, ", ");
        path_to_constant(fp_cpp, _globalNames, op->_matrule, i);
      }
    }
    fprintf(fp_cpp, " );\n");
  }
  if (inst->captures_bottom_type(_globalNames)) {
    if (strncmp("MachCall", inst->mach_base_class(_globalNames), strlen("MachCall"))) {
      fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent);
    }
  }
  if( inst->is_ideal_if() ) {
    fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent);
    fprintf(fp_cpp, "%s node->_fcnt = _leaf->as_If()->_fcnt;\n", indent);
  }
  if( inst->is_ideal_fastlock() ) {
    fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent);
    fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent);
    fprintf(fp_cpp, "%s node->_stack_rtm_counters = _leaf->as_FastLock()->stack_rtm_counters();\n", indent);
  }
}
void InstructForm::declare_cisc_version(ArchDesc &AD, FILE *fp_hpp) {
  if( AD.can_cisc_spill() ) {
    InstructForm *inst_cisc = cisc_spill_alternate();
    if (inst_cisc != NULL) {
      fprintf(fp_hpp, "  virtual int            cisc_operand() const { return %d; }\n", cisc_spill_operand());
      fprintf(fp_hpp, "  virtual MachNode      *cisc_version(int offset, Compile* C);\n");
      fprintf(fp_hpp, "  virtual void           use_cisc_RegMask();\n");
      fprintf(fp_hpp, "  virtual const RegMask *cisc_RegMask() const { return _cisc_RegMask; }\n");
    }
  }
}
bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) {
  InstructForm *inst_cisc = this->cisc_spill_alternate();
  if( AD.can_cisc_spill() && (inst_cisc != NULL) ) {
    const char   *name      = inst_cisc->_ident;
    assert( inst_cisc->num_opnds() == this->num_opnds(), "Must have same number of operands");
    OperandForm *cisc_oper = AD.cisc_spill_operand();
    assert( cisc_oper != NULL, "insanity check");
    const char *cisc_oper_name  = cisc_oper->_ident;
    assert( cisc_oper_name != NULL, "insanity check");
    fprintf(fp_cpp, "\n");
    fprintf(fp_cpp, "void %sNode::use_cisc_RegMask() {\n", this->_ident);
    const char *reg_mask_name = cisc_reg_mask_name();
    fprintf(fp_cpp, "  _cisc_RegMask = &STACK_OR_%s;\n", reg_mask_name);
    fprintf(fp_cpp, "}\n");
    fprintf(fp_cpp, "\n");
    fprintf(fp_cpp, "// Build CISC version of this instruction\n");
    fprintf(fp_cpp, "MachNode *%sNode::cisc_version( int offset, Compile* C ) {\n", this->_ident);
    fprintf(fp_cpp, "  %sNode *node = new (C) %sNode();\n", name, name);
    if ( this->captures_bottom_type(AD.globalNames()) ) {
      fprintf(fp_cpp, "  node->_bottom_type = bottom_type();\n");
    }
    uint cur_num_opnds = num_opnds();
    if (cur_num_opnds > 1 && cur_num_opnds != num_unique_opnds()) {
      fprintf(fp_cpp,"  node->_num_opnds = %d;\n", num_unique_opnds());
    }
    fprintf(fp_cpp, "\n");
    fprintf(fp_cpp, "  // Copy _idx, inputs and operands to new node\n");
    fprintf(fp_cpp, "  fill_new_machnode(node, C);\n");
    fprintf(fp_cpp, "  // Construct operand to access [stack_pointer + offset]\n");
    fprintf(fp_cpp, "  node->set_opnd_array(cisc_operand(), new (C) %sOper(offset));\n", cisc_oper_name);
    fprintf(fp_cpp, "\n");
    fprintf(fp_cpp, "  return node;\n");
    fprintf(fp_cpp, "}\n");
    fprintf(fp_cpp, "\n");
    return true;
  }
  return false;
}
void InstructForm::declare_short_branch_methods(FILE *fp_hpp) {
  if (has_short_branch_form()) {
    fprintf(fp_hpp, "  virtual MachNode      *short_branch_version(Compile* C);\n");
  }
}
bool InstructForm::define_short_branch_methods(ArchDesc &AD, FILE *fp_cpp) {
  if (has_short_branch_form()) {
    InstructForm *short_branch = short_branch_form();
    const char   *name         = short_branch->_ident;
    fprintf(fp_cpp, "// Build short branch version of this instruction\n");
    fprintf(fp_cpp, "MachNode *%sNode::short_branch_version(Compile* C) {\n", this->_ident);
    fprintf(fp_cpp, "  %sNode *node = new (C) %sNode();\n", name, name);
    if( is_ideal_if() ) {
      fprintf(fp_cpp, "  node->_prob = _prob;\n");
      fprintf(fp_cpp, "  node->_fcnt = _fcnt;\n");
    }
    if ( this->captures_bottom_type(AD.globalNames()) ) {
      fprintf(fp_cpp, "  node->_bottom_type = bottom_type();\n");
    }
    fprintf(fp_cpp, "\n");
    fprintf(fp_cpp, "  // Copy _idx, inputs and operands to new node\n");
    fprintf(fp_cpp, "  fill_new_machnode(node, C);\n");
    fprintf(fp_cpp, "  return node;\n");
    fprintf(fp_cpp, "}\n");
    fprintf(fp_cpp,"\n");
    return true;
  }
  return false;
}
void ArchDesc::buildMachNodeGenerator(FILE *fp_cpp) {
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp,
          "//------------------------- MachNode Generator ---------------\n");
  fprintf(fp_cpp,
          "// A switch statement on the dense-packed user-defined type system\n"
          "// that invokes 'new' on the corresponding class constructor.\n");
  fprintf(fp_cpp, "\n");
  fprintf(fp_cpp, "MachNode *State::MachNodeGenerator");
  fprintf(fp_cpp, "(int opcode, Compile* C)");
  fprintf(fp_cpp, "{\n");
  fprintf(fp_cpp, "  switch(opcode) {\n");
  _instructions.reset();
  int  opIndex = operandFormCount();
  InstructForm *inst;
  for( ; (inst = (InstructForm*)_instructions.iter()) != NULL; ) {
    if ( inst->_matrule == NULL ) continue;
    int         opcode  = opIndex++;
    const char *opClass = inst->_ident;
    char       *opType  = NULL;
    fprintf(fp_cpp, "  case %s_rule:", opClass);
    fprintf(fp_cpp, " {\n");
    buildMachNode(fp_cpp, inst, "     ");
    fprintf(fp_cpp, "      return node;\n");
    fprintf(fp_cpp, "    }\n");
  }
  fprintf(fp_cpp, "  \n");
  fprintf(fp_cpp, "  default:\n");
  fprintf(fp_cpp, "    fprintf(stderr, \"Default MachNode Generator invoked for: \\n\");\n");
  fprintf(fp_cpp, "    fprintf(stderr, \"   opcode = %cd\\n\", opcode);\n", '%');
  fprintf(fp_cpp, "    break;\n");
  fprintf(fp_cpp, "  };\n");
  fprintf(fp_cpp, "  return NULL;\n");
  fprintf(fp_cpp, "}\n");
}
void ArchDesc::buildInstructMatchCheck(FILE *fp_cpp) const {
  fprintf(fp_cpp, "\n\n");
  fprintf(fp_cpp, "const bool Matcher::has_match_rule(int opcode) {\n");
  fprintf(fp_cpp, "  assert(_last_machine_leaf < opcode && opcode < _last_opcode, \"opcode in range\");\n");
  fprintf(fp_cpp, "  return _hasMatchRule[opcode];\n");
  fprintf(fp_cpp, "}\n\n");
  fprintf(fp_cpp, "const bool Matcher::_hasMatchRule[_last_opcode] = {\n");
  int i;
  for (i = 0; i < _last_opcode - 1; i++) {
    fprintf(fp_cpp, "    %-5s,  // %s\n",
            _has_match_rule[i] ? "true" : "false",
            NodeClassNames[i]);
  }
  fprintf(fp_cpp, "    %-5s   // %s\n",
          _has_match_rule[i] ? "true" : "false",
          NodeClassNames[i]);
  fprintf(fp_cpp, "};\n");
}
void ArchDesc::buildFrameMethods(FILE *fp_cpp) {
  fprintf(fp_cpp,"\n\n");
  fprintf(fp_cpp,"bool Matcher::stack_direction() const { return %s; }\n\n",
          _frame->_direction ? "true" : "false");
  fprintf(fp_cpp,"int Compile::sync_stack_slots() const { return %s; }\n\n",
          _frame->_sync_stack_slots);
  fprintf(fp_cpp,"uint Matcher::stack_alignment_in_bytes() { return %s; }\n\n",
          _frame->_alignment);
  fprintf(fp_cpp,"OptoReg::Name Matcher::return_addr() const {");
  if (_frame->_return_addr_loc) {
    fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n",
            _frame->_return_addr);
  }
  else {
    fprintf(fp_cpp," return OptoReg::stack2reg(%s); }\n\n",
            _frame->_return_addr);
  }
  fprintf(fp_cpp,"uint Compile::in_preserve_stack_slots() ");
  fprintf(fp_cpp,"{ return %s; }\n\n", _frame->_in_preserve_slots);
  fprintf(fp_cpp,"uint Compile::out_preserve_stack_slots() ");
  fprintf(fp_cpp,"{ return SharedRuntime::out_preserve_stack_slots(); }\n\n");
  fprintf(fp_cpp,"uint Compile::varargs_C_out_slots_killed() const ");
  fprintf(fp_cpp,"{ return %s; }\n\n", _frame->_varargs_C_out_slots_killed);
  fprintf(fp_cpp,"void Matcher::calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length, bool is_outgoing) {\n");
  fprintf(fp_cpp,"%s\n", _frame->_calling_convention);
  fprintf(fp_cpp,"}\n\n");
  fprintf(fp_cpp,"void Matcher::c_calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length) {\n");
  fprintf(fp_cpp,"%s\n", _frame->_c_calling_convention);
  fprintf(fp_cpp,"}\n\n");
  fprintf(fp_cpp,"OptoRegPair Matcher::return_value(uint ideal_reg, bool is_outgoing) {\n");
  fprintf(fp_cpp,"%s\n", _frame->_return_value);
  fprintf(fp_cpp,"}\n\n");
  fprintf(fp_cpp,"OptoRegPair Matcher::c_return_value(uint ideal_reg, bool is_outgoing) {\n");
  fprintf(fp_cpp,"%s\n", _frame->_c_return_value);
  fprintf(fp_cpp,"}\n\n");
  fprintf(fp_cpp,"OptoReg::Name Matcher::inline_cache_reg() {");
  fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n",
          _frame->_inline_cache_reg);
  fprintf(fp_cpp,"int Matcher::inline_cache_reg_encode() {");
  fprintf(fp_cpp," return _regEncode[inline_cache_reg()]; }\n\n");
  fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_method_oop_reg() {");
  fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n",
          _frame->_interpreter_method_oop_reg);
  fprintf(fp_cpp,"int Matcher::interpreter_method_oop_reg_encode() {");
  fprintf(fp_cpp," return _regEncode[interpreter_method_oop_reg()]; }\n\n");
  fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_frame_pointer_reg() {");
  if (_frame->_interpreter_frame_pointer_reg == NULL)
    fprintf(fp_cpp," return OptoReg::Bad; }\n\n");
  else
    fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n",
            _frame->_interpreter_frame_pointer_reg);
     Java and native code; makes my head hurt to think about it.
  fprintf(fp_cpp,"OptoReg::Name Matcher::frame_pointer() const {");
  fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n",
          _frame->_frame_pointer);
  fprintf(fp_cpp,"OptoReg::Name Matcher::c_frame_pointer() const {");
  fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n",
          _frame->_frame_pointer);
  fprintf(fp_cpp, "// Number of callee-save + always-save registers\n");
  fprintf(fp_cpp, "int  Matcher::number_of_saved_registers() {\n");
  RegDef *rdef;
  int nof_saved_registers = 0;
  _register->reset_RegDefs();
  while( (rdef = _register->iter_RegDefs()) != NULL ) {
    if( !strcmp(rdef->_callconv, "SOE") ||  !strcmp(rdef->_callconv, "AS") )
      ++nof_saved_registers;
  }
  fprintf(fp_cpp, "  return %d;\n", nof_saved_registers);
  fprintf(fp_cpp, "};\n\n");
}
static int PrintAdlcCisc = 0;
void ArchDesc::identify_cisc_spill_instructions() {
  if (_frame == NULL)
    return;
  if( _frame->_cisc_spilling_operand_name != NULL ) {
    const Form *form = _globalNames[_frame->_cisc_spilling_operand_name];
    OperandForm *oper = form ? form->is_operand() : NULL;
    if( oper != NULL ) {
      if ( oper->_matrule != NULL )  {
        MatchRule &mrule = *oper->_matrule;
        if( strcmp(mrule._opType,"AddP") == 0 ) {
          MatchNode *left = mrule._lChild;
          MatchNode *right= mrule._rChild;
          if( left != NULL && right != NULL ) {
            const Form *left_op  = _globalNames[left->_opType]->is_operand();
            const Form *right_op = _globalNames[right->_opType]->is_operand();
            if(  (left_op != NULL && right_op != NULL)
              && (left_op->interface_type(_globalNames) == Form::register_interface)
              && (right_op->interface_type(_globalNames) == Form::constant_interface) ) {
              set_cisc_spill_operand( oper );
              if( _cisc_spill_debug ) {
                fprintf(stderr, "\n\nVerified CISC-spill operand %s\n\n", oper->_ident);
             }
            }
          }
        }
      }
    }
  }
  if( cisc_spill_operand() != NULL ) {
    _instructions.reset();
    InstructForm *instr;
    for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) {
      if ( instr->_matrule == NULL )  continue;
      MatchRule &mrule = *instr->_matrule;
      Predicate *pred  =  instr->build_predicate();
      const char *rootOp = instr->_ident;
      mrule._machType    = rootOp;
      const char *result = instr->reduce_result();
      if( PrintAdlcCisc ) fprintf(stderr, "  new instruction %s \n", instr->_ident ? instr->_ident : " ");
      bool  found_cisc_alternate = false;
      _instructions.reset2();
      InstructForm *instr2;
      for( ; !found_cisc_alternate && (instr2 = (InstructForm*)_instructions.iter2()) != NULL; ) {
        if( PrintAdlcCisc ) fprintf(stderr, "  instr2 == %s \n", instr2->_ident ? instr2->_ident : " ");
        if ( instr2->_matrule != NULL
            && (instr != instr2 )                // Skip self
            && (instr2->reduce_result() != NULL) // want same result
            && (strcmp(result, instr2->reduce_result()) == 0)) {
          MatchRule &mrule2 = *instr2->_matrule;
          Predicate *pred2  =  instr2->build_predicate();
          found_cisc_alternate = instr->cisc_spills_to(*this, instr2);
        }
      }
    }
  }
}
void ArchDesc::build_cisc_spill_instructions(FILE *fp_hpp, FILE *fp_cpp) {
  fprintf(fp_cpp, "//  The following instructions can cisc-spill\n");
  _instructions.reset();
  InstructForm *inst = NULL;
  for(; (inst = (InstructForm*)_instructions.iter()) != NULL; ) {
    if ( inst->ideal_only() )  continue;
    const char *inst_name = inst->_ident;
    int   operand   = inst->cisc_spill_operand();
    if( operand != AdlcVMDeps::Not_cisc_spillable ) {
      InstructForm *inst2 = inst->cisc_spill_alternate();
      fprintf(fp_cpp, "//  %s can cisc-spill operand %d to %s\n", inst->_ident, operand, inst2->_ident);
    }
  }
  fprintf(fp_cpp, "\n\n");
}
void ArchDesc::identify_short_branches() {
  _instructions.reset();
  InstructForm *instr;
  while( (instr = (InstructForm*)_instructions.iter()) != NULL ) {
    if (instr->_matrule != NULL &&
        instr->is_short_branch()) {
      _instructions.reset2();
      InstructForm *instr2;
      while( (instr2 = (InstructForm*)_instructions.iter2()) != NULL ) {
        instr2->check_branch_variant(*this, instr);
      }
    }
  }
}
void ArchDesc::identify_unique_operands() {
  _instructions.reset();
  InstructForm *instr;
  while( (instr = (InstructForm*)_instructions.iter()) != NULL ) {
    if (!instr->ideal_only()) {
      instr->set_unique_opnds();
    }
  }
}
C:\hotspot-69087d08d473\src\share\vm/adlc/output_h.cpp
#include "adlc.hpp"
#if defined(PPC64)
#define commentSeperator "\t//"
#else
#define commentSeperator "!"
#endif
static void defineRegCount(FILE *fp, RegisterForm *registers) {
  if (registers) {
    int regCount =  AdlcVMDeps::Physical + registers->_rdefs.count();
    fprintf(fp,"\n");
    fprintf(fp,"// the number of reserved registers + machine registers.\n");
    fprintf(fp,"#define REG_COUNT    %d\n", regCount);
  }
}
void ArchDesc::buildMachRegisterNumbers(FILE *fp_hpp) {
  if (_register) {
    RegDef *reg_def = NULL;
    defineRegCount(fp_hpp, _register);
    int    saved_on_entry = 0;
    int  c_saved_on_entry = 0;
    _register->reset_RegDefs();
    while( (reg_def = _register->iter_RegDefs()) != NULL ) {
      if( strcmp(reg_def->_callconv,"SOE") == 0 ||
          strcmp(reg_def->_callconv,"AS")  == 0 )  ++saved_on_entry;
      if( strcmp(reg_def->_c_conv,"SOE") == 0 ||
          strcmp(reg_def->_c_conv,"AS")  == 0 )  ++c_saved_on_entry;
    }
    fprintf(fp_hpp, "\n");
    fprintf(fp_hpp, "// the number of save_on_entry + always_saved registers.\n");
    fprintf(fp_hpp, "#define MAX_SAVED_ON_ENTRY_REG_COUNT    %d\n",   max(saved_on_entry,c_saved_on_entry));
    fprintf(fp_hpp, "#define     SAVED_ON_ENTRY_REG_COUNT    %d\n",   saved_on_entry);
    fprintf(fp_hpp, "#define   C_SAVED_ON_ENTRY_REG_COUNT    %d\n", c_saved_on_entry);
    fprintf(fp_hpp, "\n");
    fprintf(fp_hpp, "// Enumerate machine register numbers starting after reserved regs.\n");
    fprintf(fp_hpp, "// in the order of occurrence in the register block.\n");
    fprintf(fp_hpp, "enum MachRegisterNumbers {\n");
    _register->reset_RegDefs();
    int i = 0;
    while( (reg_def = _register->iter_RegDefs()) != NULL ) {
      fprintf(fp_hpp,"  %s_num,", reg_def->_regname);
      for (int j = 0; j < 20-(int)strlen(reg_def->_regname); j++) fprintf(fp_hpp, " ");
      fprintf(fp_hpp," // enum %3d, regnum %3d, reg encode %3s\n",
              i++,
              reg_def->register_num(),
              reg_def->register_encode());
    }
    fprintf(fp_hpp, "  _last_Mach_Reg            // %d\n", i);
    fprintf(fp_hpp, "};\n");
  }
  fprintf(fp_hpp, "\n// Size of register-mask in ints\n");
  fprintf(fp_hpp, "#define RM_SIZE %d\n",RegisterForm::RegMask_Size());
  fprintf(fp_hpp, "// Unroll factor for loops over the data in a RegMask\n");
  fprintf(fp_hpp, "#define FORALL_BODY ");
  int len = RegisterForm::RegMask_Size();
  for( int i = 0; i < len; i++ )
    fprintf(fp_hpp, "BODY(%d) ",i);
  fprintf(fp_hpp, "\n\n");
  fprintf(fp_hpp,"class RegMask;\n");
}

void ArchDesc::buildMachRegisterEncodes(FILE *fp_hpp) {
  if (_register) {
    RegDef *reg_def = NULL;
    RegDef *reg_def_next = NULL;
    fprintf(fp_hpp, "\n");
    fprintf(fp_hpp, "// Enumerate machine registers starting after reserved regs.\n");
    fprintf(fp_hpp, "// in the order of occurrence in the alloc_class(es).\n");
    fprintf(fp_hpp, "enum MachRegisterEncodes {\n");
    size_t maxlen = 0;
    _register->reset_RegDefs();
    reg_def = _register->iter_RegDefs();
    while (reg_def != NULL) {
      size_t len = strlen(reg_def->_regname);
      if (len > maxlen) maxlen = len;
      reg_def = _register->iter_RegDefs();
    }
    _register->reset_RegDefs();
    reg_def_next = _register->iter_RegDefs();
    while( (reg_def = reg_def_next) != NULL ) {
      reg_def_next = _register->iter_RegDefs();
      fprintf(fp_hpp,"  %s_enc", reg_def->_regname);
      for (size_t i = strlen(reg_def->_regname); i < maxlen; i++) fprintf(fp_hpp, " ");
      fprintf(fp_hpp," = %3s%s\n", reg_def->register_encode(), reg_def_next == NULL? "" : "," );
    }
    fprintf(fp_hpp, "};\n");
  } // Done with register form
}
static void declareRegNames(FILE *fp, RegisterForm *registers) {
  if (registers) {
  }
}
void ArchDesc::declareRegSizes(FILE *fp) {
}
static void declareRegEncodes(FILE *fp, RegisterForm *registers) {
  if (registers) {
  }
}
static void out_RegMask(FILE *fp) {
  fprintf(fp,"  virtual const RegMask &out_RegMask() const;\n");
}
static void in_RegMask(FILE *fp) {
  fprintf(fp,"  virtual const RegMask *in_RegMask(int index) const;\n");
}
static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper) {
  int i = 0;
  Component *comp;
  if (oper->num_consts(globals) == 0) return;
  oper->_components.reset();
  if ((comp = oper->_components.iter()) == NULL) {
    assert(oper->num_consts(globals) == 1, "Bad component list detected.\n");
    const char *type = oper->ideal_type(globals);
    if (!strcmp(type, "ConI")) {
      if (i > 0) fprintf(fp,", ");
      fprintf(fp,"  int32          _c%d;\n", i);
    }
    else if (!strcmp(type, "ConP")) {
      if (i > 0) fprintf(fp,", ");
      fprintf(fp,"  const TypePtr *_c%d;\n", i);
    }
    else if (!strcmp(type, "ConN")) {
      if (i > 0) fprintf(fp,", ");
      fprintf(fp,"  const TypeNarrowOop *_c%d;\n", i);
    }
    else if (!strcmp(type, "ConNKlass")) {
      if (i > 0) fprintf(fp,", ");
      fprintf(fp,"  const TypeNarrowKlass *_c%d;\n", i);
    }
    else if (!strcmp(type, "ConL")) {
      if (i > 0) fprintf(fp,", ");
      fprintf(fp,"  jlong          _c%d;\n", i);
    }
    else if (!strcmp(type, "ConF")) {
      if (i > 0) fprintf(fp,", ");
      fprintf(fp,"  jfloat         _c%d;\n", i);
    }
    else if (!strcmp(type, "ConD")) {
      if (i > 0) fprintf(fp,", ");
      fprintf(fp,"  jdouble        _c%d;\n", i);
    }
    else if (!strcmp(type, "Bool")) {
      fprintf(fp,"private:\n");
      fprintf(fp,"  BoolTest::mask _c%d;\n", i);
      fprintf(fp,"public:\n");
    }
    else {
      assert(0, "Non-constant operand lacks component list.");
    }
  } // end if NULL
  else {
    oper->_components.reset();
    while ((comp = oper->_components.iter()) != NULL) {
      if (!strcmp(comp->base_type(globals), "ConI")) {
        fprintf(fp,"  jint             _c%d;\n", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConP")) {
        fprintf(fp,"  const TypePtr *_c%d;\n", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConN")) {
        fprintf(fp,"  const TypePtr *_c%d;\n", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConNKlass")) {
        fprintf(fp,"  const TypePtr *_c%d;\n", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConL")) {
        fprintf(fp,"  jlong            _c%d;\n", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConF")) {
        fprintf(fp,"  jfloat           _c%d;\n", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConD")) {
        fprintf(fp,"  jdouble          _c%d;\n", i);
        i++;
      }
    }
  }
}
static void defineConstructor(FILE *fp, const char *name, uint num_consts,
                              ComponentList &lst, bool is_ideal_bool,
                              Form::DataType constant_type, FormDict &globals) {
  fprintf(fp,"public:\n");
  fprintf(fp,"  %sOper(", name);
  if( num_consts == 0 ) {
    fprintf(fp,") {}\n");
    return;
  }
  uint i = 0;
  Component *comp;
  lst.reset();
  if ((comp = lst.iter()) == NULL) {
    assert(num_consts == 1, "Bad component list detected.\n");
    switch( constant_type ) {
    case Form::idealI : {
      fprintf(fp,is_ideal_bool ? "BoolTest::mask c%d" : "int32 c%d", i);
      break;
    }
    case Form::idealN :      { fprintf(fp,"const TypeNarrowOop *c%d", i); break; }
    case Form::idealNKlass : { fprintf(fp,"const TypeNarrowKlass *c%d", i); break; }
    case Form::idealP :      { fprintf(fp,"const TypePtr *c%d", i); break; }
    case Form::idealL :      { fprintf(fp,"jlong c%d", i);   break;        }
    case Form::idealF :      { fprintf(fp,"jfloat c%d", i);  break;        }
    case Form::idealD :      { fprintf(fp,"jdouble c%d", i); break;        }
    default:
      assert(!is_ideal_bool, "Non-constant operand lacks component list.");
      break;
    }
  } // end if NULL
  else {
    lst.reset();
    while((comp = lst.iter()) != NULL) {
      if (!strcmp(comp->base_type(globals), "ConI")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"int32 c%d", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConP")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"const TypePtr *c%d", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConN")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"const TypePtr *c%d", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConNKlass")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"const TypePtr *c%d", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConL")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"jlong c%d", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConF")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"jfloat c%d", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "ConD")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"jdouble c%d", i);
        i++;
      }
      else if (!strcmp(comp->base_type(globals), "Bool")) {
        if (i > 0) fprintf(fp,", ");
        fprintf(fp,"BoolTest::mask c%d", i);
        i++;
      }
    }
  }
  fprintf(fp,")  : ");
  i = 0;
  fprintf(fp,"_c%d(c%d)", i, i);
  for( i = 1; i < num_consts; ++i) {
    fprintf(fp,", _c%d(c%d)", i, i);
  }
  fprintf(fp," {}\n");
}
static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) {
  assert(oper != NULL, "what");
  CondInterface* cond = oper->_interface->is_CondInterface();
  fprintf(fp, "       if( _c%d == BoolTest::eq ) st->print_raw(\"%s\");\n",i,cond->_equal_format);
  fprintf(fp, "  else if( _c%d == BoolTest::ne ) st->print_raw(\"%s\");\n",i,cond->_not_equal_format);
  fprintf(fp, "  else if( _c%d == BoolTest::le ) st->print_raw(\"%s\");\n",i,cond->_less_equal_format);
  fprintf(fp, "  else if( _c%d == BoolTest::ge ) st->print_raw(\"%s\");\n",i,cond->_greater_equal_format);
  fprintf(fp, "  else if( _c%d == BoolTest::lt ) st->print_raw(\"%s\");\n",i,cond->_less_format);
  fprintf(fp, "  else if( _c%d == BoolTest::gt ) st->print_raw(\"%s\");\n",i,cond->_greater_format);
  fprintf(fp, "  else if( _c%d == BoolTest::overflow ) st->print_raw(\"%s\");\n",i,cond->_overflow_format);
  fprintf(fp, "  else if( _c%d == BoolTest::no_overflow ) st->print_raw(\"%s\");\n",i,cond->_no_overflow_format);
}
static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) {
  if (!strcmp(ideal_type, "ConI")) {
    fprintf(fp,"   st->print(\"#%%d\", _c%d);\n", i);
    fprintf(fp,"   st->print(\"/0x%%08x\", _c%d);\n", i);
    ++i;
  }
  else if (!strcmp(ideal_type, "ConP")) {
    fprintf(fp,"    _c%d->dump_on(st);\n", i);
    ++i;
  }
  else if (!strcmp(ideal_type, "ConN")) {
    fprintf(fp,"    _c%d->dump_on(st);\n", i);
    ++i;
  }
  else if (!strcmp(ideal_type, "ConNKlass")) {
    fprintf(fp,"    _c%d->dump_on(st);\n", i);
    ++i;
  }
  else if (!strcmp(ideal_type, "ConL")) {
    fprintf(fp,"    st->print(\"#\" INT64_FORMAT, (int64_t)_c%d);\n", i);
    fprintf(fp,"    st->print(\"/\" PTR64_FORMAT, (uint64_t)_c%d);\n", i);
    ++i;
  }
  else if (!strcmp(ideal_type, "ConF")) {
    fprintf(fp,"    st->print(\"#%%f\", _c%d);\n", i);
    fprintf(fp,"    jint _c%di = JavaValue(_c%d).get_jint();\n", i, i);
    fprintf(fp,"    st->print(\"/0x%%x/\", _c%di);\n", i);
    ++i;
  }
  else if (!strcmp(ideal_type, "ConD")) {
    fprintf(fp,"    st->print(\"#%%f\", _c%d);\n", i);
    fprintf(fp,"    jlong _c%dl = JavaValue(_c%d).get_jlong();\n", i, i);
    fprintf(fp,"    st->print(\"/\" PTR64_FORMAT, (uint64_t)_c%dl);\n", i);
    ++i;
  }
  else if (!strcmp(ideal_type, "Bool")) {
    defineCCodeDump(oper, fp,i);
    ++i;
  }
  return i;
}
void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_file = false) {
  if (!for_c_file) {
    fprintf(fp,"  virtual void           int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const;\n");
    fprintf(fp,"  virtual void           ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const;\n");
    return;
  }
  int idx = 0;                   // position of operand in match rule
  fprintf(fp, "\n#ifndef PRODUCT\n");
  fprintf(fp,"void %sOper::int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const {\n", oper._ident);
  if (oper._format) {
    if ( oper._format->_strings.count() != 0 ) {
      const char  *string  = NULL;
      oper._format->_rep_vars.reset();
      oper._format->_strings.reset();
      while ( (string = oper._format->_strings.iter()) != NULL ) {
        if ( string != NameList::_signal ) {
          fprintf(fp,"  st->print_raw(\"%s\");\n", string);
        } else {
          const char *rep_var = oper._format->_rep_vars.iter();
          const Form* form = oper._localNames[rep_var];
          if (form == NULL) {
            globalAD->syntax_err(oper._linenum,
                                 "\'%s\' not found in format for %s\n", rep_var, oper._ident);
            assert(form, "replacement variable was not found in local names");
          }
          OperandForm *op      = form->is_operand();
          if ( op->_matrule && op->_matrule->is_base_register(globals) ) {
            idx  = oper.register_position( globals, rep_var);
          }
          else if (op->_matrule && op->_matrule->is_base_constant(globals)) {
            idx  = oper.constant_position( globals, rep_var);
          } else {
            idx = 0;
          }
          if ( op != NULL ) op->int_format(fp, globals, idx);
          if ( idx == -1 ) {
            fprintf(stderr,
                    "Using a name, %s, that isn't in match rule\n", rep_var);
            assert( strcmp(op->_ident,"label")==0, "Unimplemented");
          }
        } // Done with a replacement variable
      } // Done with all format strings
    } else {
      oper.int_format(fp, globals, 0);
    }
  } else { // oper._format == NULL
    if ( strcmp(oper._ident,"Universe")==0 ) {
      fprintf(fp, "  st->print(\"$$univ\");\n");
    }
  }
  if( oper.is_ideal_bool() ) {
    defineCCodeDump(&oper, fp,0);
  }
  fprintf(fp,"}\n");
  fprintf(fp,"void %sOper::ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const {\n", oper._ident);
  if (oper._format) {
    if ( oper._format->_strings.count() != 0 ) {
      if ( oper._format->_rep_vars.count() != 0 ) {
      }
      const char  *string  = NULL;
      oper._format->_rep_vars.reset();
      oper._format->_strings.reset();
      while ( (string = oper._format->_strings.iter()) != NULL ) {
        if ( string != NameList::_signal ) {
          fprintf(fp,"  st->print_raw(\"%s\");\n", string);
        } else {
          const char *rep_var = oper._format->_rep_vars.iter();
          const Form* form = oper._localNames[rep_var];
          if (form == NULL) {
            globalAD->syntax_err(oper._linenum,
                                 "\'%s\' not found in format for %s\n", rep_var, oper._ident);
            assert(form, "replacement variable was not found in local names");
          }
          OperandForm *op      = form->is_operand();
          if ( op->_matrule && op->_matrule->is_base_register(globals) ) {
            idx  = oper.register_position( globals, rep_var);
          }
          else if (op->_matrule && op->_matrule->is_base_constant(globals)) {
            idx  = oper.constant_position( globals, rep_var);
          } else {
            idx = 0;
          }
          if ( op != NULL )   op->ext_format(fp, globals, idx);
          idx      = oper._components.operand_position_format(rep_var, &oper);
          if ( idx == -1 ) {
            fprintf(stderr,
                    "Using a name, %s, that isn't in match rule\n", rep_var);
            assert( strcmp(op->_ident,"label")==0, "Unimplemented");
          }
        } // Done with a replacement variable
      } // Done with all format strings
    } else {
      oper.ext_format(fp, globals, 0);
    }
  } else { // oper._format == NULL
    if ( strcmp(oper._ident,"Universe")==0 ) {
      fprintf(fp, "  st->print(\"$$univ\");\n");
    }
  }
  if( oper.is_ideal_bool() ) {
    defineCCodeDump(&oper, fp,0);
  }
  fprintf(fp, "}\n");
  fprintf(fp, "#endif\n");
}

void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c_file = false) {
  if (!for_c_file) {
    fprintf(fp,"  virtual void           format(PhaseRegAlloc *ra, outputStream *st) const;\n");
    return;
  }
  fprintf(fp, "#ifndef PRODUCT\n");
  fprintf(fp, "void %sNode::format(PhaseRegAlloc *ra, outputStream *st) const {\n", inst._ident);
  if( inst._format ) {
    if( inst._format->_rep_vars.count() )
      inst.index_temps(fp, globals);
    const char  *string  = NULL;
    inst._format->_rep_vars.reset();
    inst._format->_strings.reset();
    while( (string = inst._format->_strings.iter()) != NULL ) {
      fprintf(fp,"  ");
      if( string == NameList::_signal ) { // Replacement variable
        const char* rep_var =  inst._format->_rep_vars.iter();
        inst.rep_var_format( fp, rep_var);
      } else if( string == NameList::_signal3 ) { // Replacement variable in raw text
        const char* rep_var =  inst._format->_rep_vars.iter();
        const Form *form   = inst._localNames[rep_var];
        if (form == NULL) {
          fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var);
          assert(false, "ShouldNotReachHere()");
        }
        OpClassForm *opc   = form->is_opclass();
        assert( opc, "replacement variable was not found in local names");
        int idx  = inst.operand_position_format(rep_var);
        if ( idx == -1 ) {
          assert( strcmp(opc->_ident,"label")==0, "Unimplemented");
          assert( false, "ShouldNotReachHere()");
        }
        if (inst.is_noninput_operand(idx)) {
          assert( false, "ShouldNotReachHere()");
        } else {
          fprintf(fp,"opnd_array(%d)",idx);
        }
        rep_var =  inst._format->_rep_vars.iter();
        inst._format->_strings.iter();
        if ( strcmp(rep_var,"$constant") == 0 && opc->is_operand()) {
          Form::DataType constant_type = form->is_operand()->is_base_constant(globals);
          if ( constant_type == Form::idealD ) {
            fprintf(fp,"->constantD()");
          } else if ( constant_type == Form::idealF ) {
            fprintf(fp,"->constantF()");
          } else if ( constant_type == Form::idealL ) {
            fprintf(fp,"->constantL()");
          } else {
            fprintf(fp,"->constant()");
          }
        } else if ( strcmp(rep_var,"$cmpcode") == 0) {
            fprintf(fp,"->ccode()");
        } else {
          assert( false, "ShouldNotReachHere()");
        }
      } else if( string == NameList::_signal2 ) // Raw program text
        fputs(inst._format->_strings.iter(), fp);
      else
        fprintf(fp,"st->print_raw(\"%s\");\n", string);
    } // Done with all format strings
  } // Done generating the user-defined portion of the format
  Form::CallType call_type = inst.is_ideal_call();
  if( call_type != Form::invalid_type ) {
    switch( call_type ) {
    case Form::JAVA_DYNAMIC:
      fprintf(fp,"  _method->print_short_name(st);\n");
      break;
    case Form::JAVA_STATIC:
      fprintf(fp,"  if( _method ) _method->print_short_name(st);\n");
      fprintf(fp,"  else st->print(\" wrapper for: %%s\", _name);\n");
      fprintf(fp,"  if( !_method ) dump_trap_args(st);\n");
      break;
    case Form::JAVA_COMPILED:
    case Form::JAVA_INTERP:
      break;
    case Form::JAVA_RUNTIME:
    case Form::JAVA_LEAF:
    case Form::JAVA_NATIVE:
      fprintf(fp,"  st->print(\" %%s\", _name);");
      break;
    default:
      assert(0,"ShouldNotReachHere");
    }
    fprintf(fp,  "  st->cr();\n" );
    fprintf(fp,  "  if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\"        No JVM State Info\");\n" );
    fprintf(fp,  "  st->print(\"        # \");\n" );
    fprintf(fp,  "  if( _jvms && _oop_map ) _oop_map->print_on(st);\n");
  }
  else if(inst.is_ideal_safepoint()) {
    fprintf(fp,  "  st->print_raw(\"\");\n" );
    fprintf(fp,  "  if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\"        No JVM State Info\");\n" );
    fprintf(fp,  "  st->print(\"        # \");\n" );
    fprintf(fp,  "  if( _jvms && _oop_map ) _oop_map->print_on(st);\n");
  }
  else if( inst.is_ideal_if() ) {
    fprintf(fp,  "  st->print(\"  P=%%f C=%%f\",_prob,_fcnt);\n" );
  }
  else if( inst.is_ideal_mem() ) {
    fprintf(fp,  "  if (ra->C->alias_type(adr_type())->field() != NULL) {\n");
    fprintf(fp,  "    ciField* f = ra->C->alias_type(adr_type())->field();\n");
    fprintf(fp,  "    st->print(\" %s Field: \");\n", commentSeperator);
    fprintf(fp,  "    if (f->is_volatile())\n");
    fprintf(fp,  "      st->print(\"volatile \");\n");
    fprintf(fp,  "    f->holder()->name()->print_symbol_on(st);\n");
    fprintf(fp,  "    st->print(\".\");\n");
    fprintf(fp,  "    f->name()->print_symbol_on(st);\n");
    fprintf(fp,  "    if (f->is_constant())\n");
    fprintf(fp,  "      st->print(\" (constant)\");\n");
    fprintf(fp,  "  } else {\n");
    fprintf(fp,  "    if (ra->C->alias_type(adr_type())->is_volatile())\n");
    fprintf(fp,  "      st->print(\" volatile!\");\n");
    fprintf(fp,  "  }\n");
  }
  fprintf(fp, "}\n#endif\n");
}
void ArchDesc::declare_pipe_classes(FILE *fp_hpp) {
  if (!_pipeline)
    return;
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "// Pipeline_Use_Cycle_Mask Class\n");
  fprintf(fp_hpp, "class Pipeline_Use_Cycle_Mask {\n");
  if (_pipeline->_maxcycleused <=
#ifdef SPARC
    64
#else
    32
#endif
      ) {
    fprintf(fp_hpp, "protected:\n");
    fprintf(fp_hpp, "  %s _mask;\n\n", _pipeline->_maxcycleused <= 32 ? "uint" : "uint64_t" );
    fprintf(fp_hpp, "public:\n");
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask() : _mask(0) {}\n\n");
    if (_pipeline->_maxcycleused <= 32)
      fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask(uint mask) : _mask(mask) {}\n\n");
    else {
      fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask(uint mask1, uint mask2) : _mask((((uint64_t)mask1) << 32) | mask2) {}\n\n");
      fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask(uint64_t mask) : _mask(mask) {}\n\n");
    }
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask& operator=(const Pipeline_Use_Cycle_Mask &in) {\n");
    fprintf(fp_hpp, "    _mask = in._mask;\n");
    fprintf(fp_hpp, "    return *this;\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  bool overlaps(const Pipeline_Use_Cycle_Mask &in2) const {\n");
    fprintf(fp_hpp, "    return ((_mask & in2._mask) != 0);\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask& operator<<=(int n) {\n");
    fprintf(fp_hpp, "    _mask <<= n;\n");
    fprintf(fp_hpp, "    return *this;\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  void Or(const Pipeline_Use_Cycle_Mask &in2) {\n");
    fprintf(fp_hpp, "    _mask |= in2._mask;\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  friend Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n");
    fprintf(fp_hpp, "  friend Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n\n");
  }
  else {
    fprintf(fp_hpp, "protected:\n");
    uint masklen = (_pipeline->_maxcycleused + 31) >> 5;
    uint l;
    fprintf(fp_hpp, "  uint ");
    for (l = 1; l <= masklen; l++)
      fprintf(fp_hpp, "_mask%d%s", l, l < masklen ? ", " : ";\n\n");
    fprintf(fp_hpp, "public:\n");
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask() : ");
    for (l = 1; l <= masklen; l++)
      fprintf(fp_hpp, "_mask%d(0)%s", l, l < masklen ? ", " : " {}\n\n");
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask(");
    for (l = 1; l <= masklen; l++)
      fprintf(fp_hpp, "uint mask%d%s", l, l < masklen ? ", " : ") : ");
    for (l = 1; l <= masklen; l++)
      fprintf(fp_hpp, "_mask%d(mask%d)%s", l, l, l < masklen ? ", " : " {}\n\n");
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask& operator=(const Pipeline_Use_Cycle_Mask &in) {\n");
    for (l = 1; l <= masklen; l++)
      fprintf(fp_hpp, "    _mask%d = in._mask%d;\n", l, l);
    fprintf(fp_hpp, "    return *this;\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask intersect(const Pipeline_Use_Cycle_Mask &in2) {\n");
    fprintf(fp_hpp, "    Pipeline_Use_Cycle_Mask out;\n");
    for (l = 1; l <= masklen; l++)
      fprintf(fp_hpp, "    out._mask%d = _mask%d & in2._mask%d;\n", l, l, l);
    fprintf(fp_hpp, "    return out;\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  bool overlaps(const Pipeline_Use_Cycle_Mask &in2) const {\n");
    fprintf(fp_hpp, "    return (");
    for (l = 1; l <= masklen; l++)
      fprintf(fp_hpp, "((_mask%d & in2._mask%d) != 0)%s", l, l, l < masklen ? " || " : "");
    fprintf(fp_hpp, ") ? true : false;\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask& operator<<=(int n) {\n");
    fprintf(fp_hpp, "    if (n >= 32)\n");
    fprintf(fp_hpp, "      do {\n       ");
    for (l = masklen; l > 1; l--)
      fprintf(fp_hpp, " _mask%d = _mask%d;", l, l-1);
    fprintf(fp_hpp, " _mask%d = 0;\n", 1);
    fprintf(fp_hpp, "      } while ((n -= 32) >= 32);\n\n");
    fprintf(fp_hpp, "    if (n > 0) {\n");
    fprintf(fp_hpp, "      uint m = 32 - n;\n");
    fprintf(fp_hpp, "      uint mask = (1 << n) - 1;\n");
    fprintf(fp_hpp, "      uint temp%d = mask & (_mask%d >> m); _mask%d <<= n;\n", 2, 1, 1);
    for (l = 2; l < masklen; l++) {
      fprintf(fp_hpp, "      uint temp%d = mask & (_mask%d >> m); _mask%d <<= n; _mask%d |= temp%d;\n", l+1, l, l, l, l);
    }
    fprintf(fp_hpp, "      _mask%d <<= n; _mask%d |= temp%d;\n", masklen, masklen, masklen);
    fprintf(fp_hpp, "    }\n");
    fprintf(fp_hpp, "    return *this;\n");
    fprintf(fp_hpp, "  }\n\n");
    fprintf(fp_hpp, "  void Or(const Pipeline_Use_Cycle_Mask &);\n\n");
    fprintf(fp_hpp, "  friend Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n");
    fprintf(fp_hpp, "  friend Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n\n");
  }
  fprintf(fp_hpp, "  friend class Pipeline_Use;\n\n");
  fprintf(fp_hpp, "  friend class Pipeline_Use_Element;\n\n");
  fprintf(fp_hpp, "};\n\n");
  uint rescount = 0;
  const char *resource;
  for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) {
      int mask = _pipeline->_resdict[resource]->is_resource()->mask();
      if ((mask & (mask-1)) == 0)
        rescount++;
    }
  fprintf(fp_hpp, "// Pipeline_Use_Element Class\n");
  fprintf(fp_hpp, "class Pipeline_Use_Element {\n");
  fprintf(fp_hpp, "protected:\n");
  fprintf(fp_hpp, "  // Mask of used functional units\n");
  fprintf(fp_hpp, "  uint _used;\n\n");
  fprintf(fp_hpp, "  // Lower and upper bound of functional unit number range\n");
  fprintf(fp_hpp, "  uint _lb, _ub;\n\n");
  fprintf(fp_hpp, "  // Indicates multiple functionals units available\n");
  fprintf(fp_hpp, "  bool _multiple;\n\n");
  fprintf(fp_hpp, "  // Mask of specific used cycles\n");
  fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask _mask;\n\n");
  fprintf(fp_hpp, "public:\n");
  fprintf(fp_hpp, "  Pipeline_Use_Element() {}\n\n");
  fprintf(fp_hpp, "  Pipeline_Use_Element(uint used, uint lb, uint ub, bool multiple, Pipeline_Use_Cycle_Mask mask)\n");
  fprintf(fp_hpp, "  : _used(used), _lb(lb), _ub(ub), _multiple(multiple), _mask(mask) {}\n\n");
  fprintf(fp_hpp, "  uint used() const { return _used; }\n\n");
  fprintf(fp_hpp, "  uint lowerBound() const { return _lb; }\n\n");
  fprintf(fp_hpp, "  uint upperBound() const { return _ub; }\n\n");
  fprintf(fp_hpp, "  bool multiple() const { return _multiple; }\n\n");
  fprintf(fp_hpp, "  Pipeline_Use_Cycle_Mask mask() const { return _mask; }\n\n");
  fprintf(fp_hpp, "  bool overlaps(const Pipeline_Use_Element &in2) const {\n");
  fprintf(fp_hpp, "    return ((_used & in2._used) != 0 && _mask.overlaps(in2._mask));\n");
  fprintf(fp_hpp, "  }\n\n");
  fprintf(fp_hpp, "  void step(uint cycles) {\n");
  fprintf(fp_hpp, "    _used = 0;\n");
  fprintf(fp_hpp, "    _mask <<= cycles;\n");
  fprintf(fp_hpp, "  }\n\n");
  fprintf(fp_hpp, "  friend class Pipeline_Use;\n");
  fprintf(fp_hpp, "};\n\n");
  fprintf(fp_hpp, "// Pipeline_Use Class\n");
  fprintf(fp_hpp, "class Pipeline_Use {\n");
  fprintf(fp_hpp, "protected:\n");
  fprintf(fp_hpp, "  // These resources can be used\n");
  fprintf(fp_hpp, "  uint _resources_used;\n\n");
  fprintf(fp_hpp, "  // These resources are used; excludes multiple choice functional units\n");
  fprintf(fp_hpp, "  uint _resources_used_exclusively;\n\n");
  fprintf(fp_hpp, "  // Number of elements\n");
  fprintf(fp_hpp, "  uint _count;\n\n");
  fprintf(fp_hpp, "  // This is the array of Pipeline_Use_Elements\n");
  fprintf(fp_hpp, "  Pipeline_Use_Element * _elements;\n\n");
  fprintf(fp_hpp, "public:\n");
  fprintf(fp_hpp, "  Pipeline_Use(uint resources_used, uint resources_used_exclusively, uint count, Pipeline_Use_Element *elements)\n");
  fprintf(fp_hpp, "  : _resources_used(resources_used)\n");
  fprintf(fp_hpp, "  , _resources_used_exclusively(resources_used_exclusively)\n");
  fprintf(fp_hpp, "  , _count(count)\n");
  fprintf(fp_hpp, "  , _elements(elements)\n");
  fprintf(fp_hpp, "  {}\n\n");
  fprintf(fp_hpp, "  uint resourcesUsed() const { return _resources_used; }\n\n");
  fprintf(fp_hpp, "  uint resourcesUsedExclusively() const { return _resources_used_exclusively; }\n\n");
  fprintf(fp_hpp, "  uint count() const { return _count; }\n\n");
  fprintf(fp_hpp, "  Pipeline_Use_Element * element(uint i) const { return &_elements[i]; }\n\n");
  fprintf(fp_hpp, "  uint full_latency(uint delay, const Pipeline_Use &pred) const;\n\n");
  fprintf(fp_hpp, "  void add_usage(const Pipeline_Use &pred);\n\n");
  fprintf(fp_hpp, "  void reset() {\n");
  fprintf(fp_hpp, "    _resources_used = _resources_used_exclusively = 0;\n");
  fprintf(fp_hpp, "  };\n\n");
  fprintf(fp_hpp, "  void step(uint cycles) {\n");
  fprintf(fp_hpp, "    reset();\n");
  fprintf(fp_hpp, "    for (uint i = 0; i < %d; i++)\n",
    rescount);
  fprintf(fp_hpp, "      (&_elements[i])->step(cycles);\n");
  fprintf(fp_hpp, "  };\n\n");
  fprintf(fp_hpp, "  static const Pipeline_Use         elaborated_use;\n");
  fprintf(fp_hpp, "  static const Pipeline_Use_Element elaborated_elements[%d];\n\n",
    rescount);
  fprintf(fp_hpp, "  friend class Pipeline;\n");
  fprintf(fp_hpp, "};\n\n");
  fprintf(fp_hpp, "// Pipeline Class\n");
  fprintf(fp_hpp, "class Pipeline {\n");
  fprintf(fp_hpp, "public:\n");
  fprintf(fp_hpp, "  static bool enabled() { return %s; }\n\n",
    _pipeline ? "true" : "false" );
  assert( _pipeline->_maxInstrsPerBundle &&
        ( _pipeline->_instrUnitSize || _pipeline->_bundleUnitSize) &&
          _pipeline->_instrFetchUnitSize &&
          _pipeline->_instrFetchUnits,
    "unspecified pipeline architecture units");
  uint unitSize = _pipeline->_instrUnitSize ? _pipeline->_instrUnitSize : _pipeline->_bundleUnitSize;
  fprintf(fp_hpp, "  enum {\n");
  fprintf(fp_hpp, "    _variable_size_instructions = %d,\n",
    _pipeline->_variableSizeInstrs ? 1 : 0);
  fprintf(fp_hpp, "    _fixed_size_instructions = %d,\n",
    _pipeline->_variableSizeInstrs ? 0 : 1);
  fprintf(fp_hpp, "    _branch_has_delay_slot = %d,\n",
    _pipeline->_branchHasDelaySlot ? 1 : 0);
  fprintf(fp_hpp, "    _max_instrs_per_bundle = %d,\n",
    _pipeline->_maxInstrsPerBundle);
  fprintf(fp_hpp, "    _max_bundles_per_cycle = %d,\n",
    _pipeline->_maxBundlesPerCycle);
  fprintf(fp_hpp, "    _max_instrs_per_cycle = %d\n",
    _pipeline->_maxBundlesPerCycle * _pipeline->_maxInstrsPerBundle);
  fprintf(fp_hpp, "  };\n\n");
  fprintf(fp_hpp, "  static bool instr_has_unit_size() { return %s; }\n\n",
    _pipeline->_instrUnitSize != 0 ? "true" : "false" );
  if( _pipeline->_bundleUnitSize != 0 )
    if( _pipeline->_instrUnitSize != 0 )
      fprintf(fp_hpp, "// Individual Instructions may be bundled together by the hardware\n\n");
    else
      fprintf(fp_hpp, "// Instructions exist only in bundles\n\n");
  else
    fprintf(fp_hpp, "// Bundling is not supported\n\n");
  if( _pipeline->_instrUnitSize != 0 )
    fprintf(fp_hpp, "  // Size of an instruction\n");
  else
    fprintf(fp_hpp, "  // Size of an individual instruction does not exist - unsupported\n");
  fprintf(fp_hpp, "  static uint instr_unit_size() {");
  if( _pipeline->_instrUnitSize == 0 )
    fprintf(fp_hpp, " assert( false, \"Instructions are only in bundles\" );");
  fprintf(fp_hpp, " return %d; };\n\n", _pipeline->_instrUnitSize);
  if( _pipeline->_bundleUnitSize != 0 )
    fprintf(fp_hpp, "  // Size of a bundle\n");
  else
    fprintf(fp_hpp, "  // Bundles do not exist - unsupported\n");
  fprintf(fp_hpp, "  static uint bundle_unit_size() {");
  if( _pipeline->_bundleUnitSize == 0 )
    fprintf(fp_hpp, " assert( false, \"Bundles are not supported\" );");
  fprintf(fp_hpp, " return %d; };\n\n", _pipeline->_bundleUnitSize);
  fprintf(fp_hpp, "  static bool requires_bundling() { return %s; }\n\n",
    _pipeline->_bundleUnitSize != 0 && _pipeline->_instrUnitSize == 0 ? "true" : "false" );
  fprintf(fp_hpp, "private:\n");
  fprintf(fp_hpp, "  Pipeline();  // Not a legal constructor\n");
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "  const unsigned char                   _read_stage_count;\n");
  fprintf(fp_hpp, "  const unsigned char                   _write_stage;\n");
  fprintf(fp_hpp, "  const unsigned char                   _fixed_latency;\n");
  fprintf(fp_hpp, "  const unsigned char                   _instruction_count;\n");
  fprintf(fp_hpp, "  const bool                            _has_fixed_latency;\n");
  fprintf(fp_hpp, "  const bool                            _has_branch_delay;\n");
  fprintf(fp_hpp, "  const bool                            _has_multiple_bundles;\n");
  fprintf(fp_hpp, "  const bool                            _force_serialization;\n");
  fprintf(fp_hpp, "  const bool                            _may_have_no_code;\n");
  fprintf(fp_hpp, "  const enum machPipelineStages * const _read_stages;\n");
  fprintf(fp_hpp, "  const enum machPipelineStages * const _resource_stage;\n");
  fprintf(fp_hpp, "  const uint                    * const _resource_cycles;\n");
  fprintf(fp_hpp, "  const Pipeline_Use                    _resource_use;\n");
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "public:\n");
  fprintf(fp_hpp, "  Pipeline(uint                            write_stage,\n");
  fprintf(fp_hpp, "           uint                            count,\n");
  fprintf(fp_hpp, "           bool                            has_fixed_latency,\n");
  fprintf(fp_hpp, "           uint                            fixed_latency,\n");
  fprintf(fp_hpp, "           uint                            instruction_count,\n");
  fprintf(fp_hpp, "           bool                            has_branch_delay,\n");
  fprintf(fp_hpp, "           bool                            has_multiple_bundles,\n");
  fprintf(fp_hpp, "           bool                            force_serialization,\n");
  fprintf(fp_hpp, "           bool                            may_have_no_code,\n");
  fprintf(fp_hpp, "           enum machPipelineStages * const dst,\n");
  fprintf(fp_hpp, "           enum machPipelineStages * const stage,\n");
  fprintf(fp_hpp, "           uint                    * const cycles,\n");
  fprintf(fp_hpp, "           Pipeline_Use                    resource_use)\n");
  fprintf(fp_hpp, "  : _write_stage(write_stage)\n");
  fprintf(fp_hpp, "  , _read_stage_count(count)\n");
  fprintf(fp_hpp, "  , _has_fixed_latency(has_fixed_latency)\n");
  fprintf(fp_hpp, "  , _fixed_latency(fixed_latency)\n");
  fprintf(fp_hpp, "  , _read_stages(dst)\n");
  fprintf(fp_hpp, "  , _resource_stage(stage)\n");
  fprintf(fp_hpp, "  , _resource_cycles(cycles)\n");
  fprintf(fp_hpp, "  , _resource_use(resource_use)\n");
  fprintf(fp_hpp, "  , _instruction_count(instruction_count)\n");
  fprintf(fp_hpp, "  , _has_branch_delay(has_branch_delay)\n");
  fprintf(fp_hpp, "  , _has_multiple_bundles(has_multiple_bundles)\n");
  fprintf(fp_hpp, "  , _force_serialization(force_serialization)\n");
  fprintf(fp_hpp, "  , _may_have_no_code(may_have_no_code)\n");
  fprintf(fp_hpp, "  {};\n");
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "  uint writeStage() const {\n");
  fprintf(fp_hpp, "    return (_write_stage);\n");
  fprintf(fp_hpp, "  }\n");
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "  enum machPipelineStages readStage(int ndx) const {\n");
  fprintf(fp_hpp, "    return (ndx < _read_stage_count ? _read_stages[ndx] : stage_undefined);");
  fprintf(fp_hpp, "  }\n\n");
  fprintf(fp_hpp, "  uint resourcesUsed() const {\n");
  fprintf(fp_hpp, "    return _resource_use.resourcesUsed();\n  }\n\n");
  fprintf(fp_hpp, "  uint resourcesUsedExclusively() const {\n");
  fprintf(fp_hpp, "    return _resource_use.resourcesUsedExclusively();\n  }\n\n");
  fprintf(fp_hpp, "  bool hasFixedLatency() const {\n");
  fprintf(fp_hpp, "    return (_has_fixed_latency);\n  }\n\n");
  fprintf(fp_hpp, "  uint fixedLatency() const {\n");
  fprintf(fp_hpp, "    return (_fixed_latency);\n  }\n\n");
  fprintf(fp_hpp, "  uint functional_unit_latency(uint start, const Pipeline *pred) const;\n\n");
  fprintf(fp_hpp, "  uint operand_latency(uint opnd, const Pipeline *pred) const;\n\n");
  fprintf(fp_hpp, "  const Pipeline_Use& resourceUse() const {\n");
  fprintf(fp_hpp, "    return (_resource_use); }\n\n");
  fprintf(fp_hpp, "  const Pipeline_Use_Element * resourceUseElement(uint i) const {\n");
  fprintf(fp_hpp, "    return (&_resource_use._elements[i]); }\n\n");
  fprintf(fp_hpp, "  uint resourceUseCount() const {\n");
  fprintf(fp_hpp, "    return (_resource_use._count); }\n\n");
  fprintf(fp_hpp, "  uint instructionCount() const {\n");
  fprintf(fp_hpp, "    return (_instruction_count); }\n\n");
  fprintf(fp_hpp, "  bool hasBranchDelay() const {\n");
  fprintf(fp_hpp, "    return (_has_branch_delay); }\n\n");
  fprintf(fp_hpp, "  bool hasMultipleBundles() const {\n");
  fprintf(fp_hpp, "    return (_has_multiple_bundles); }\n\n");
  fprintf(fp_hpp, "  bool forceSerialization() const {\n");
  fprintf(fp_hpp, "    return (_force_serialization); }\n\n");
  fprintf(fp_hpp, "  bool mayHaveNoCode() const {\n");
  fprintf(fp_hpp, "    return (_may_have_no_code); }\n\n");
  fprintf(fp_hpp, "//const Pipeline_Use_Cycle_Mask& resourceUseMask(int resource) const {\n");
  fprintf(fp_hpp, "//  return (_resource_use_masks[resource]); }\n\n");
  fprintf(fp_hpp, "\n#ifndef PRODUCT\n");
  fprintf(fp_hpp, "  static const char * stageName(uint i);\n");
  fprintf(fp_hpp, "#endif\n");
  fprintf(fp_hpp, "};\n\n");
  fprintf(fp_hpp, "// Bundle class\n");
  fprintf(fp_hpp, "class Bundle {\n");
  uint mshift = 0;
  for (uint msize = _pipeline->_maxInstrsPerBundle * _pipeline->_maxBundlesPerCycle; msize != 0; msize >>= 1)
    mshift++;
  uint rshift = rescount;
  fprintf(fp_hpp, "protected:\n");
  fprintf(fp_hpp, "  enum {\n");
  fprintf(fp_hpp, "    _unused_delay                   = 0x%x,\n", 0);
  fprintf(fp_hpp, "    _use_nop_delay                  = 0x%x,\n", 1);
  fprintf(fp_hpp, "    _use_unconditional_delay        = 0x%x,\n", 2);
  fprintf(fp_hpp, "    _use_conditional_delay          = 0x%x,\n", 3);
  fprintf(fp_hpp, "    _used_in_conditional_delay      = 0x%x,\n", 4);
  fprintf(fp_hpp, "    _used_in_unconditional_delay    = 0x%x,\n", 5);
  fprintf(fp_hpp, "    _used_in_all_conditional_delays = 0x%x,\n", 6);
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "    _use_delay                      = 0x%x,\n", 3);
  fprintf(fp_hpp, "    _used_in_delay                  = 0x%x\n",  4);
  fprintf(fp_hpp, "  };\n\n");
  fprintf(fp_hpp, "  uint _flags          : 3,\n");
  fprintf(fp_hpp, "       _starts_bundle  : 1,\n");
  fprintf(fp_hpp, "       _instr_count    : %d,\n",   mshift);
  fprintf(fp_hpp, "       _resources_used : %d;\n",   rshift);
  fprintf(fp_hpp, "public:\n");
  fprintf(fp_hpp, "  Bundle() : _flags(_unused_delay), _starts_bundle(0), _instr_count(0), _resources_used(0) {}\n\n");
  fprintf(fp_hpp, "  void set_instr_count(uint i) { _instr_count  = i; }\n");
  fprintf(fp_hpp, "  void set_resources_used(uint i) { _resources_used   = i; }\n");
  fprintf(fp_hpp, "  void clear_usage() { _flags = _unused_delay; }\n");
  fprintf(fp_hpp, "  void set_starts_bundle() { _starts_bundle = true; }\n");
  fprintf(fp_hpp, "  uint flags() const { return (_flags); }\n");
  fprintf(fp_hpp, "  uint instr_count() const { return (_instr_count); }\n");
  fprintf(fp_hpp, "  uint resources_used() const { return (_resources_used); }\n");
  fprintf(fp_hpp, "  bool starts_bundle() const { return (_starts_bundle != 0); }\n");
  fprintf(fp_hpp, "  void set_use_nop_delay() { _flags = _use_nop_delay; }\n");
  fprintf(fp_hpp, "  void set_use_unconditional_delay() { _flags = _use_unconditional_delay; }\n");
  fprintf(fp_hpp, "  void set_use_conditional_delay() { _flags = _use_conditional_delay; }\n");
  fprintf(fp_hpp, "  void set_used_in_unconditional_delay() { _flags = _used_in_unconditional_delay; }\n");
  fprintf(fp_hpp, "  void set_used_in_conditional_delay() { _flags = _used_in_conditional_delay; }\n");
  fprintf(fp_hpp, "  void set_used_in_all_conditional_delays() { _flags = _used_in_all_conditional_delays; }\n");
  fprintf(fp_hpp, "  bool use_nop_delay() { return (_flags == _use_nop_delay); }\n");
  fprintf(fp_hpp, "  bool use_unconditional_delay() { return (_flags == _use_unconditional_delay); }\n");
  fprintf(fp_hpp, "  bool use_conditional_delay() { return (_flags == _use_conditional_delay); }\n");
  fprintf(fp_hpp, "  bool used_in_unconditional_delay() { return (_flags == _used_in_unconditional_delay); }\n");
  fprintf(fp_hpp, "  bool used_in_conditional_delay() { return (_flags == _used_in_conditional_delay); }\n");
  fprintf(fp_hpp, "  bool used_in_all_conditional_delays() { return (_flags == _used_in_all_conditional_delays); }\n");
  fprintf(fp_hpp, "  bool use_delay() { return ((_flags & _use_delay) != 0); }\n");
  fprintf(fp_hpp, "  bool used_in_delay() { return ((_flags & _used_in_delay) != 0); }\n\n");
  fprintf(fp_hpp, "  enum {\n");
  fprintf(fp_hpp, "    _nop_count = %d\n",
    _pipeline->_nopcnt);
  fprintf(fp_hpp, "  };\n\n");
  fprintf(fp_hpp, "  static void initialize_nops(MachNode *nop_list[%d], Compile* C);\n\n",
    _pipeline->_nopcnt);
  fprintf(fp_hpp, "#ifndef PRODUCT\n");
  fprintf(fp_hpp, "  void dump(outputStream *st = tty) const;\n");
  fprintf(fp_hpp, "#endif\n");
  fprintf(fp_hpp, "};\n\n");
}
void ArchDesc::declareClasses(FILE *fp) {
  declareRegNames(fp, _register);
  declareRegEncodes(fp, _register);
  fprintf(fp,"\n");
  fprintf(fp,"// Total number of operands defined in architecture definition\n");
  int num_operands = 0;
  OperandForm *op;
  for (_operands.reset(); (op = (OperandForm*)_operands.iter()) != NULL; ) {
    if (op->ideal_only()) continue;
    ++num_operands;
  }
  int first_operand_class = num_operands;
  OpClassForm *opc;
  for (_opclass.reset(); (opc = (OpClassForm*)_opclass.iter()) != NULL; ) {
    if (opc->ideal_only()) continue;
    ++num_operands;
  }
  fprintf(fp,"#define FIRST_OPERAND_CLASS   %d\n", first_operand_class);
  fprintf(fp,"#define NUM_OPERANDS          %d\n", num_operands);
  fprintf(fp,"\n");
  fprintf(fp,"// Total number of instructions defined in architecture definition\n");
  fprintf(fp,"#define NUM_INSTRUCTIONS   %d\n",instructFormCount());
  fprintf(fp,"\n");
  fprintf(fp,"//----------------------------Declare classes derived from MachOper----------\n");
  _operands.reset();
  OperandForm *oper;
  for( ; (oper = (OperandForm*)_operands.iter()) != NULL;) {
    if (oper->ideal_only() ) continue;
    if ( strcmp(oper->_ident,"label")  == 0 ) continue;
    if ( strcmp(oper->_ident,"method") == 0 ) continue;
    fprintf(fp,"\n");
    fprintf(fp,"class %sOper : public MachOper { \n",oper->_ident);
    fprintf(fp,"private:\n");
    {
      uint num_edges = oper->num_edges(_globalNames);
      if( num_edges != 1 ) { // Use MachOper::num_edges() {return 1;}
        fprintf(fp,"  virtual uint           num_edges() const { return %d; }\n",
              num_edges );
      }
      if( num_edges > 0 ) {
        in_RegMask(fp);
      }
    }
    declareConstStorage(fp,_globalNames,oper);
    if( oper->is_ideal_bool() ) {
      fprintf(fp,"  virtual int ccode() const { \n");
      fprintf(fp,"    switch (_c0) {\n");
      fprintf(fp,"    case  BoolTest::eq : return equal();\n");
      fprintf(fp,"    case  BoolTest::gt : return greater();\n");
      fprintf(fp,"    case  BoolTest::lt : return less();\n");
      fprintf(fp,"    case  BoolTest::ne : return not_equal();\n");
      fprintf(fp,"    case  BoolTest::le : return less_equal();\n");
      fprintf(fp,"    case  BoolTest::ge : return greater_equal();\n");
      fprintf(fp,"    case  BoolTest::overflow : return overflow();\n");
      fprintf(fp,"    case  BoolTest::no_overflow: return no_overflow();\n");
      fprintf(fp,"    default : ShouldNotReachHere(); return 0;\n");
      fprintf(fp,"    }\n");
      fprintf(fp,"  };\n");
    }
    if( oper->is_ideal_bool() ) {
      fprintf(fp,"  virtual void negate() { \n");
      fprintf(fp,"    _c0 = (BoolTest::mask)((int)_c0^0x4); \n");
      fprintf(fp,"  };\n");
    }
    Form::DataType constant_type = oper->simple_type(_globalNames);
    defineConstructor(fp, oper->_ident, oper->num_consts(_globalNames),
                      oper->_components, oper->is_ideal_bool(),
                      constant_type, _globalNames);
    fprintf(fp,"  virtual MachOper      *clone(Compile* C) const;\n");
    if( oper->has_conI(_globalNames) ||
        oper->has_conL(_globalNames) )
      fprintf(fp, "  virtual void set_con( jint c0 ) { _c0 = c0; }\n");
    fprintf(fp,"  virtual uint           opcode() const { return %s; }\n",
            machOperEnum(oper->_ident));
    if ((oper->_matrule) && (oper->_matrule->_lChild == NULL) &&
        (oper->_matrule->_rChild == NULL)) {
      unsigned int position = 0;
      const char  *opret, *opname, *optype;
      oper->_matrule->base_operand(position,_globalNames,opret,opname,optype);
      fprintf(fp,"  virtual const Type    *type() const {");
      const char *type = getIdealType(optype);
      if( type != NULL ) {
        Form::DataType data_type = oper->is_base_constant(_globalNames);
        if( data_type == Form::idealP || data_type == Form::idealN || data_type == Form::idealNKlass ) {
          fprintf(fp," return _c0;");
        } else {
          fprintf(fp," return %s;", getIdealType(optype));
        }
      } else {
        fprintf(fp," ShouldNotCallThis(); return Type::BOTTOM;");
      }
      fprintf(fp," }\n");
    } else {
      Form::DataType data_type = oper->is_user_name_for_sReg();
      if( data_type != Form::none ){
        const char *type = NULL;
        switch( data_type ) {
        case Form::idealI: type = "TypeInt::INT";   break;
        case Form::idealP: type = "TypePtr::BOTTOM";break;
        case Form::idealF: type = "Type::FLOAT";    break;
        case Form::idealD: type = "Type::DOUBLE";   break;
        case Form::idealL: type = "TypeLong::LONG"; break;
        case Form::none: // fall through
        default:
          assert( false, "No support for this type of stackSlot");
        }
        fprintf(fp,"  virtual const Type    *type() const { return %s; } // stackSlotX\n", type);
      }
    }
    if ( oper->_matrule && oper->_matrule->is_base_register(_globalNames) ) {
    } else if ( oper->ideal_to_sReg_type(oper->_ident) != Form::none ) {
      fprintf(fp,"  virtual int            reg(PhaseRegAlloc *ra_, const Node *node) const {\n");
      fprintf(fp,"    return (int)OptoReg::reg2stack(ra_->get_reg_first(node));/* sReg */\n");
      fprintf(fp,"  }\n");
      fprintf(fp,"  virtual int            reg(PhaseRegAlloc *ra_, const Node *node, int idx) const {\n");
      fprintf(fp,"    return (int)OptoReg::reg2stack(ra_->get_reg_first(node->in(idx)));/* sReg */\n");
      fprintf(fp,"  }\n");
    }
    if (oper->_interface != NULL) {
      fprintf(fp,"\n");
      if ( oper->_interface->is_MemInterface() != NULL ) {
        MemInterface *mem_interface = oper->_interface->is_MemInterface();
        const char *base = mem_interface->_base;
        if( base != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "base", base);
        }
        char *index = mem_interface->_index;
        if( index != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "index", index);
        }
        const char *scale = mem_interface->_scale;
        if( scale != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "scale", scale);
        }
        const char *disp = mem_interface->_disp;
        if( disp != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "disp", disp);
          oper->disp_is_oop(fp, _globalNames);
        }
        if( oper->stack_slots_only(_globalNames) ) {
          fprintf(fp,"  virtual int       constant_disp() const { return Type::OffsetBot; }");
        } else if ( disp != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "constant_disp", disp);
        }
      } // end Memory Interface
      else if (oper->_interface->is_CondInterface() != NULL) {
        CondInterface *cInterface = oper->_interface->is_CondInterface();
        const char *equal = cInterface->_equal;
        if( equal != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "equal", equal);
        }
        const char *not_equal = cInterface->_not_equal;
        if( not_equal != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "not_equal", not_equal);
        }
        const char *less = cInterface->_less;
        if( less != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "less", less);
        }
        const char *greater_equal = cInterface->_greater_equal;
        if( greater_equal != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "greater_equal", greater_equal);
        }
        const char *less_equal = cInterface->_less_equal;
        if( less_equal != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "less_equal", less_equal);
        }
        const char *greater = cInterface->_greater;
        if( greater != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "greater", greater);
        }
        const char *overflow = cInterface->_overflow;
        if( overflow != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "overflow", overflow);
        }
        const char *no_overflow = cInterface->_no_overflow;
        if( no_overflow != NULL ) {
          define_oper_interface(fp, *oper, _globalNames, "no_overflow", no_overflow);
        }
      } // end Conditional Interface
      else if (oper->_interface->is_ConstInterface() != NULL ) {
        assert( oper->num_consts(_globalNames) == 1,
                "Must have one constant when using CONST_INTER encoding");
        if (!strcmp(oper->ideal_type(_globalNames), "ConI")) {
          fprintf(fp,"  virtual intptr_t       constant() const {");
          fprintf(fp,   " return (intptr_t)_c0;");
          fprintf(fp,"  }\n");
        }
        else if (!strcmp(oper->ideal_type(_globalNames), "ConP")) {
          fprintf(fp,"  virtual intptr_t       constant() const {");
          fprintf(fp,   " return _c0->get_con();");
          fprintf(fp, " }\n");
          fprintf(fp,"  virtual relocInfo::relocType           constant_reloc() const {");
          fprintf(fp,   " return _c0->reloc();");
          fprintf(fp, " }\n");
        }
        else if (!strcmp(oper->ideal_type(_globalNames), "ConN")) {
          fprintf(fp,"  virtual intptr_t       constant() const {");
          fprintf(fp,   " return _c0->get_ptrtype()->get_con();");
          fprintf(fp, " }\n");
          fprintf(fp,"  virtual relocInfo::relocType           constant_reloc() const {");
          fprintf(fp,   " return _c0->get_ptrtype()->reloc();");
          fprintf(fp, " }\n");
        }
        else if (!strcmp(oper->ideal_type(_globalNames), "ConNKlass")) {
          fprintf(fp,"  virtual intptr_t       constant() const {");
          fprintf(fp,   " return _c0->get_ptrtype()->get_con();");
          fprintf(fp, " }\n");
          fprintf(fp,"  virtual relocInfo::relocType           constant_reloc() const {");
          fprintf(fp,   " return _c0->get_ptrtype()->reloc();");
          fprintf(fp, " }\n");
        }
        else if (!strcmp(oper->ideal_type(_globalNames), "ConL")) {
          fprintf(fp,"  virtual intptr_t       constant() const {");
          fprintf(fp,   "  return (intptr_t)_c0;");
          fprintf(fp, " }\n");
          fprintf(fp,"  virtual jlong          constantL() const {");
          fprintf(fp,   " return _c0;");
          fprintf(fp, " }\n");
        }
        else if (!strcmp(oper->ideal_type(_globalNames), "ConF")) {
          fprintf(fp,"  virtual intptr_t       constant() const {");
          fprintf(fp,   " ShouldNotReachHere(); return 0; ");
          fprintf(fp, " }\n");
          fprintf(fp,"  virtual jfloat         constantF() const {");
          fprintf(fp,   " return (jfloat)_c0;");
          fprintf(fp, " }\n");
        }
        else if (!strcmp(oper->ideal_type(_globalNames), "ConD")) {
          fprintf(fp,"  virtual intptr_t       constant() const {");
          fprintf(fp,   " ShouldNotReachHere(); return 0; ");
          fprintf(fp, " }\n");
          fprintf(fp,"  virtual jdouble        constantD() const {");
          fprintf(fp,   " return _c0;");
          fprintf(fp, " }\n");
        }
      }
      else if (oper->_interface->is_RegInterface() != NULL) {
        if (oper->_format->_strings.count() != 0 && !oper->is_bound_register()) {
          syntax_err(oper->_linenum,
                     "Only bound registers can have fixed formats: %s\n",
                     oper->_ident);
        }
      }
      else {
        assert( false, "ShouldNotReachHere();");
      }
    }
    fprintf(fp,"\n");
    fprintf(fp, "#ifndef PRODUCT\n");
    gen_oper_format(fp, _globalNames, *oper);
    uint num_consts = oper->num_consts(_globalNames);
    if( num_consts > 0 ) {
      fprintf(fp, "  virtual void           dump_spec(outputStream *st) const {\n");
      uint i = 0;
      const char *type = oper->ideal_type(_globalNames);
      Component  *comp;
      oper->_components.reset();
      if ((comp = oper->_components.iter()) == NULL) {
        assert(num_consts == 1, "Bad component list detected.\n");
        i = dump_spec_constant( fp, type, i, oper );
        assert( i != 0, "Non-constant operand lacks component list.");
      } // end if NULL
      else {
        oper->_components.reset();
        while((comp = oper->_components.iter()) != NULL) {
          type = comp->base_type(_globalNames);
          i = dump_spec_constant( fp, type, i, NULL );
        }
      }
      fprintf(fp,"  }\n");
    }
    fprintf(fp,"  virtual const char    *Name() const { return \"%s\";}\n",
            oper->_ident);
    fprintf(fp,"#endif\n");
    fprintf(fp,"};\n");
  }
  fprintf(fp,"\n");
  fprintf(fp,"//----------------------------Declare classes for Pipelines-----------------\n");
  declare_pipe_classes(fp);
  fprintf(fp,"\n");
  fprintf(fp,"//----------------------------Declare classes derived from MachNode----------\n");
  _instructions.reset();
  InstructForm *instr;
  for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) {
    if ( instr->ideal_only() ) continue;
    fprintf(fp,"\n");
    fprintf(fp,"class %sNode : public %s { \n",
            instr->_ident, instr->mach_base_class(_globalNames) );
    fprintf(fp,"private:\n");
    fprintf(fp,"  MachOper *_opnd_array[%d];\n", instr->num_opnds() );
    if ( instr->is_ideal_jump() ) {
      fprintf(fp, "  GrowableArray<Label*> _index2label;\n");
    }
    fprintf(fp, "public:\n");
    Attribute *att = instr->_attribs;
    while (att != NULL) {
      if (strncmp(att->_ident, "ins_field_", 10) == 0) {
        const char *field_name = att->_ident+10;
        const char *field_type = att->_val;
        fprintf(fp, "  %s _%s;\n", field_type, field_name);
      }
      att = (Attribute *)att->_next;
    }
    fprintf(fp,"  MachOper *opnd_array(uint operand_index) const {\n");
    fprintf(fp,"    assert(operand_index < _num_opnds, \"invalid _opnd_array index\");\n");
    fprintf(fp,"    return _opnd_array[operand_index];\n");
    fprintf(fp,"  }\n");
    fprintf(fp,"  void      set_opnd_array(uint operand_index, MachOper *operand) {\n");
    fprintf(fp,"    assert(operand_index < _num_opnds, \"invalid _opnd_array index\");\n");
    fprintf(fp,"    _opnd_array[operand_index] = operand;\n");
    fprintf(fp,"  }\n");
    fprintf(fp,"private:\n");
    if ( instr->is_ideal_jump() ) {
      fprintf(fp,"  virtual void           add_case_label(int index_num, Label* blockLabel) {\n");
      fprintf(fp,"    _index2label.at_put_grow(index_num, blockLabel);\n");
      fprintf(fp,"  }\n");
    }
    if( can_cisc_spill() && (instr->cisc_spill_alternate() != NULL) ) {
      fprintf(fp,"  const RegMask  *_cisc_RegMask;\n");
    }
    out_RegMask(fp);                      // output register mask
    fprintf(fp,"  virtual uint           rule() const { return %s_rule; }\n",
            instr->_ident);
    int label_position = instr->label_position();
    if( label_position != -1 ) {
      fprintf(fp,"  virtual void           label_set( Label* label, uint block_num );\n");
      fprintf(fp,"  virtual void           save_label( Label** label, uint* block_num );\n");
    }
    int method_position = instr->method_position();
    if( method_position != -1 ) {
      fprintf(fp,"  virtual void           method_set( intptr_t method );\n");
    }
    Attribute *attr = instr->_attribs;
    Attribute *avoid_back_to_back_attr = NULL;
    while (attr != NULL) {
      if (strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") == 0) {
        fprintf(fp, "  virtual bool           is_TrapBasedCheckNode() const { return %s; }\n", attr->_val);
      } else if (strcmp (attr->_ident, "ins_cost") != 0 &&
          strncmp(attr->_ident, "ins_field_", 10) != 0 &&
          strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") != 0 &&
          strcmp (attr->_ident, "ins_short_branch") != 0) {
        fprintf(fp, "  virtual int            %s() const { return %s; }\n", attr->_ident, attr->_val);
      }
      if (strcmp(attr->_ident, "ins_avoid_back_to_back") == 0) {
        avoid_back_to_back_attr = attr;
      }
      attr = (Attribute *)attr->_next;
    }
    if (instr->is_mach_constant()) {
      fprintf(fp,"  virtual void           eval_constant(Compile* C);\n");
    }
    if ( instr->_insencode ) {
      if (instr->postalloc_expands()) {
        fprintf(fp,"  virtual bool           requires_postalloc_expand() const { return true; }\n");
        fprintf(fp,"  virtual void           postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_);\n");
      } else {
        fprintf(fp,"  virtual void           emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const;\n");
      }
    }
    if ( instr->_size ) {
      fprintf(fp,"  virtual uint           size(PhaseRegAlloc *ra_) const;\n");
    }
    if ( strcmp("Node", instr->ideal_Opcode(_globalNames)) != 0 ||
         strcmp("MachNode", instr->mach_base_class(_globalNames)) != 0 ) {
      fprintf(fp,"  virtual int            ideal_Opcode() const { return Op_%s; }\n",
            instr->ideal_Opcode(_globalNames) );
    }
    if (instr->needs_constant_base() &&
        !instr->is_mach_constant()) {  // These inherit the funcion from MachConstantNode.
      fprintf(fp,"  virtual uint           mach_constant_base_node_input() const { ");
      if (instr->is_ideal_call() != Form::invalid_type &&
          instr->is_ideal_call() != Form::JAVA_LEAF) {
        fprintf(fp,"assert(tf() && tf()->domain(), \"\"); return tf()->domain()->cnt();");
      } else {
        fprintf(fp,"return req()-1;");
      }
      fprintf(fp," }\n");
    }
    if( instr->is_ideal_if() ) {
      fprintf(fp,"  virtual void           negate() { \n");
      int   idx = 0;
      instr->_components.reset();
      for( Component *comp; (comp = instr->_components.iter()) != NULL; ) {
        Form *form = (Form*)_globalNames[comp->_type];
        OperandForm *opForm = form ? form->is_operand() : NULL;
        if( opForm == NULL ) continue;
        if( opForm->is_ideal_bool() ) {
          idx = instr->operand_position(comp->_name, comp->_usedef);
          assert( idx != NameList::Not_in_list, "Did not find component in list that contained it.");
          break;
        }
      }
      fprintf(fp,"    opnd_array(%d)->negate();\n", idx);
      fprintf(fp,"    _prob = 1.0f - _prob;\n");
      fprintf(fp,"  };\n");
    }
    uint  matching_input = instr->two_address(_globalNames);
    if( matching_input != 0 ) {
      fprintf(fp,"  virtual uint           two_adr() const  ");
      fprintf(fp,"{ return oper_input_base()");
      for( uint i = 2; i <= matching_input; i++ )
        fprintf(fp," + opnd_array(%d)->num_edges()",i-1);
      fprintf(fp,"; }\n");
    }
    instr->declare_cisc_version(*this, fp);
    if ( instr->peepholes() != NULL ) {
      fprintf(fp,"  virtual MachNode      *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile *C);\n");
    }
    if ( instr->reloc(_globalNames) != 0 ) {
      fprintf(fp,"  virtual int            reloc() const;\n");
    }
    if (instr->alignment() != 1) {
      fprintf(fp,"  virtual int            alignment_required() const { return %d; }\n", instr->alignment());
      fprintf(fp,"  virtual int            compute_padding(int current_offset) const;\n");
    }
    if ( instr->oper_input_base(_globalNames) != 1 ||
         strcmp("MachNode", instr->mach_base_class(_globalNames)) != 0 ) {
      fprintf(fp,"  virtual uint           oper_input_base() const { return %d; }\n",
            instr->oper_input_base(_globalNames));
    }
    fprintf(fp,"public:\n");
    if ( instr->is_ideal_jump() ) {
      fprintf(fp,"  %sNode() : _index2label(MinJumpTableSize*2) { ", instr->_ident);
    } else {
      fprintf(fp,"  %sNode() { ", instr->_ident);
      if( can_cisc_spill() && (instr->cisc_spill_alternate() != NULL) ) {
        fprintf(fp,"_cisc_RegMask = NULL; ");
      }
    }
    fprintf(fp," _num_opnds = %d; _opnds = _opnd_array; ", instr->num_opnds());
    bool node_flags_set = false;
    if ( instr->is_ideal_copy() != 0 ) {
      fprintf(fp,"init_flags(Flag_is_Copy");
      node_flags_set = true;
    }
    Form::DataType  data_type;
    const char     *opType = NULL;
    const char     *result = NULL;
    data_type    = instr->is_chain_of_constant(_globalNames, opType, result);
    if ( data_type != Form::none ) {
      if ( node_flags_set ) {
        fprintf(fp," | Flag_is_Con");
      } else {
        fprintf(fp,"init_flags(Flag_is_Con");
        node_flags_set = true;
      }
    }
    if ( can_cisc_spill() && instr->is_cisc_alternate() ) {
      if ( node_flags_set ) {
        fprintf(fp," | Flag_is_cisc_alternate");
      } else {
        fprintf(fp,"init_flags(Flag_is_cisc_alternate");
        node_flags_set = true;
      }
    }
    if ( instr->has_short_branch_form() ) {
      if ( node_flags_set ) {
        fprintf(fp," | Flag_may_be_short_branch");
      } else {
        fprintf(fp,"init_flags(Flag_may_be_short_branch");
        node_flags_set = true;
      }
    }
    if (avoid_back_to_back_attr != NULL) {
      if (node_flags_set) {
        fprintf(fp," | (%s)", avoid_back_to_back_attr->_val);
      } else {
        fprintf(fp,"init_flags((%s)", avoid_back_to_back_attr->_val);
        node_flags_set = true;
      }
    }
    if ( instr->needs_anti_dependence_check(_globalNames) ) {
      if ( node_flags_set ) {
        fprintf(fp," | Flag_needs_anti_dependence_check");
      } else {
        fprintf(fp,"init_flags(Flag_needs_anti_dependence_check");
        node_flags_set = true;
      }
    }
    if ( instr->_has_call ) {
      if ( node_flags_set ) {
        fprintf(fp," | Flag_has_call");
      } else {
        fprintf(fp,"init_flags(Flag_has_call");
        node_flags_set = true;
      }
    }
    if ( node_flags_set ) {
      fprintf(fp,"); ");
    }
    fprintf(fp,"}\n");
    fprintf(fp,"  virtual uint           size_of() const {");
    fprintf(fp,   " return sizeof(%sNode);", instr->_ident);
    fprintf(fp, " }\n");
    if( instr->expands() || instr->needs_projections() ||
        instr->has_temps() ||
        instr->is_mach_constant() ||
        instr->needs_constant_base() ||
        instr->_matrule != NULL &&
        instr->num_opnds() != instr->num_unique_opnds() ) {
      fprintf(fp,"  virtual MachNode      *Expand(State *state, Node_List &proj_list, Node* mem);\n");
    }
    if (instr->is_pinned(_globalNames)) {
      fprintf(fp,"  virtual bool           pinned() const { return ");
      if (instr->is_parm(_globalNames)) {
        fprintf(fp,"_in[0]->pinned();");
      } else {
        fprintf(fp,"true;");
      }
      fprintf(fp," }\n");
    }
    if (instr->is_projection(_globalNames)) {
      fprintf(fp,"  virtual const Node *is_block_proj() const { return this; }\n");
    }
    if ( instr->num_post_match_opnds() != 0
         || instr->is_chain_of_constant(_globalNames) ) {
      fprintf(fp,"  friend MachNode *State::MachNodeGenerator(int opcode, Compile* C);\n");
    }
    if ( instr->rematerialize(_globalNames, get_registers()) ) {
      fprintf(fp,"  // Rematerialize %s\n", instr->_ident);
    }
    instr->declare_short_branch_methods(fp);
    if (instr->_ins_pipe) {
      fprintf(fp,"  static  const Pipeline *pipeline_class();\n");
      fprintf(fp,"  virtual const Pipeline *pipeline() const;\n");
    }
    if( data_type != Form::none ) {
      fprintf(fp,"  virtual const class Type *bottom_type() const {\n");
      switch( data_type ) {
      case Form::idealI:
        fprintf(fp,"    return  TypeInt::make(opnd_array(1)->constant());\n");
        break;
      case Form::idealP:
      case Form::idealN:
      case Form::idealNKlass:
        fprintf(fp,"    return  opnd_array(1)->type();\n");
        break;
      case Form::idealD:
        fprintf(fp,"    return  TypeD::make(opnd_array(1)->constantD());\n");
        break;
      case Form::idealF:
        fprintf(fp,"    return  TypeF::make(opnd_array(1)->constantF());\n");
        break;
      case Form::idealL:
        fprintf(fp,"    return  TypeLong::make(opnd_array(1)->constantL());\n");
        break;
      default:
        assert( false, "Unimplemented()" );
        break;
      }
      fprintf(fp,"  };\n");
    }
        (  strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0
        || strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) {
      fprintf(fp,"  virtual const class Type *bottom_type() const {");
      fprintf(fp,   " return  TypeInt::INT;");
      fprintf(fp, " };\n");
    }*/
    else if( instr->is_ideal_copy() &&
              !strcmp(instr->_matrule->_lChild->_opType,"stackSlotP") ) {
      fprintf(fp,"  const Type            *bottom_type() const { return in(1)->bottom_type(); } // Copy?\n");
    }
    else if( instr->is_ideal_loadPC() ) {
      fprintf(fp,"  const Type            *bottom_type() const { return TypeRawPtr::BOTTOM; } // LoadPC?\n");
    }
    else if( instr->is_ideal_box() ) {
      fprintf(fp,"  const Type            *bottom_type() const { return TypeRawPtr::BOTTOM; } // Box?\n");
    }
    else if( instr->_matrule && instr->_matrule->_rChild && !strcmp(instr->_matrule->_rChild->_opType,"CMoveP") ) {
      int offset = 1;
      MatchNode *rl = instr->_matrule->_rChild->_lChild;
      if( rl && !strcmp(rl->_opType, "Binary") ) {
          MatchNode *rlr = rl->_rChild;
          if (rlr && strncmp(rlr->_opType, "Cmp", 3) == 0)
            offset = 2;
      }
      fprintf(fp,"  const Type            *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveP\n",
        offset, offset+1, offset+1);
    }
    else if( instr->_matrule && instr->_matrule->_rChild && !strcmp(instr->_matrule->_rChild->_opType,"CMoveN") ) {
      int offset = 1;
      MatchNode *rl = instr->_matrule->_rChild->_lChild;
      if( rl && !strcmp(rl->_opType, "Binary") ) {
          MatchNode *rlr = rl->_rChild;
          if (rlr && strncmp(rlr->_opType, "Cmp", 3) == 0)
            offset = 2;
      }
      fprintf(fp,"  const Type            *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveN\n",
        offset, offset+1, offset+1);
    }
    else if (instr->is_tls_instruction()) {
      fprintf(fp,"  const Type            *bottom_type() const { return TypeRawPtr::BOTTOM; } // tlsLoadP\n");
    }
    else if ( instr->is_ideal_if() ) {
      fprintf(fp,"  const Type            *bottom_type() const { return TypeTuple::IFBOTH; } // matched IfNode\n");
    }
    else if ( instr->is_ideal_membar() ) {
      fprintf(fp,"  const Type            *bottom_type() const { return TypeTuple::MEMBAR; } // matched MemBar\n");
    }
    if ( instr->_matrule && instr->_matrule->_rChild &&
        (  strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0
        || strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) {
      fprintf(fp,"  virtual uint           ideal_reg() const { return Compile::current()->matcher()->base2reg[Type::Int]; }\n");
    }*/
    int memory_operand = instr->memory_operand(_globalNames);
    if ( instr->is_wide_memory_kill(_globalNames) ) {
      memory_operand = InstructForm::MANY_MEMORY_OPERANDS;
    }
    if ( memory_operand != InstructForm::NO_MEMORY_OPERAND ) {
      if( memory_operand == InstructForm::MANY_MEMORY_OPERANDS ) {
        fprintf(fp,"  virtual const TypePtr *adr_type() const;\n");
      }
      fprintf(fp,"  virtual const MachOper *memory_operand() const;\n");
    }
    fprintf(fp, "#ifndef PRODUCT\n");
    gen_inst_format(fp, _globalNames,*instr);
    fprintf(fp,"  virtual const char    *Name() const { return \"%s\";}\n",
            instr->_ident);
    fprintf(fp, "#endif\n");
    fprintf(fp,"};\n");
  };
}
void ArchDesc::defineStateClass(FILE *fp) {
  static const char *state__valid    = "_valid[((uint)index) >> 5] &  (0x1 << (((uint)index) & 0x0001F))";
  static const char *state__set_valid= "_valid[((uint)index) >> 5] |= (0x1 << (((uint)index) & 0x0001F))";
  fprintf(fp,"\n");
  fprintf(fp,"// MACROS to inline and constant fold State::valid(index)...\n");
  fprintf(fp,"// when given a constant 'index' in dfa_<arch>.cpp\n");
  fprintf(fp,"//   uint word   = index >> 5;       // Shift out bit position\n");
  fprintf(fp,"//   uint bitpos = index & 0x0001F;  // Mask off word bits\n");
  fprintf(fp,"#define STATE__VALID(index) ");
  fprintf(fp,"    (%s)\n", state__valid);
  fprintf(fp,"\n");
  fprintf(fp,"#define STATE__NOT_YET_VALID(index) ");
  fprintf(fp,"  ( (%s) == 0 )\n", state__valid);
  fprintf(fp,"\n");
  fprintf(fp,"#define STATE__VALID_CHILD(state,index) ");
  fprintf(fp,"  ( state && (state->%s) )\n", state__valid);
  fprintf(fp,"\n");
  fprintf(fp,"#define STATE__SET_VALID(index) ");
  fprintf(fp,"  (%s)\n", state__set_valid);
  fprintf(fp,"\n");
  fprintf(fp,
          "//---------------------------State-------------------------------------------\n");
  fprintf(fp,"// State contains an integral cost vector, indexed by machine operand opcodes,\n");
  fprintf(fp,"// a rule vector consisting of machine operand/instruction opcodes, and also\n");
  fprintf(fp,"// indexed by machine operand opcodes, pointers to the children in the label\n");
  fprintf(fp,"// tree generated by the Label routines in ideal nodes (currently limited to\n");
  fprintf(fp,"// two for convenience, but this could change).\n");
  fprintf(fp,"class State : public ResourceObj {\n");
  fprintf(fp,"public:\n");
  fprintf(fp,"  int    _id;         // State identifier\n");
  fprintf(fp,"  Node  *_leaf;       // Ideal (non-machine-node) leaf of match tree\n");
  fprintf(fp,"  State *_kids[2];       // Children of state node in label tree\n");
  fprintf(fp,"  unsigned int _cost[_LAST_MACH_OPER];  // Cost vector, indexed by operand opcodes\n");
  fprintf(fp,"  unsigned int _rule[_LAST_MACH_OPER];  // Rule vector, indexed by operand opcodes\n");
  fprintf(fp,"  unsigned int _valid[(_LAST_MACH_OPER/32)+1]; // Bit Map of valid Cost/Rule entries\n");
  fprintf(fp,"\n");
  fprintf(fp,"  State(void);                      // Constructor\n");
  fprintf(fp,"  DEBUG_ONLY( ~State(void); )       // Destructor\n");
  fprintf(fp,"\n");
  fprintf(fp,"  // Methods created by ADLC and invoked by Reduce\n");
  fprintf(fp,"  MachOper *MachOperGenerator( int opcode, Compile* C );\n");
  fprintf(fp,"  MachNode *MachNodeGenerator( int opcode, Compile* C );\n");
  fprintf(fp,"\n");
  fprintf(fp,"  // Assign a state to a node, definition of method produced by ADLC\n");
  fprintf(fp,"  bool DFA( int opcode, const Node *ideal );\n");
  fprintf(fp,"\n");
  fprintf(fp,"  // Access function for _valid bit vector\n");
  fprintf(fp,"  bool valid(uint index) {\n");
  fprintf(fp,"    return( STATE__VALID(index) != 0 );\n");
  fprintf(fp,"  }\n");
  fprintf(fp,"\n");
  fprintf(fp,"  // Set function for _valid bit vector\n");
  fprintf(fp,"  void set_valid(uint index) {\n");
  fprintf(fp,"    STATE__SET_VALID(index);\n");
  fprintf(fp,"  }\n");
  fprintf(fp,"\n");
  fprintf(fp,"#ifndef PRODUCT\n");
  fprintf(fp,"  void dump();                // Debugging prints\n");
  fprintf(fp,"  void dump(int depth);\n");
  fprintf(fp,"#endif\n");
  if (_dfa_small) {
    for (int i = 1; i < _last_opcode; i++) {
      if (_mlistab[i] == NULL) continue;
      fprintf(fp, "  void  _sub_Op_%s(const Node *n);\n", NodeClassNames[i]);
    }
  }
  fprintf(fp,"};\n");
  fprintf(fp,"\n");
  fprintf(fp,"\n");
}
class OutputMachOperands : public OutputMap {
public:
  OutputMachOperands(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
    : OutputMap(hpp, cpp, globals, AD, "MachOperands") {};
  void declaration() { }
  void definition()  { fprintf(_cpp, "enum MachOperands {\n"); }
  void closing()     { fprintf(_cpp, "  _LAST_MACH_OPER\n");
                       OutputMap::closing();
  }
  void map(OpClassForm &opc)  {
    const char* opc_ident_to_upper = _AD.machOperEnum(opc._ident);
    fprintf(_cpp, "  %s", opc_ident_to_upper);
    delete[] opc_ident_to_upper;
  }
  void map(OperandForm &oper) {
    const char* oper_ident_to_upper = _AD.machOperEnum(oper._ident);
    fprintf(_cpp, "  %s", oper_ident_to_upper);
    delete[] oper_ident_to_upper;
  }
  void map(char *name) {
    const char* name_to_upper = _AD.machOperEnum(name);
    fprintf(_cpp, "  %s", name_to_upper);
    delete[] name_to_upper;
  }
  bool do_instructions()      { return false; }
  void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); }
};
void ArchDesc::buildMachOperEnum(FILE *fp_hpp) {
  OutputMachOperands output_mach_operands(fp_hpp, fp_hpp, _globalNames, *this);
  build_map(output_mach_operands);
}
class OutputMachOpcodes : public OutputMap {
  int begin_inst_chain_rule;
  int end_inst_chain_rule;
  int begin_rematerialize;
  int end_rematerialize;
  int end_instructions;
public:
  OutputMachOpcodes(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
    : OutputMap(hpp, cpp, globals, AD, "MachOpcodes"),
      begin_inst_chain_rule(-1), end_inst_chain_rule(-1),
      begin_rematerialize(-1), end_rematerialize(-1),
      end_instructions(-1)
  {};
  void declaration() { }
  void definition()  { fprintf(_cpp, "enum MachOpcodes {\n"); }
  void closing()     {
    if( begin_inst_chain_rule != -1 )
      fprintf(_cpp, "  _BEGIN_INST_CHAIN_RULE = %d,\n", begin_inst_chain_rule);
    if( end_inst_chain_rule   != -1 )
      fprintf(_cpp, "  _END_INST_CHAIN_RULE  = %d,\n", end_inst_chain_rule);
    if( begin_rematerialize   != -1 )
      fprintf(_cpp, "  _BEGIN_REMATERIALIZE   = %d,\n", begin_rematerialize);
    if( end_rematerialize     != -1 )
      fprintf(_cpp, "  _END_REMATERIALIZE    = %d,\n", end_rematerialize);
    fprintf(_cpp, "  _last_Mach_Node  = %d \n",  end_instructions);
    OutputMap::closing();
  }
  void map(OpClassForm &opc)  { fprintf(_cpp, "  %s_rule", opc._ident ); }
  void map(OperandForm &oper) { fprintf(_cpp, "  %s_rule", oper._ident ); }
  void map(char        *name) { if (name) fprintf(_cpp, "  %s_rule", name);
                                else      fprintf(_cpp, "  0"); }
  void map(InstructForm &inst) {fprintf(_cpp, "  %s_rule", inst._ident ); }
  void record_position(OutputMap::position place, int idx ) {
    switch(place) {
    case OutputMap::BEGIN_INST_CHAIN_RULES :
      begin_inst_chain_rule = idx;
      break;
    case OutputMap::END_INST_CHAIN_RULES :
      end_inst_chain_rule   = idx;
      break;
    case OutputMap::BEGIN_REMATERIALIZE :
      begin_rematerialize   = idx;
      break;
    case OutputMap::END_REMATERIALIZE :
      end_rematerialize     = idx;
      break;
    case OutputMap::END_INSTRUCTIONS :
      end_instructions      = idx;
      break;
    default:
      break;
    }
  }
};
void ArchDesc::buildMachOpcodesEnum(FILE *fp_hpp) {
  OutputMachOpcodes output_mach_opcodes(fp_hpp, fp_hpp, _globalNames, *this);
  build_map(output_mach_opcodes);
}
void ArchDesc::build_pipeline_enums(FILE *fp_hpp) {
  int stagelen = (int)strlen("undefined");
  int stagenum = 0;
  if (_pipeline) {              // Find max enum string length
    const char *stage;
    for ( _pipeline->_stages.reset(); (stage = _pipeline->_stages.iter()) != NULL; ) {
      int len = (int)strlen(stage);
      if (stagelen < len) stagelen = len;
    }
  }
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "// Pipeline Stages\n");
  fprintf(fp_hpp, "enum machPipelineStages {\n");
  fprintf(fp_hpp, "   stage_%-*s = 0,\n", stagelen, "undefined");
  if( _pipeline ) {
    const char *stage;
    for ( _pipeline->_stages.reset(); (stage = _pipeline->_stages.iter()) != NULL; )
      fprintf(fp_hpp, "   stage_%-*s = %d,\n", stagelen, stage, ++stagenum);
  }
  fprintf(fp_hpp, "   stage_%-*s = %d\n", stagelen, "count", stagenum);
  fprintf(fp_hpp, "};\n");
  fprintf(fp_hpp, "\n");
  fprintf(fp_hpp, "// Pipeline Resources\n");
  fprintf(fp_hpp, "enum machPipelineResources {\n");
  int rescount = 0;
  if( _pipeline ) {
    const char *resource;
    int reslen = 0;
    for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) {
      int len = (int)strlen(resource);
      if (reslen < len)
        reslen = len;
    }
    for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) {
      const ResourceForm *resform = _pipeline->_resdict[resource]->is_resource();
      int mask = resform->mask();
      if ((mask & (mask-1)) == 0)
        fprintf(fp_hpp, "   resource_%-*s = %d,\n", reslen, resource, rescount++);
    }
    fprintf(fp_hpp, "\n");
    for ( _pipeline->_reslist.reset(); (resource = _pipeline->_reslist.iter()) != NULL; ) {
      const ResourceForm *resform = _pipeline->_resdict[resource]->is_resource();
      fprintf(fp_hpp, "   res_mask_%-*s = 0x%08x,\n", reslen, resource, resform->mask());
    }
    fprintf(fp_hpp, "\n");
  }
  fprintf(fp_hpp, "   resource_count = %d\n", rescount);
  fprintf(fp_hpp, "};\n");
}
C:\hotspot-69087d08d473\src\share\vm/asm/assembler.cpp
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "asm/codeBuffer.hpp"
#include "runtime/atomic.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/icache.hpp"
#include "runtime/os.hpp"
AbstractAssembler::AbstractAssembler(CodeBuffer* code) {
  if (code == NULL)  return;
  CodeSection* cs = code->insts();
  cs->clear_mark();   // new assembler kills old mark
  if (cs->start() == NULL)  {
    vm_exit_out_of_memory(0, OOM_MMAP_ERROR, err_msg("CodeCache: no room for %s",
                                     code->name()));
  }
  _code_section = cs;
  _oop_recorder= code->oop_recorder();
  DEBUG_ONLY( _short_branch_delta = 0; )
}
void AbstractAssembler::set_code_section(CodeSection* cs) {
  assert(cs->outer() == code_section()->outer(), "sanity");
  assert(cs->is_allocated(), "need to pre-allocate this section");
  cs->clear_mark();  // new assembly into this section kills old mark
  _code_section = cs;
}
address AbstractAssembler::start_a_stub(int required_space) {
  CodeBuffer*  cb = code();
  CodeSection* cs = cb->stubs();
  assert(_code_section == cb->insts(), "not in insts?");
  if (cs->maybe_expand_to_ensure_remaining(required_space)
      && cb->blob() == NULL) {
    return NULL;
  }
  set_code_section(cs);
  return pc();
}
void AbstractAssembler::end_a_stub() {
  assert(_code_section == code()->stubs(), "not in stubs?");
  set_code_section(code()->insts());
}
address AbstractAssembler::start_a_const(int required_space, int required_align) {
  CodeBuffer*  cb = code();
  CodeSection* cs = cb->consts();
  assert(_code_section == cb->insts() || _code_section == cb->stubs(), "not in insts/stubs?");
  address end = cs->end();
  int pad = -(intptr_t)end & (required_align-1);
  if (cs->maybe_expand_to_ensure_remaining(pad + required_space)) {
    if (cb->blob() == NULL)  return NULL;
    end = cs->end();  // refresh pointer
  }
  if (pad > 0) {
    while (--pad >= 0) { *end++ = 0; }
    cs->set_end(end);
  }
  set_code_section(cs);
  return end;
}
void AbstractAssembler::end_a_const(CodeSection* cs) {
  assert(_code_section == code()->consts(), "not in consts?");
  set_code_section(cs);
}
void AbstractAssembler::flush() {
  ICache::invalidate_range(addr_at(0), offset());
}
void AbstractAssembler::bind(Label& L) {
  if (L.is_bound()) {
    guarantee(L.loc() == locator(), "attempt to redefine label");
    return;
  }
  L.bind_loc(locator());
  L.patch_instructions((MacroAssembler*)this);
}
void AbstractAssembler::generate_stack_overflow_check( int frame_size_in_bytes) {
  if (UseStackBanging) {
    const int page_size = os::vm_page_size();
    int bang_end = StackShadowPages*page_size;
    const int bang_end_safe = bang_end;
    if (frame_size_in_bytes > page_size) {
      bang_end += frame_size_in_bytes;
    }
    int bang_offset = bang_end_safe;
    while (bang_offset <= bang_end) {
      bang_stack_with_offset(bang_offset);
      bang_offset += page_size;
    }
  } // end (UseStackBanging)
}
void Label::add_patch_at(CodeBuffer* cb, int branch_loc) {
  assert(_loc == -1, "Label is unbound");
  if (_patch_index < PatchCacheSize) {
    _patches[_patch_index] = branch_loc;
  } else {
    if (_patch_overflow == NULL) {
      _patch_overflow = cb->create_patch_overflow();
    }
    _patch_overflow->push(branch_loc);
  }
  ++_patch_index;
}
void Label::patch_instructions(MacroAssembler* masm) {
  assert(is_bound(), "Label is bound");
  CodeBuffer* cb = masm->code();
  int target_sect = CodeBuffer::locator_sect(loc());
  address target = cb->locator_address(loc());
  while (_patch_index > 0) {
    --_patch_index;
    int branch_loc;
    if (_patch_index >= PatchCacheSize) {
      branch_loc = _patch_overflow->pop();
    } else {
      branch_loc = _patches[_patch_index];
    }
    int branch_sect = CodeBuffer::locator_sect(branch_loc);
    address branch = cb->locator_address(branch_loc);
    if (branch_sect == CodeBuffer::SECT_CONSTS) {
      continue;
    }
#ifdef ASSERT
    if (target_sect != branch_sect) {
      for (int n = MIN2(target_sect, branch_sect),
               nlimit = (target_sect + branch_sect) - n;
           n < nlimit; n++) {
        CodeSection* cs = cb->code_section(n);
        assert(cs->is_frozen(), "cross-section branch needs stable offsets");
      }
    }
#endif //ASSERT
    masm->pd_patch_instruction(branch, target);
  }
}
struct DelayedConstant {
  typedef void (*value_fn_t)();
  BasicType type;
  intptr_t value;
  value_fn_t value_fn;
  enum { DC_LIMIT = 20 };
  static DelayedConstant delayed_constants[DC_LIMIT];
  static DelayedConstant* add(BasicType type, value_fn_t value_fn);
  bool match(BasicType t, value_fn_t cfn) {
    return type == t && value_fn == cfn;
  }
  static void update_all();
};
DelayedConstant DelayedConstant::delayed_constants[DC_LIMIT];
DelayedConstant* DelayedConstant::add(BasicType type,
                                      DelayedConstant::value_fn_t cfn) {
  for (int i = 0; i < DC_LIMIT; i++) {
    DelayedConstant* dcon = &delayed_constants[i];
    if (dcon->match(type, cfn))
      return dcon;
    if (dcon->value_fn == NULL) {
      if (Atomic::cmpxchg_ptr(CAST_FROM_FN_PTR(void*, cfn), &dcon->value_fn, NULL) == NULL) {
        dcon->type = type;
        return dcon;
      }
    }
  }
  guarantee(false, "too many delayed constants");
  return NULL;
}
void DelayedConstant::update_all() {
  for (int i = 0; i < DC_LIMIT; i++) {
    DelayedConstant* dcon = &delayed_constants[i];
    if (dcon->value_fn != NULL && dcon->value == 0) {
      typedef int     (*int_fn_t)();
      typedef address (*address_fn_t)();
      switch (dcon->type) {
      case T_INT:     dcon->value = (intptr_t) ((int_fn_t)    dcon->value_fn)(); break;
      case T_ADDRESS: dcon->value = (intptr_t) ((address_fn_t)dcon->value_fn)(); break;
      }
    }
  }
}
RegisterOrConstant AbstractAssembler::delayed_value(int(*value_fn)(), Register tmp, int offset) {
  intptr_t val = (intptr_t) (*value_fn)();
  if (val != 0)  return val + offset;
  return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
}
RegisterOrConstant AbstractAssembler::delayed_value(address(*value_fn)(), Register tmp, int offset) {
  intptr_t val = (intptr_t) (*value_fn)();
  if (val != 0)  return val + offset;
  return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
}
intptr_t* AbstractAssembler::delayed_value_addr(int(*value_fn)()) {
  DelayedConstant* dcon = DelayedConstant::add(T_INT, (DelayedConstant::value_fn_t) value_fn);
  return &dcon->value;
}
intptr_t* AbstractAssembler::delayed_value_addr(address(*value_fn)()) {
  DelayedConstant* dcon = DelayedConstant::add(T_ADDRESS, (DelayedConstant::value_fn_t) value_fn);
  return &dcon->value;
}
void AbstractAssembler::update_delayed_values() {
  DelayedConstant::update_all();
}
void AbstractAssembler::block_comment(const char* comment) {
  if (sect() == CodeBuffer::SECT_INSTS) {
    code_section()->outer()->block_comment(offset(), comment);
  }
}
const char* AbstractAssembler::code_string(const char* str) {
  if (sect() == CodeBuffer::SECT_INSTS || sect() == CodeBuffer::SECT_STUBS) {
    return code_section()->outer()->code_string(str);
  }
  return NULL;
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
#ifdef _LP64
  if (UseCompressedOops && Universe::narrow_oop_base() != NULL) {
    assert (Universe::heap() != NULL, "java heap should be initialized");
    uintptr_t base = (uintptr_t)Universe::narrow_oop_base();
    if ((uintptr_t)offset >= base) {
      offset = (intptr_t)(pointer_delta((void*)offset, (void*)base, 1));
    }
  }
#endif
  return offset < 0 || os::vm_page_size() <= offset;
}
C:\hotspot-69087d08d473\src\share\vm/asm/assembler.hpp
#ifndef SHARE_VM_ASM_ASSEMBLER_HPP
#define SHARE_VM_ASM_ASSEMBLER_HPP
#include "asm/codeBuffer.hpp"
#include "code/oopRecorder.hpp"
#include "code/relocInfo.hpp"
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/top.hpp"
#ifdef TARGET_ARCH_x86
# include "register_x86.hpp"
# include "vm_version_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "register_sparc.hpp"
# include "vm_version_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "register_zero.hpp"
# include "vm_version_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "register_arm.hpp"
# include "vm_version_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "register_ppc.hpp"
# include "vm_version_ppc.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "register_aarch64.hpp"
# include "vm_version_aarch64.hpp"
#endif
class MacroAssembler;
class AbstractAssembler;
class Label;
class Label VALUE_OBJ_CLASS_SPEC {
 private:
  enum { PatchCacheSize = 4 };
  int _loc;
  int _patches[PatchCacheSize];
  int _patch_index;
  GrowableArray<int>* _patch_overflow;
  Label(const Label&) { ShouldNotReachHere(); }
 public:
  void bind_loc(int loc) {
    assert(loc >= 0, "illegal locator");
    assert(_loc == -1, "already bound");
    _loc = loc;
  }
  void bind_loc(int pos, int sect) { bind_loc(CodeBuffer::locator(pos, sect)); }
#ifndef PRODUCT
  void print_instructions(MacroAssembler* masm) const;
#endif // PRODUCT
  int loc() const {
    assert(_loc >= 0, "unbound label");
    return _loc;
  }
  int loc_pos()  const { return CodeBuffer::locator_pos(loc()); }
  int loc_sect() const { return CodeBuffer::locator_sect(loc()); }
  bool is_bound() const    { return _loc >=  0; }
  bool is_unbound() const  { return _loc == -1 && _patch_index > 0; }
  bool is_unused() const   { return _loc == -1 && _patch_index == 0; }
  void add_patch_at(CodeBuffer* cb, int branch_loc);
  void patch_instructions(MacroAssembler* masm);
  void init() {
    _loc = -1;
    _patch_index = 0;
    _patch_overflow = NULL;
  }
  Label() {
    init();
  }
  ~Label() {
    assert(is_bound() || is_unused(), "Label was never bound to a location, but it was used as a jmp target");
  }
  void reset() {
    init(); //leave _patch_overflow because it points to CodeBuffer.
  }
};
class RegisterOrConstant VALUE_OBJ_CLASS_SPEC {
 private:
  Register _r;
  intptr_t _c;
 public:
  RegisterOrConstant(): _r(noreg), _c(0) {}
  RegisterOrConstant(Register r): _r(r), _c(0) {}
  RegisterOrConstant(intptr_t c): _r(noreg), _c(c) {}
  Register as_register() const { assert(is_register(),""); return _r; }
  intptr_t as_constant() const { assert(is_constant(),""); return _c; }
  Register register_or_noreg() const { return _r; }
  intptr_t constant_or_zero() const  { return _c; }
  bool is_register() const { return _r != noreg; }
  bool is_constant() const { return _r == noreg; }
};
class AbstractAssembler : public ResourceObj  {
  friend class Label;
 protected:
  CodeSection* _code_section;          // section within the code buffer
  OopRecorder* _oop_recorder;          // support for relocInfo::oop_type
 public:
  address addr_at(int pos) const { return code_section()->start() + pos; }
 protected:
  address target(Label& L)             { return code_section()->target(L, pc()); }
  bool is8bit(int x) const             { return -0x80 <= x && x < 0x80; }
  bool isByte(int x) const             { return 0 <= x && x < 0x100; }
  bool isShiftCount(int x) const       { return 0 <= x && x < 32; }
  class InstructionMark: public StackObj {
   private:
    AbstractAssembler* _assm;
   public:
    InstructionMark(AbstractAssembler* assm) : _assm(assm) {
      assert(assm->inst_mark() == NULL, "overlapping instructions");
      _assm->set_inst_mark();
    }
    ~InstructionMark() {
      _assm->clear_inst_mark();
    }
  };
  friend class InstructionMark;
#ifdef ASSERT
  static bool pd_check_instruction_mark();
  int _short_branch_delta;
  int  short_branch_delta() const { return _short_branch_delta; }
  void set_short_branch_delta()   { _short_branch_delta = 32; }
  void clear_short_branch_delta() { _short_branch_delta = 0; }
  class ShortBranchVerifier: public StackObj {
   private:
    AbstractAssembler* _assm;
   public:
    ShortBranchVerifier(AbstractAssembler* assm) : _assm(assm) {
      assert(assm->short_branch_delta() == 0, "overlapping instructions");
      _assm->set_short_branch_delta();
    }
    ~ShortBranchVerifier() {
      _assm->clear_short_branch_delta();
    }
  };
#else
  class ShortBranchVerifier: public StackObj {
   public:
    ShortBranchVerifier(AbstractAssembler* assm) {}
  };
#endif
 public:
  AbstractAssembler(CodeBuffer* code);
  void flush();
  void emit_int8(   int8_t  x) { code_section()->emit_int8(   x); }
  void emit_int16(  int16_t x) { code_section()->emit_int16(  x); }
  void emit_int32(  int32_t x) { code_section()->emit_int32(  x); }
  void emit_int64(  int64_t x) { code_section()->emit_int64(  x); }
  void emit_float(  jfloat  x) { code_section()->emit_float(  x); }
  void emit_double( jdouble x) { code_section()->emit_double( x); }
  void emit_address(address x) { code_section()->emit_address(x); }
  enum { min_simm10 = -512 };
  static bool is_simm(int64_t x, uint w) {
    precond(1 < w && w < 64);
    int64_t limes = INT64_C(1) << (w - 1);
    return -limes <= x && x < limes;
  }
  static bool is_simm8(int64_t x) { return is_simm(x, 8); }
  static bool is_simm9(int64_t x) { return is_simm(x, 9); }
  static bool is_simm10(int64_t x) { return is_simm(x, 10); }
  static bool is_simm16(int64_t x) { return is_simm(x, 16); }
  static bool is_simm32(int64_t x) { return is_simm(x, 32); }
  static bool is_uimm(uint64_t x, uint w) {
    precond(0 < w && w < 64);
    uint64_t limes = UINT64_C(1) << w;
    return x < limes;
  }
  static bool is_uimm12(uint64_t x) { return is_uimm(x, 12); }
  CodeSection*  code_section() const   { return _code_section; }
  CodeBuffer*   code()         const   { return code_section()->outer(); }
  int           sect()         const   { return code_section()->index(); }
  address       pc()           const   { return code_section()->end();   }
  int           offset()       const   { return code_section()->size();  }
  int           locator()      const   { return CodeBuffer::locator(offset(), sect()); }
  OopRecorder*  oop_recorder() const   { return _oop_recorder; }
  void      set_oop_recorder(OopRecorder* r) { _oop_recorder = r; }
  address       inst_mark() const { return code_section()->mark();       }
  void      set_inst_mark()       {        code_section()->set_mark();   }
  void    clear_inst_mark()       {        code_section()->clear_mark(); }
  void relocate(RelocationHolder const& rspec, int format = 0) {
    assert(!pd_check_instruction_mark()
        || inst_mark() == NULL || inst_mark() == code_section()->end(),
        "call relocate() between instructions");
    code_section()->relocate(code_section()->end(), rspec, format);
  }
  void relocate(   relocInfo::relocType rtype, int format = 0) {
    code_section()->relocate(code_section()->end(), rtype, format);
  }
  static int code_fill_byte();         // used to pad out odd-sized code buffers
  void block_comment(const char* comment);
  const char* code_string(const char* str);
  void bind(Label& L); // binds an unbound label L to the current code position
  void set_code_section(CodeSection* cs);
  address    start_a_stub(int required_space);
  void       end_a_stub();
  address    start_a_const(int required_space, int required_align = sizeof(double));
  void       end_a_const(CodeSection* cs);  // Pass the codesection to continue in (insts or stubs?).
  address long_constant(jlong c) {
    CodeSection* c1 = _code_section;
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      emit_int64(c);
      end_a_const(c1);
    }
    return ptr;
  }
  address double_constant(jdouble c) {
    CodeSection* c1 = _code_section;
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      emit_double(c);
      end_a_const(c1);
    }
    return ptr;
  }
  address float_constant(jfloat c) {
    CodeSection* c1 = _code_section;
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      emit_float(c);
      end_a_const(c1);
    }
    return ptr;
  }
  address address_constant(address c) {
    CodeSection* c1 = _code_section;
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      emit_address(c);
      end_a_const(c1);
    }
    return ptr;
  }
  address address_constant(address c, RelocationHolder const& rspec) {
    CodeSection* c1 = _code_section;
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      relocate(rspec);
      emit_address(c);
      end_a_const(c1);
    }
    return ptr;
  }
  RegisterOrConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0);
  RegisterOrConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0);
  virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset) = 0;
  static intptr_t* delayed_value_addr(int(*constant_fn)());
  static intptr_t* delayed_value_addr(address(*constant_fn)());
  static void update_delayed_values();
  void generate_stack_overflow_check( int frame_size_in_bytes );
  virtual void bang_stack_with_offset(int offset) = 0;
  void pd_patch_instruction(address branch, address target);
};
#ifdef TARGET_ARCH_x86
# include "assembler_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "assembler_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "assembler_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "assembler_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "assembler_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "assembler_ppc.hpp"
#endif
#endif // SHARE_VM_ASM_ASSEMBLER_HPP
C:\hotspot-69087d08d473\src\share\vm/asm/assembler.inline.hpp
#ifndef SHARE_VM_ASM_ASSEMBLER_INLINE_HPP
#define SHARE_VM_ASM_ASSEMBLER_INLINE_HPP
#include "asm/assembler.hpp"
#ifdef TARGET_ARCH_x86
# include "assembler_x86.inline.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "assembler_sparc.inline.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "assembler_zero.inline.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "assembler_arm.inline.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "assembler_ppc.inline.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "assembler_aarch64.inline.hpp"
#endif
#endif // SHARE_VM_ASM_ASSEMBLER_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/asm/codeBuffer.cpp
#include "precompiled.hpp"
#include "asm/codeBuffer.hpp"
#include "compiler/disassembler.hpp"
#include "memory/gcLocker.hpp"
#include "oops/methodData.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/copy.hpp"
#include "utilities/xmlstream.hpp"
typedef CodeBuffer::csize_t csize_t;  // file-local definition
CodeBuffer::CodeBuffer(CodeBlob* blob) {
  initialize_misc("static buffer");
  initialize(blob->content_begin(), blob->content_size());
  verify_section_allocation();
}
void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
  int align = _insts.alignment();
  int slop = (int) CodeSection::end_slop();
  assert(blob() == NULL, "only once");
  set_blob(BufferBlob::create(_name, code_size + (align+slop) * (SECT_LIMIT+1)));
  if (blob() == NULL) {
    return;  // caller must test this
  }
  initialize(_total_start, _total_size);
  assert((uintptr_t)insts_begin() % CodeEntryAlignment == 0, "instruction start not code entry aligned");
  pd_initialize();
  if (locs_size != 0) {
    _insts.initialize_locs(locs_size / sizeof(relocInfo));
  }
  verify_section_allocation();
}
CodeBuffer::~CodeBuffer() {
  verify_section_allocation();
  for (CodeBuffer* cb = this; cb != NULL; cb = cb->before_expand()) {
    cb->free_blob();
  }
  delete _overflow_arena;
  free_strings();
#ifdef ASSERT
  assert(_default_oop_recorder.allocated_on_stack(), "should be embedded object");
  ResourceObj::allocation_type at = _default_oop_recorder.get_allocation_type();
  Copy::fill_to_bytes(this, sizeof(*this), badResourceValue);
  ResourceObj::set_allocation_type((address)(&_default_oop_recorder), at);
#endif
}
void CodeBuffer::initialize_oop_recorder(OopRecorder* r) {
  assert(_oop_recorder == &_default_oop_recorder && _default_oop_recorder.is_unused(), "do this once");
  DEBUG_ONLY(_default_oop_recorder.freeze());  // force unused OR to be frozen
  _oop_recorder = r;
}
void CodeBuffer::initialize_section_size(CodeSection* cs, csize_t size) {
  assert(cs != &_insts, "insts is the memory provider, not the consumer");
  csize_t slop = CodeSection::end_slop();  // margin between sections
  int align = cs->alignment();
  assert(is_power_of_2(align), "sanity");
  address start  = _insts._start;
  address limit  = _insts._limit;
  address middle = limit - size;
  middle -= (intptr_t)middle & (align-1);  // align the division point downward
  guarantee(middle - slop > start, "need enough space to divide up");
  _insts._limit = middle - slop;  // subtract desired space, plus slop
  cs->initialize(middle, limit - middle);
  assert(cs->start() == middle, "sanity");
  assert(cs->limit() == limit,  "sanity");
  if (_insts.has_locs())  cs->initialize_locs(1);
}
void CodeBuffer::freeze_section(CodeSection* cs) {
  CodeSection* next_cs = (cs == consts())? NULL: code_section(cs->index()+1);
  csize_t frozen_size = cs->size();
  if (next_cs != NULL) {
    frozen_size = next_cs->align_at_start(frozen_size);
  }
  address old_limit = cs->limit();
  address new_limit = cs->start() + frozen_size;
  relocInfo* old_locs_limit = cs->locs_limit();
  relocInfo* new_locs_limit = cs->locs_end();
  cs->_limit = new_limit;
  cs->_locs_limit = new_locs_limit;
  cs->_frozen = true;
  if (!next_cs->is_allocated() && !next_cs->is_frozen()) {
    next_cs->initialize(new_limit, old_limit - new_limit);
    next_cs->initialize_shared_locs(new_locs_limit,
                                    old_locs_limit - new_locs_limit);
  }
}
void CodeBuffer::set_blob(BufferBlob* blob) {
  _blob = blob;
  if (blob != NULL) {
    address start = blob->content_begin();
    address end   = blob->content_end();
    int align = _insts.alignment();
    start += (-(intptr_t)start) & (align-1);
    _total_start = start;
    _total_size  = end - start;
  } else {
#ifdef ASSERT
    _total_start    = badAddress;
    _consts._start  = _consts._end  = badAddress;
    _insts._start   = _insts._end   = badAddress;
    _stubs._start   = _stubs._end   = badAddress;
#endif //ASSERT
  }
}
void CodeBuffer::free_blob() {
  if (_blob != NULL) {
    BufferBlob::free(_blob);
    set_blob(NULL);
  }
}
const char* CodeBuffer::code_section_name(int n) {
#ifdef PRODUCT
  return NULL;
#else //PRODUCT
  switch (n) {
  case SECT_CONSTS:            return "consts";
  case SECT_INSTS:             return "insts";
  case SECT_STUBS:             return "stubs";
  default:                     return NULL;
  }
#endif //PRODUCT
}
int CodeBuffer::section_index_of(address addr) const {
  for (int n = 0; n < (int)SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    if (cs->allocates(addr))  return n;
  }
  return SECT_NONE;
}
int CodeBuffer::locator(address addr) const {
  for (int n = 0; n < (int)SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    if (cs->allocates(addr)) {
      return locator(addr - cs->start(), n);
    }
  }
  return -1;
}
address CodeBuffer::locator_address(int locator) const {
  if (locator < 0)  return NULL;
  address start = code_section(locator_sect(locator))->start();
  return start + locator_pos(locator);
}
bool CodeBuffer::is_backward_branch(Label& L) {
  return L.is_bound() && insts_end() <= locator_address(L.loc());
}
address CodeBuffer::decode_begin() {
  address begin = _insts.start();
  if (_decode_begin != NULL && _decode_begin > begin)
    begin = _decode_begin;
  return begin;
}
GrowableArray<int>* CodeBuffer::create_patch_overflow() {
  if (_overflow_arena == NULL) {
    _overflow_arena = new (mtCode) Arena(mtCode);
  }
  return new (_overflow_arena) GrowableArray<int>(_overflow_arena, 8, 0, 0);
}
address CodeSection::target(Label& L, address branch_pc) {
  if (L.is_bound()) {
    int loc = L.loc();
    if (index() == CodeBuffer::locator_sect(loc)) {
      return start() + CodeBuffer::locator_pos(loc);
    } else {
      return outer()->locator_address(loc);
    }
  } else {
    assert(allocates2(branch_pc), "sanity");
    address base = start();
    int patch_loc = CodeBuffer::locator(branch_pc - base, index());
    L.add_patch_at(outer(), patch_loc);
    return branch_pc;
  }
}
void CodeSection::relocate(address at, RelocationHolder const& spec, int format) {
  Relocation* reloc = spec.reloc();
  relocInfo::relocType rtype = (relocInfo::relocType) reloc->type();
  if (rtype == relocInfo::none)  return;
  assert(start() <= at && at <= end()+1,
         "cannot relocate data outside code boundaries");
  if (!has_locs()) {
    assert(rtype == relocInfo::none              ||
           rtype == relocInfo::runtime_call_type ||
           rtype == relocInfo::internal_word_type||
           rtype == relocInfo::section_word_type ||
           rtype == relocInfo::external_word_type,
           "code needs relocation information");
    DEBUG_ONLY(_locs_start = _locs_limit = (relocInfo*)badAddress);
    return;
  }
  csize_t offset = at - locs_point();
  set_locs_point(at);
  relocInfo* end = locs_end();
  relocInfo* req = end + relocInfo::length_limit;
  if (req >= locs_limit() || offset >= relocInfo::offset_limit()) {
    req += (uint)offset / (uint)relocInfo::offset_limit();
    if (req >= locs_limit()) {
      expand_locs(locs_count() + (req - end));
      end = locs_end();
    }
  }
  while (offset >= relocInfo::offset_limit()) {
    assert(end < locs_limit(), "adjust previous paragraph of code");
    offset -= filler_relocInfo().addr_offset();
  }
  (*end) = relocInfo(rtype, offset, format);
  end->initialize(this, reloc);
}
void CodeSection::initialize_locs(int locs_capacity) {
  assert(_locs_start == NULL, "only one locs init step, please");
  csize_t min_locs = MAX2(size() / 16, (csize_t)4);
  if (locs_capacity < min_locs)  locs_capacity = min_locs;
  relocInfo* locs_start = NEW_RESOURCE_ARRAY(relocInfo, locs_capacity);
  _locs_start    = locs_start;
  _locs_end      = locs_start;
  _locs_limit    = locs_start + locs_capacity;
  _locs_own      = true;
}
void CodeSection::initialize_shared_locs(relocInfo* buf, int length) {
  assert(_locs_start == NULL, "do this before locs are allocated");
  while ((uintptr_t)buf % HeapWordSize != 0 && length > 0) {
    ++buf; --length;
  }
  if (length > 0) {
    _locs_start = buf;
    _locs_end   = buf;
    _locs_limit = buf + length;
    _locs_own   = false;
  }
}
void CodeSection::initialize_locs_from(const CodeSection* source_cs) {
  int lcount = source_cs->locs_count();
  if (lcount != 0) {
    initialize_shared_locs(source_cs->locs_start(), lcount);
    _locs_end = _locs_limit = _locs_start + lcount;
    assert(is_allocated(), "must have copied code already");
    set_locs_point(start() + source_cs->locs_point_off());
  }
  assert(this->locs_count() == source_cs->locs_count(), "sanity");
}
void CodeSection::expand_locs(int new_capacity) {
  if (_locs_start == NULL) {
    initialize_locs(new_capacity);
    return;
  } else {
    int old_count    = locs_count();
    int old_capacity = locs_capacity();
    if (new_capacity < old_capacity * 2)
      new_capacity = old_capacity * 2;
    relocInfo* locs_start;
    if (_locs_own) {
      locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity);
    } else {
      locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity);
      Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
      _locs_own = true;
    }
    _locs_start    = locs_start;
    _locs_end      = locs_start + old_count;
    _locs_limit    = locs_start + new_capacity;
  }
}
csize_t CodeBuffer::total_content_size() const {
  csize_t size_so_far = 0;
  for (int n = 0; n < (int)SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    if (cs->is_empty())  continue;  // skip trivial section
    size_so_far = cs->align_at_start(size_so_far);
    size_so_far += cs->size();
  }
  return size_so_far;
}
void CodeBuffer::compute_final_layout(CodeBuffer* dest) const {
  address buf = dest->_total_start;
  csize_t buf_offset = 0;
  assert(dest->_total_size >= total_content_size(), "must be big enough");
  {
    int alignSize = MAX2((intx) sizeof(jdouble), CodeEntryAlignment);
    assert( (dest->_total_start - _insts.start()) % alignSize == 0, "copy must preserve alignment");
  }
  const CodeSection* prev_cs      = NULL;
  CodeSection*       prev_dest_cs = NULL;
  for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    csize_t csize = cs->size();
    CodeSection* dest_cs = dest->code_section(n);
    if (!cs->is_empty()) {
      csize_t padding = cs->align_at_start(buf_offset) - buf_offset;
      if (padding != 0) {
        buf_offset += padding;
        assert(prev_dest_cs != NULL, "sanity");
        prev_dest_cs->_limit += padding;
      }
      #ifdef ASSERT
      if (prev_cs != NULL && prev_cs->is_frozen() && n < (SECT_LIMIT - 1)) {
        address dest_start = buf+buf_offset;
        csize_t start2start = cs->start() - prev_cs->start();
        csize_t dest_start2start = dest_start - prev_dest_cs->start();
        assert(start2start == dest_start2start, "cannot stretch frozen sect");
      }
      #endif //ASSERT
      prev_dest_cs = dest_cs;
      prev_cs      = cs;
    }
    debug_only(dest_cs->_start = NULL);  // defeat double-initialization assert
    dest_cs->initialize(buf+buf_offset, csize);
    dest_cs->set_end(buf+buf_offset+csize);
    assert(dest_cs->is_allocated(), "must always be allocated");
    assert(cs->is_empty() == dest_cs->is_empty(), "sanity");
    buf_offset += csize;
  }
  assert(buf_offset == total_content_size(), "sanity");
  dest->verify_section_allocation();
}
static void append_oop_references(GrowableArray<oop>* oops, Klass* k) {
  oop cl = k->klass_holder();
  if (cl != NULL && !oops->contains(cl)) {
    oops->append(cl);
  }
}
void CodeBuffer::finalize_oop_references(methodHandle mh) {
  No_Safepoint_Verifier nsv;
  GrowableArray<oop> oops;
  for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
    CodeSection* cs = code_section(n);
    if (cs->is_empty())  continue;  // skip trivial section
    RelocIterator iter(cs);
    while (iter.next()) {
      if (iter.type() == relocInfo::metadata_type) {
        metadata_Relocation* md = iter.metadata_reloc();
        if (md->metadata_is_immediate()) {
          Metadata* m = md->metadata_value();
          if (oop_recorder()->is_real(m)) {
            if (m->is_methodData()) {
              m = ((MethodData*)m)->method();
            }
            if (m->is_method()) {
              m = ((Method*)m)->method_holder();
            }
            if (m->is_klass()) {
              append_oop_references(&oops, (Klass*)m);
            } else {
              m->print();
              ShouldNotReachHere();
            }
          }
        }
      }
    }
  }
  if (!oop_recorder()->is_unused()) {
    for (int i = 0; i < oop_recorder()->metadata_count(); i++) {
      Metadata* m = oop_recorder()->metadata_at(i);
      if (oop_recorder()->is_real(m)) {
        if (m->is_methodData()) {
          m = ((MethodData*)m)->method();
        }
        if (m->is_method()) {
          m = ((Method*)m)->method_holder();
        }
        if (m->is_klass()) {
          append_oop_references(&oops, (Klass*)m);
        } else {
          m->print();
          ShouldNotReachHere();
        }
      }
    }
  }
  append_oop_references(&oops, mh->method_holder());
  Thread* thread = Thread::current();
  for (int i = 0; i < oops.length(); i++) {
    oop_recorder()->find_index((jobject)thread->handle_area()->allocate_handle(oops.at(i)));
  }
}
csize_t CodeBuffer::total_offset_of(CodeSection* cs) const {
  csize_t size_so_far = 0;
  for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
    const CodeSection* cur_cs = code_section(n);
    if (!cur_cs->is_empty()) {
      size_so_far = cur_cs->align_at_start(size_so_far);
    }
    if (cur_cs->index() == cs->index()) {
      return size_so_far;
    }
    size_so_far += cur_cs->size();
  }
  ShouldNotReachHere();
  return -1;
}
csize_t CodeBuffer::total_relocation_size() const {
  csize_t lsize = copy_relocations_to(NULL);  // dry run only
  csize_t csize = total_content_size();
  csize_t total = RelocIterator::locs_and_index_size(csize, lsize);
  return (csize_t) align_size_up(total, HeapWordSize);
}
csize_t CodeBuffer::copy_relocations_to(CodeBlob* dest) const {
  address buf = NULL;
  csize_t buf_offset = 0;
  csize_t buf_limit = 0;
  if (dest != NULL) {
    buf = (address)dest->relocation_begin();
    buf_limit = (address)dest->relocation_end() - buf;
    assert((uintptr_t)buf % HeapWordSize == 0, "buf must be fully aligned");
    assert(buf_limit % HeapWordSize == 0, "buf must be evenly sized");
  }
  csize_t code_end_so_far = 0;
  csize_t code_point_so_far = 0;
  for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    assert(!(cs->is_empty() && cs->locs_count() > 0), "sanity");
    if (cs->is_empty())  continue;  // skip trivial section
    relocInfo* lstart = cs->locs_start();
    relocInfo* lend   = cs->locs_end();
    csize_t    lsize  = (csize_t)( (address)lend - (address)lstart );
    csize_t    csize  = cs->size();
    code_end_so_far = cs->align_at_start(code_end_so_far);
    if (lsize > 0) {
      csize_t new_code_point = code_end_so_far;
      for (csize_t jump;
           code_point_so_far < new_code_point;
           code_point_so_far += jump) {
        jump = new_code_point - code_point_so_far;
        relocInfo filler = filler_relocInfo();
        if (jump >= filler.addr_offset()) {
          jump = filler.addr_offset();
        } else {  // else shrink the filler to fit
          filler = relocInfo(relocInfo::none, jump);
        }
        if (buf != NULL) {
          assert(buf_offset + (csize_t)sizeof(filler) <= buf_limit, "filler in bounds");
        }
        buf_offset += sizeof(filler);
      }
      csize_t last_code_point = code_end_so_far + cs->locs_point_off();
      assert(code_point_so_far <= last_code_point, "sanity");
      code_point_so_far = last_code_point; // advance past this guy's relocs
    }
    code_end_so_far += csize;  // advance past this guy's instructions too
    if (buf != NULL && lsize != 0) {
      assert(buf_offset + lsize <= buf_limit, "target in bounds");
      assert((uintptr_t)lstart % HeapWordSize == 0, "sane start");
      if (buf_offset % HeapWordSize == 0) {
        Copy::disjoint_words((HeapWord*)lstart,
                             (HeapWord*)(buf+buf_offset),
                             (lsize + HeapWordSize-1) / HeapWordSize);
      } else {
        Copy::conjoint_jbytes(lstart, buf+buf_offset, lsize);
      }
    }
    buf_offset += lsize;
  }
  while (buf_offset % HeapWordSize != 0) {
    if (buf != NULL) {
      relocInfo padding = relocInfo(relocInfo::none, 0);
      assert(buf_offset + (csize_t)sizeof(padding) <= buf_limit, "padding in bounds");
    }
    buf_offset += sizeof(relocInfo);
  }
  assert(code_end_so_far == total_content_size(), "sanity");
  if (buf != NULL) {
    RelocIterator::create_index(dest->relocation_begin(),
                                buf_offset / sizeof(relocInfo),
                                dest->relocation_end());
  }
  return buf_offset;
}
void CodeBuffer::copy_code_to(CodeBlob* dest_blob) {
#ifndef PRODUCT
  if (PrintNMethods && (WizardMode || Verbose)) {
    tty->print("done with CodeBuffer:");
    ((CodeBuffer*)this)->print();
  }
#endif //PRODUCT
  CodeBuffer dest(dest_blob);
  assert(dest_blob->content_size() >= total_content_size(), "good sizing");
  this->compute_final_layout(&dest);
  relocate_code_to(&dest);
  dest_blob->set_strings(_code_strings);
  assert(round_to(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
  ICache::invalidate_range(dest_blob->code_begin(), dest_blob->code_size());
}
void CodeBuffer::relocate_code_to(CodeBuffer* dest) const {
  address dest_end = dest->_total_start + dest->_total_size;
  address dest_filled = NULL;
  for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    if (cs->is_empty())  continue;  // skip trivial section
    CodeSection* dest_cs = dest->code_section(n);
    assert(cs->size() == dest_cs->size(), "sanity");
    csize_t usize = dest_cs->size();
    csize_t wsize = align_size_up(usize, HeapWordSize);
    assert(dest_cs->start() + wsize <= dest_end, "no overflow");
    Copy::disjoint_words((HeapWord*)cs->start(),
                         (HeapWord*)dest_cs->start(),
                         wsize / HeapWordSize);
    if (dest->blob() == NULL) {
      Copy::fill_to_bytes(dest_cs->end(), dest_cs->remaining(),
                          Assembler::code_fill_byte());
    }
    dest_filled = MAX2(dest_filled, dest_cs->end() + dest_cs->remaining());
    assert(cs->locs_start() != (relocInfo*)badAddress,
           "this section carries no reloc storage, but reloc was attempted");
    dest_cs->initialize_locs_from(cs);
  }
  for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    if (cs->is_empty()) continue;  // skip trivial section
    CodeSection* dest_cs = dest->code_section(n);
    { // Repair the pc relative information in the code after the move
      RelocIterator iter(dest_cs);
      while (iter.next()) {
        iter.reloc()->fix_relocation_after_move(this, dest);
      }
    }
  }
  if (dest->blob() == NULL && dest_filled != NULL) {
    Copy::fill_to_bytes(dest_filled, dest_end - dest_filled,
                        Assembler::code_fill_byte());
  }
}
csize_t CodeBuffer::figure_expanded_capacities(CodeSection* which_cs,
                                               csize_t amount,
                                               csize_t* new_capacity) {
  csize_t new_total_cap = 0;
  for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
    const CodeSection* sect = code_section(n);
    if (!sect->is_empty()) {
      csize_t padding = sect->align_at_start(new_total_cap) - new_total_cap;
      if (padding != 0) {
        new_total_cap += padding;
        assert(n - 1 >= SECT_FIRST, "sanity");
        new_capacity[n - 1] += padding;
      }
    }
    csize_t exp = sect->size();  // 100% increase
    if ((uint)exp < 4*K)  exp = 4*K;       // minimum initial increase
    if (sect == which_cs) {
      if (exp < amount)  exp = amount;
      if (StressCodeBuffers)  exp = amount;  // expand only slightly
    } else if (n == SECT_INSTS) {
      exp = 4*K + ((exp - 4*K) >> 2);
      if (StressCodeBuffers)  exp = amount / 2;  // expand only slightly
    } else if (sect->is_empty()) {
      exp = 0;
    }
    exp += CodeSection::end_slop();
    csize_t new_cap = sect->size() + exp;
    if (new_cap < sect->capacity()) {
      new_cap = sect->capacity();
    }
    new_capacity[n] = new_cap;
    new_total_cap += new_cap;
  }
  return new_total_cap;
}
void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
#ifndef PRODUCT
  if (PrintNMethods && (WizardMode || Verbose)) {
    tty->print("expanding CodeBuffer:");
    this->print();
  }
  if (StressCodeBuffers && blob() != NULL) {
    static int expand_count = 0;
    if (expand_count >= 0)  expand_count += 1;
    if (expand_count > 100 && is_power_of_2(expand_count)) {
      tty->print_cr("StressCodeBuffers: have expanded %d times", expand_count);
      free_blob();
    }
  }
#endif //PRODUCT
  {
    if (blob() == NULL)  return;  // caller must check for blob == NULL
    for (int n = 0; n < (int)SECT_LIMIT; n++) {
      guarantee(!code_section(n)->is_frozen(), "resizing not allowed when frozen");
    }
  }
  csize_t new_capacity[SECT_LIMIT];
  csize_t new_total_cap
    = figure_expanded_capacities(which_cs, amount, new_capacity);
  CodeBuffer cb(name(), new_total_cap, 0);
  if (cb.blob() == NULL) {
    free_blob();
    return;
  }
  CodeBuffer* bxp = new CodeBuffer(_total_start, _total_size);
  bxp->take_over_code_from(this);  // remember the old undersized blob
  DEBUG_ONLY(this->_blob = NULL);  // silence a later assert
  bxp->_before_expand = this->_before_expand;
  this->_before_expand = bxp;
  for (int n = (int)SECT_LIMIT-1; n >= SECT_FIRST; n--) {
    CodeSection* cb_sect   = cb.code_section(n);
    CodeSection* this_sect = code_section(n);
    if (new_capacity[n] == 0)  continue;  // already nulled out
    if (n != SECT_INSTS) {
      cb.initialize_section_size(cb_sect, new_capacity[n]);
    }
    assert(cb_sect->capacity() >= new_capacity[n], "big enough");
    address cb_start = cb_sect->start();
    cb_sect->set_end(cb_start + this_sect->size());
    if (this_sect->mark() == NULL) {
      cb_sect->clear_mark();
    } else {
      cb_sect->set_mark(cb_start + this_sect->mark_off());
    }
  }
  relocate_code_to(&cb);
  this->take_over_code_from(&cb);
  cb.set_blob(NULL);
  debug_only(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
                                 badCodeHeapFreeVal));
  _decode_begin = NULL;  // sanity
  verify_section_allocation();
#ifndef PRODUCT
  if (PrintNMethods && (WizardMode || Verbose)) {
    tty->print("expanded CodeBuffer:");
    this->print();
  }
#endif //PRODUCT
}
void CodeBuffer::take_over_code_from(CodeBuffer* cb) {
  assert(blob() == NULL, "must be empty");
#ifdef ASSERT
#endif
  set_blob(cb->blob());
  for (int n = 0; n < (int)SECT_LIMIT; n++) {
    CodeSection* cb_sect   = cb->code_section(n);
    CodeSection* this_sect = code_section(n);
    this_sect->take_over_code_from(cb_sect);
  }
  _overflow_arena = cb->_overflow_arena;
  DEBUG_ONLY(cb->_blob = (BufferBlob*)badAddress);
}
void CodeBuffer::verify_section_allocation() {
  address tstart = _total_start;
  if (tstart == badAddress)  return;  // smashed by set_blob(NULL)
  address tend   = tstart + _total_size;
  if (_blob != NULL) {
    guarantee(tstart >= _blob->content_begin(), "sanity");
    guarantee(tend   <= _blob->content_end(),   "sanity");
  }
  for (int n = (int) SECT_FIRST; n < (int) SECT_LIMIT; n++) {
    CodeSection* sect = code_section(n);
    if (!sect->is_allocated() || sect->is_empty())  continue;
    guarantee((intptr_t)sect->start() % sect->alignment() == 0
           || sect->is_empty() || _blob == NULL,
           "start is aligned");
    for (int m = (int) SECT_FIRST; m < (int) SECT_LIMIT; m++) {
      CodeSection* other = code_section(m);
      if (!other->is_allocated() || other == sect)  continue;
      guarantee(!other->contains(sect->start()    ), "sanity");
      guarantee(!other->contains(sect->limit() - 1), "sanity");
    }
    guarantee(sect->end() <= tend, "sanity");
    guarantee(sect->end() <= sect->limit(), "sanity");
  }
}
void CodeBuffer::log_section_sizes(const char* name) {
  if (xtty != NULL) {
    xtty->print_cr("<blob name='%s' size='%d'>", name, _total_size);
    for (int n = (int) CodeBuffer::SECT_FIRST; n < (int) CodeBuffer::SECT_LIMIT; n++) {
      CodeSection* sect = code_section(n);
      if (!sect->is_allocated() || sect->is_empty())  continue;
      xtty->print_cr("<sect index='%d' size='" SIZE_FORMAT "' free='" SIZE_FORMAT "'/>",
                     n, sect->limit() - sect->start(), sect->limit() - sect->end());
    }
    xtty->print_cr("</blob>");
  }
}
#ifndef PRODUCT
void CodeSection::dump() {
  address ptr = start();
  for (csize_t step; ptr < end(); ptr += step) {
    step = end() - ptr;
    if (step > jintSize * 4)  step = jintSize * 4;
    tty->print(INTPTR_FORMAT ": ", p2i(ptr));
    while (step > 0) {
      tty->print(" " PTR32_FORMAT, *(jint*)ptr);
      ptr += jintSize;
    }
    tty->cr();
  }
}
void CodeSection::decode() {
  Disassembler::decode(start(), end());
}
void CodeBuffer::block_comment(intptr_t offset, const char * comment) {
  _code_strings.add_comment(offset, comment);
}
const char* CodeBuffer::code_string(const char* str) {
  return _code_strings.add_string(str);
}
class CodeString: public CHeapObj<mtCode> {
 private:
  friend class CodeStrings;
  const char * _string;
  CodeString*  _next;
  intptr_t     _offset;
  ~CodeString() {
    assert(_next == NULL, "wrong interface for freeing list");
    os::free((void*)_string, mtCode);
  }
  bool is_comment() const { return _offset >= 0; }
 public:
  CodeString(const char * string, intptr_t offset = -1)
    : _next(NULL), _offset(offset) {
    _string = os::strdup(string, mtCode);
  }
  const char * string() const { return _string; }
  intptr_t     offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset;  }
  CodeString* next()    const { return _next; }
  void set_next(CodeString* next) { _next = next; }
  CodeString* first_comment() {
    if (is_comment()) {
      return this;
    } else {
      return next_comment();
    }
  }
  CodeString* next_comment() const {
    CodeString* s = _next;
    while (s != NULL && !s->is_comment()) {
      s = s->_next;
    }
    return s;
  }
};
CodeString* CodeStrings::find(intptr_t offset) const {
  CodeString* a = _strings->first_comment();
  while (a != NULL && a->offset() != offset) {
    a = a->next_comment();
  }
  return a;
}
CodeString* CodeStrings::find_last(intptr_t offset) const {
  CodeString* a = find(offset);
  if (a != NULL) {
    CodeString* c = NULL;
    while (((c = a->next_comment()) != NULL) && (c->offset() == offset)) {
      a = c;
    }
  }
  return a;
}
void CodeStrings::add_comment(intptr_t offset, const char * comment) {
  check_valid();
  CodeString* c      = new CodeString(comment, offset);
  CodeString* inspos = (_strings == NULL) ? NULL : find_last(offset);
  if (inspos) {
    c->set_next(inspos->next());
    inspos->set_next(c);
  } else {
    c->set_next(_strings);
    _strings = c;
  }
}
void CodeStrings::assign(CodeStrings& other) {
  other.check_valid();
  assert(is_null(), "Cannot assign onto non-empty CodeStrings");
  _strings = other._strings;
  other.set_null_and_invalidate();
}
void CodeStrings::copy(CodeStrings& other) {
  other.check_valid();
  check_valid();
  assert(is_null(), "Cannot copy onto non-empty CodeStrings");
  CodeString* n = other._strings;
  CodeString** ps = &_strings;
  while (n != NULL) {
    ps = &((*ps)->_next);
    n = n->next();
  }
}
void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
    check_valid();
    if (_strings != NULL) {
    CodeString* c = find(offset);
    while (c && c->offset() == offset) {
      stream->bol();
      stream->print("  ;; ");
      stream->print_cr("%s", c->string());
      c = c->next_comment();
    }
  }
}
void CodeStrings::free() {
  CodeString* n = _strings;
  while (n) {
    CodeString* p = n->next();
    n->set_next(NULL);
    delete n;
    n = p;
  }
  set_null_and_invalidate();
}
const char* CodeStrings::add_string(const char * string) {
  check_valid();
  CodeString* s = new CodeString(string);
  s->set_next(_strings);
  _strings = s;
  assert(s->string() != NULL, "should have a string");
  return s->string();
}
void CodeBuffer::decode() {
  ttyLocker ttyl;
  Disassembler::decode(decode_begin(), insts_end());
  _decode_begin = insts_end();
}
void CodeBuffer::skip_decode() {
  _decode_begin = insts_end();
}
void CodeBuffer::decode_all() {
  ttyLocker ttyl;
  for (int n = 0; n < (int)SECT_LIMIT; n++) {
    CodeSection* cs = code_section(n);
    tty->print_cr("! %s:", code_section_name(n));
    if (cs != consts())
      cs->decode();
    else
      cs->dump();
  }
}
void CodeSection::print(const char* name) {
  csize_t locs_size = locs_end() - locs_start();
  tty->print_cr(" %7s.code = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d)%s",
                name, p2i(start()), p2i(end()), p2i(limit()), size(), capacity(),
                is_frozen()? " [frozen]": "");
  tty->print_cr(" %7s.locs = " PTR_FORMAT " : " PTR_FORMAT " : " PTR_FORMAT " (%d of %d) point=%d",
                name, p2i(locs_start()), p2i(locs_end()), p2i(locs_limit()), locs_size, locs_capacity(), locs_point_off());
  if (PrintRelocations) {
    RelocIterator iter(this);
    iter.print();
  }
}
void CodeBuffer::print() {
  if (this == NULL) {
    tty->print_cr("NULL CodeBuffer pointer");
    return;
  }
  tty->print_cr("CodeBuffer:");
  for (int n = 0; n < (int)SECT_LIMIT; n++) {
    CodeSection* cs = code_section(n);
    cs->print(code_section_name(n));
  }
}
#endif // PRODUCT
C:\hotspot-69087d08d473\src\share\vm/asm/codeBuffer.hpp
#ifndef SHARE_VM_ASM_CODEBUFFER_HPP
#define SHARE_VM_ASM_CODEBUFFER_HPP
#include "code/oopRecorder.hpp"
#include "code/relocInfo.hpp"
#include "utilities/debug.hpp"
class CodeStrings;
class PhaseCFG;
class Compile;
class BufferBlob;
class CodeBuffer;
class Label;
class CodeOffsets: public StackObj {
public:
  enum Entries { Entry,
                 Verified_Entry,
                 Frame_Complete, // Offset in the code where the frame setup is (for forte stackwalks) is complete
                 OSR_Entry,
                 Dtrace_trap = OSR_Entry,  // dtrace probes can never have an OSR entry so reuse it
                 Exceptions,     // Offset where exception handler lives
                 Deopt,          // Offset where deopt handler lives
                 DeoptMH,        // Offset where MethodHandle deopt handler lives
                 UnwindHandler,  // Offset to default unwind handler
                 max_Entries };
  enum { frame_never_safe = -1 };
private:
  int _values[max_Entries];
public:
  CodeOffsets() {
    _values[Entry         ] = 0;
    _values[Verified_Entry] = 0;
    _values[Frame_Complete] = frame_never_safe;
    _values[OSR_Entry     ] = 0;
    _values[Exceptions    ] = -1;
    _values[Deopt         ] = -1;
    _values[DeoptMH       ] = -1;
    _values[UnwindHandler ] = -1;
  }
  int value(Entries e) { return _values[e]; }
  void set_value(Entries e, int val) { _values[e] = val; }
};
class CodeSection VALUE_OBJ_CLASS_SPEC {
  friend class CodeBuffer;
 public:
  typedef int csize_t;  // code size type; would be size_t except for history
 private:
  address     _start;           // first byte of contents (instructions)
  address     _mark;            // user mark, usually an instruction beginning
  address     _end;             // current end address
  address     _limit;           // last possible (allocated) end address
  relocInfo*  _locs_start;      // first byte of relocation information
  relocInfo*  _locs_end;        // first byte after relocation information
  relocInfo*  _locs_limit;      // first byte after relocation information buf
  address     _locs_point;      // last relocated position (grows upward)
  bool        _locs_own;        // did I allocate the locs myself?
  bool        _frozen;          // no more expansion of this section
  char        _index;           // my section number (SECT_INST, etc.)
  CodeBuffer* _outer;           // enclosing CodeBuffer
  CodeSection() {
    _start         = NULL;
    _mark          = NULL;
    _end           = NULL;
    _limit         = NULL;
    _locs_start    = NULL;
    _locs_end      = NULL;
    _locs_limit    = NULL;
    _locs_point    = NULL;
    _locs_own      = false;
    _frozen        = false;
    debug_only(_index = (char)-1);
    debug_only(_outer = (CodeBuffer*)badAddress);
  }
  void initialize_outer(CodeBuffer* outer, int index) {
    _outer = outer;
    _index = index;
  }
  void initialize(address start, csize_t size = 0) {
    assert(_start == NULL, "only one init step, please");
    _start         = start;
    _mark          = NULL;
    _end           = start;
    _limit         = start + size;
    _locs_point    = start;
  }
  void initialize_locs(int locs_capacity);
  void expand_locs(int new_capacity);
  void initialize_locs_from(const CodeSection* source_cs);
  void take_over_code_from(CodeSection* cs) {
    _start      = cs->_start;
    _mark       = cs->_mark;
    _end        = cs->_end;
    _limit      = cs->_limit;
    _locs_point = cs->_locs_point;
  }
 public:
  address     start() const         { return _start; }
  address     mark() const          { return _mark; }
  address     end() const           { return _end; }
  address     limit() const         { return _limit; }
  csize_t     size() const          { return (csize_t)(_end - _start); }
  csize_t     mark_off() const      { assert(_mark != NULL, "not an offset");
                                      return (csize_t)(_mark - _start); }
  csize_t     capacity() const      { return (csize_t)(_limit - _start); }
  csize_t     remaining() const     { return (csize_t)(_limit - _end); }
  relocInfo*  locs_start() const    { return _locs_start; }
  relocInfo*  locs_end() const      { return _locs_end; }
  int         locs_count() const    { return (int)(_locs_end - _locs_start); }
  relocInfo*  locs_limit() const    { return _locs_limit; }
  address     locs_point() const    { return _locs_point; }
  csize_t     locs_point_off() const{ return (csize_t)(_locs_point - _start); }
  csize_t     locs_capacity() const { return (csize_t)(_locs_limit - _locs_start); }
  csize_t     locs_remaining()const { return (csize_t)(_locs_limit - _locs_end); }
  int         index() const         { return _index; }
  bool        is_allocated() const  { return _start != NULL; }
  bool        is_empty() const      { return _start == _end; }
  bool        is_frozen() const     { return _frozen; }
  bool        has_locs() const      { return _locs_end != NULL; }
  CodeBuffer* outer() const         { return _outer; }
  bool contains(address pc) const   { return pc >= _start && pc <  _end; }
  bool contains2(address pc) const  { return pc >= _start && pc <= _end; }
  bool allocates(address pc) const  { return pc >= _start && pc <  _limit; }
  bool allocates2(address pc) const { return pc >= _start && pc <= _limit; }
  void    set_end(address pc)       { assert(allocates2(pc), err_msg("not in CodeBuffer memory: " PTR_FORMAT " <= " PTR_FORMAT " <= " INTPTR_FORMAT, p2i(_start), p2i(pc), p2i(_limit))); _end = pc; }
  void    set_mark(address pc)      { assert(contains2(pc), "not in codeBuffer");
                                      _mark = pc; }
  void    set_mark_off(int offset)  { assert(contains2(offset+_start),"not in codeBuffer");
                                      _mark = offset + _start; }
  void    set_mark()                { _mark = _end; }
  void    clear_mark()              { _mark = NULL; }
  void    set_locs_end(relocInfo* p) {
    assert(p <= locs_limit(), "locs data fits in allocated buffer");
    _locs_end = p;
  }
  void    set_locs_point(address pc) {
    assert(pc >= locs_point(), "relocation addr may not decrease");
    assert(allocates2(pc),     "relocation addr must be in this section");
    _locs_point = pc;
  }
  void emit_int8 ( int8_t  x)  { *((int8_t*)  end()) = x; set_end(end() + sizeof(int8_t)); }
  void emit_int16( int16_t x)  { *((int16_t*) end()) = x; set_end(end() + sizeof(int16_t)); }
  void emit_int32( int32_t x)  { *((int32_t*) end()) = x; set_end(end() + sizeof(int32_t)); }
  void emit_int64( int64_t x)  { *((int64_t*) end()) = x; set_end(end() + sizeof(int64_t)); }
  void emit_float( jfloat  x)  { *((jfloat*)  end()) = x; set_end(end() + sizeof(jfloat)); }
  void emit_double(jdouble x)  { *((jdouble*) end()) = x; set_end(end() + sizeof(jdouble)); }
  void emit_address(address x) { *((address*) end()) = x; set_end(end() + sizeof(address)); }
  void initialize_shared_locs(relocInfo* buf, int length);
  address target(Label& L, address branch_pc);
  void relocate(address at, RelocationHolder const& rspec, int format = 0);
  void relocate(address at,    relocInfo::relocType rtype, int format = 0) {
    if (rtype != relocInfo::none)
      relocate(at, Relocation::spec_simple(rtype), format);
  }
  int alignment() const             { return MAX2((int)sizeof(jdouble), (int)CodeEntryAlignment); }
  static csize_t end_slop()         { return MAX2((int)sizeof(jdouble), (int)CodeEntryAlignment); }
  csize_t align_at_start(csize_t off) const { return (csize_t) align_size_up(off, alignment()); }
  inline void freeze();         //  { _outer->freeze_section(this); }
  bool maybe_expand_to_ensure_remaining(csize_t amount);
#ifndef PRODUCT
  void decode();
  void dump();
  void print(const char* name);
#endif //PRODUCT
};
class CodeString;
class CodeStrings VALUE_OBJ_CLASS_SPEC {
private:
#ifndef PRODUCT
  CodeString* _strings;
#ifdef ASSERT
  bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env
#endif
#endif
  CodeString* find(intptr_t offset) const;
  CodeString* find_last(intptr_t offset) const;
  void set_null_and_invalidate() {
#ifndef PRODUCT
    _strings = NULL;
#ifdef ASSERT
    _defunct = true;
#endif
#endif
  }
public:
  CodeStrings() {
#ifndef PRODUCT
    _strings = NULL;
#ifdef ASSERT
    _defunct = false;
#endif
#endif
  }
  bool is_null() {
#ifdef ASSERT
    return _strings == NULL;
#else
    return true;
#endif
  }
  const char* add_string(const char * string) PRODUCT_RETURN_(return NULL;);
  void add_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
  void print_block_comment(outputStream* stream, intptr_t offset) const PRODUCT_RETURN;
  void assign(CodeStrings& other)  PRODUCT_RETURN;
  void copy(CodeStrings& other)  PRODUCT_RETURN;
  void free() PRODUCT_RETURN;
  inline void check_valid() const {
#ifdef ASSERT
    assert(!_defunct, "Use of invalid CodeStrings");
#endif
  }
};
class CodeBuffer: public StackObj {
  friend class CodeSection;
 private:
  void* operator new(size_t size) throw() { return ResourceObj::operator new(size); }
  void  operator delete(void* p)          { ShouldNotCallThis(); }
 public:
  typedef int csize_t;  // code size type; would be size_t except for history
  enum {
    SECT_FIRST = 0,
    SECT_CONSTS = SECT_FIRST, // Non-instruction data:  Floats, jump tables, etc.
    SECT_INSTS,               // Executable instructions.
    SECT_STUBS,               // Outbound trampolines for supporting call sites.
    SECT_LIMIT, SECT_NONE = -1
  };
 private:
  enum {
    sect_bits = 2,      // assert (SECT_LIMIT <= (1<<sect_bits))
    sect_mask = (1<<sect_bits)-1
  };
  const char*  _name;
  CodeSection  _consts;             // constants, jump tables
  CodeSection  _insts;              // instructions (the main section)
  CodeSection  _stubs;              // stubs (call site support), deopt, exception handling
  CodeBuffer*  _before_expand;  // dead buffer, from before the last expansion
  BufferBlob*  _blob;           // optional buffer in CodeCache for generated code
  address      _total_start;    // first address of combined memory buffer
  csize_t      _total_size;     // size in bytes of combined memory buffer
  OopRecorder* _oop_recorder;
  CodeStrings  _code_strings;
  OopRecorder  _default_oop_recorder;  // override with initialize_oop_recorder
  Arena*       _overflow_arena;
  address      _decode_begin;   // start address for decode
  address      decode_begin();
  void initialize_misc(const char * name) {
    assert(name != NULL, "must have a name");
    _name            = name;
    _before_expand   = NULL;
    _blob            = NULL;
    _oop_recorder    = NULL;
    _decode_begin    = NULL;
    _overflow_arena  = NULL;
  }
  void initialize(address code_start, csize_t code_size) {
    _consts.initialize_outer(this,  SECT_CONSTS);
    _insts.initialize_outer(this,   SECT_INSTS);
    _stubs.initialize_outer(this,   SECT_STUBS);
    _total_start = code_start;
    _total_size  = code_size;
    _insts.initialize(code_start, code_size);
    assert(!_stubs.is_allocated(),  "no garbage here");
    assert(!_consts.is_allocated(), "no garbage here");
    _oop_recorder = &_default_oop_recorder;
  }
  void initialize_section_size(CodeSection* cs, csize_t size);
  void freeze_section(CodeSection* cs);
  void take_over_code_from(CodeBuffer* cs);
  void verify_section_allocation();
  csize_t copy_relocations_to(CodeBlob* blob) const;
  void copy_code_to(CodeBlob* blob);
  void relocate_code_to(CodeBuffer* cb) const;
  void compute_final_layout(CodeBuffer* dest) const;
  void expand(CodeSection* which_cs, csize_t amount);
  csize_t figure_expanded_capacities(CodeSection* which_cs, csize_t amount, csize_t* new_capacity);
 public:
  CodeBuffer(address code_start, csize_t code_size) {
    assert(code_start != NULL, "sanity");
    initialize_misc("static buffer");
    initialize(code_start, code_size);
    verify_section_allocation();
  }
  CodeBuffer(CodeBlob* blob);
  CodeBuffer(const char* name) {
    initialize_misc(name);
  }
  CodeBuffer(const char* name, csize_t code_size, csize_t locs_size) {
    initialize_misc(name);
    initialize(code_size, locs_size);
  }
  ~CodeBuffer();
  void initialize(csize_t code_size, csize_t locs_size);
  CodeSection* consts()            { return &_consts; }
  CodeSection* insts()             { return &_insts; }
  CodeSection* stubs()             { return &_stubs; }
  CodeSection* code_section(int n) {
    CodeSection* cs = &_consts + n;
    assert(cs->index() == n || !cs->is_allocated(), "sanity");
    return cs;
  }
  const CodeSection* code_section(int n) const {  // yucky const stuff
    return ((CodeBuffer*)this)->code_section(n);
  }
  static const char* code_section_name(int n);
  int section_index_of(address addr) const;
  bool contains(address addr) const {
    return section_index_of(addr) > SECT_NONE;
  }
  static int locator_pos(int locator)   { return locator >> sect_bits; }
  static int locator_sect(int locator)  { return locator &  sect_mask; }
  static int locator(int pos, int sect) { return (pos << sect_bits) | sect; }
  int        locator(address addr) const;
  address    locator_address(int locator) const;
  bool is_backward_branch(Label& L);
  const char* name() const                  { return _name; }
  CodeBuffer* before_expand() const         { return _before_expand; }
  BufferBlob* blob() const                  { return _blob; }
  void    set_blob(BufferBlob* blob);
  void   free_blob();                       // Free the blob, if we own one.
  address       insts_begin() const      { return _insts.start();      }
  address       insts_end() const        { return _insts.end();        }
  void      set_insts_end(address end)   {        _insts.set_end(end); }
  address       insts_limit() const      { return _insts.limit();      }
  address       insts_mark() const       { return _insts.mark();       }
  void      set_insts_mark()             {        _insts.set_mark();   }
  void    clear_insts_mark()             {        _insts.clear_mark(); }
  bool    is_pure() const                { return insts_size() == total_content_size(); }
  csize_t insts_size() const             { return _insts.size(); }
  csize_t pure_insts_size() const        { assert(is_pure(), "no non-code");
                                           return insts_size(); }
  csize_t insts_capacity() const         { return _insts.capacity(); }
  csize_t insts_remaining() const        { return _insts.remaining(); }
  bool insts_contains(address pc) const  { return _insts.contains(pc); }
  bool insts_contains2(address pc) const { return _insts.contains2(pc); }
  void finalize_oop_references(methodHandle method);
  csize_t total_content_size() const;
  csize_t total_offset_of(CodeSection* cs) const;
  csize_t total_relocation_size() const;
  csize_t total_oop_size() const {
    OopRecorder* recorder = oop_recorder();
    return (recorder == NULL)? 0: recorder->oop_size();
  }
  csize_t total_metadata_size() const {
    OopRecorder* recorder = oop_recorder();
    return (recorder == NULL)? 0: recorder->metadata_size();
  }
  void initialize_consts_size(csize_t size)            { initialize_section_size(&_consts,  size); }
  void initialize_stubs_size(csize_t size)             { initialize_section_size(&_stubs,   size); }
  void initialize_oop_recorder(OopRecorder* r);
  OopRecorder* oop_recorder() const   { return _oop_recorder; }
  CodeStrings& strings()              { return _code_strings; }
  void free_strings() {
    if (!_code_strings.is_null()) {
      _code_strings.free(); // sets _strings Null as a side-effect.
    }
  }
  void relocate(address at, RelocationHolder const& rspec, int format = 0) {
    _insts.relocate(at, rspec, format);
  }
  void relocate(address at,    relocInfo::relocType rtype, int format = 0) {
    _insts.relocate(at, rtype, format);
  }
  GrowableArray<int>* create_patch_overflow();
  void copy_code_and_locs_to(CodeBlob* blob) {
    assert(blob != NULL, "sane");
    copy_relocations_to(blob);
    copy_code_to(blob);
  }
  void copy_values_to(nmethod* nm) {
    if (!oop_recorder()->is_unused()) {
      oop_recorder()->copy_values_to(nm);
    }
  }
  address transform_address(const CodeBuffer &cb, address addr) const;
  void block_comment(intptr_t offset, const char * comment) PRODUCT_RETURN;
  const char* code_string(const char* str) PRODUCT_RETURN_(return NULL;);
  void log_section_sizes(const char* name);
#ifndef PRODUCT
 public:
  void    decode();
  void    decode_all();         // decodes all the code
  void    skip_decode();        // sets decode_begin to code_end();
  void    print();
#endif
#ifdef TARGET_ARCH_x86
# include "codeBuffer_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "codeBuffer_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "codeBuffer_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "codeBuffer_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "codeBuffer_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "codeBuffer_ppc.hpp"
#endif
};
inline void CodeSection::freeze() {
  _outer->freeze_section(this);
}
inline bool CodeSection::maybe_expand_to_ensure_remaining(csize_t amount) {
  if (remaining() < amount) { _outer->expand(this, amount); return true; }
  return false;
}
#endif // SHARE_VM_ASM_CODEBUFFER_HPP
C:\hotspot-69087d08d473\src\share\vm/asm/macroAssembler.hpp
#ifndef SHARE_VM_ASM_MACROASSEMBLER_HPP
#define SHARE_VM_ASM_MACROASSEMBLER_HPP
#include "asm/assembler.hpp"
#ifdef TARGET_ARCH_x86
# include "macroAssembler_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "macroAssembler_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "assembler_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "macroAssembler_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "macroAssembler_ppc.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "macroAssembler_aarch64.hpp"
#endif
#endif // SHARE_VM_ASM_MACROASSEMBLER_HPP
C:\hotspot-69087d08d473\src\share\vm/asm/macroAssembler.inline.hpp
#ifndef SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP
#define SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP
#include "asm/macroAssembler.hpp"
#ifdef TARGET_ARCH_x86
#endif
#ifdef TARGET_ARCH_sparc
# include "macroAssembler_sparc.inline.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "assembler_zero.inline.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "macroAssembler_arm.inline.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "macroAssembler_ppc.inline.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "macroAssembler_aarch64.inline.hpp"
#endif
#endif // SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/asm/register.cpp
#include "precompiled.hpp"
#include "asm/register.hpp"
C:\hotspot-69087d08d473\src\share\vm/asm/register.hpp
#ifndef SHARE_VM_ASM_REGISTER_HPP
#define SHARE_VM_ASM_REGISTER_HPP
#include "utilities/top.hpp"
class AbstractRegisterImpl;
typedef AbstractRegisterImpl* AbstractRegister;
class AbstractRegisterImpl {
 protected:
  int value() const                              { return (int)(intx)this; }
};
#define AS_REGISTER(type,name)         ((type)name##_##type##EnumValue)
#define CONSTANT_REGISTER_DECLARATION(type, name, value) \
extern const type name;                                  \
enum { name##_##type##EnumValue = (value) }
#define REGISTER_DECLARATION(type, name, value) \
extern const type name;                         \
enum { name##_##type##EnumValue = value##_##type##EnumValue }
#define REGISTER_DEFINITION(type, name) \
const type name = ((type)name##_##type##EnumValue)
#ifdef TARGET_ARCH_x86
# include "register_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "register_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "register_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "register_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "register_ppc.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "register_aarch64.hpp"
#endif
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b
) {
  assert(
    a != b,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT "",
                p2i(a), p2i(b))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c
) {
  assert(
    a != b && a != c
           && b != c,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d
) {
  assert(
    a != b && a != c && a != d
           && b != c && b != d
                     && c != d,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e
) {
  assert(
    a != b && a != c && a != d && a != e
           && b != c && b != d && b != e
                     && c != d && c != e
                               && d != e,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e,
  AbstractRegister f
) {
  assert(
    a != b && a != c && a != d && a != e && a != f
           && b != c && b != d && b != e && b != f
                     && c != d && c != e && c != f
                               && d != e && d != f
                                         && e != f,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
                ", f=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e,
  AbstractRegister f,
  AbstractRegister g
) {
  assert(
    a != b && a != c && a != d && a != e && a != f && a != g
           && b != c && b != d && b != e && b != f && b != g
                     && c != d && c != e && c != f && c != g
                               && d != e && d != f && d != g
                                         && e != f && e != g
                                                   && f != g,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e,
  AbstractRegister f,
  AbstractRegister g,
  AbstractRegister h
) {
  assert(
    a != b && a != c && a != d && a != e && a != f && a != g && a != h
           && b != c && b != d && b != e && b != f && b != g && b != h
                     && c != d && c != e && c != f && c != g && c != h
                               && d != e && d != f && d != g && d != h
                                         && e != f && e != g && e != h
                                                   && f != g && f != h
                                                             && g != h,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e,
  AbstractRegister f,
  AbstractRegister g,
  AbstractRegister h,
  AbstractRegister i
) {
  assert(
    a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i
           && b != c && b != d && b != e && b != f && b != g && b != h && b != i
                     && c != d && c != e && c != f && c != g && c != h && c != i
                               && d != e && d != f && d != g && d != h && d != i
                                         && e != f && e != g && e != h && e != i
                                                   && f != g && f != h && f != i
                                                             && g != h && g != i
                                                                       && h != i,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
                ", i=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e,
  AbstractRegister f,
  AbstractRegister g,
  AbstractRegister h,
  AbstractRegister i,
  AbstractRegister j
) {
  assert(
    a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j
           && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j
                     && c != d && c != e && c != f && c != g && c != h && c != i && c != j
                               && d != e && d != f && d != g && d != h && d != i && d != j
                                         && e != f && e != g && e != h && e != i && e != j
                                                   && f != g && f != h && f != i && f != j
                                                             && g != h && g != i && g != j
                                                                       && h != i && h != j
                                                                                 && i != j,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
                ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e,
  AbstractRegister f,
  AbstractRegister g,
  AbstractRegister h,
  AbstractRegister i,
  AbstractRegister j,
  AbstractRegister k
) {
  assert(
    a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k
           && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k
                     && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k
                               && d != e && d != f && d != g && d != h && d != i && d != j && d !=k
                                         && e != f && e != g && e != h && e != i && e != j && e !=k
                                                   && f != g && f != h && f != i && f != j && f !=k
                                                             && g != h && g != i && g != j && g !=k
                                                                       && h != i && h != j && h !=k
                                                                                 && i != j && i !=k
                                                                                           && j !=k,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
                ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k))
  );
}
inline void assert_different_registers(
  AbstractRegister a,
  AbstractRegister b,
  AbstractRegister c,
  AbstractRegister d,
  AbstractRegister e,
  AbstractRegister f,
  AbstractRegister g,
  AbstractRegister h,
  AbstractRegister i,
  AbstractRegister j,
  AbstractRegister k,
  AbstractRegister l
) {
  assert(
    a != b && a != c && a != d && a != e && a != f && a != g && a != h && a != i && a != j && a !=k && a !=l
           && b != c && b != d && b != e && b != f && b != g && b != h && b != i && b != j && b !=k && b !=l
                     && c != d && c != e && c != f && c != g && c != h && c != i && c != j && c !=k && c !=l
                               && d != e && d != f && d != g && d != h && d != i && d != j && d !=k && d !=l
                                         && e != f && e != g && e != h && e != i && e != j && e !=k && e !=l
                                                   && f != g && f != h && f != i && f != j && f !=k && f !=l
                                                             && g != h && g != i && g != j && g !=k && g !=l
                                                                       && h != i && h != j && h !=k && h !=l
                                                                                 && i != j && i !=k && i !=l
                                                                                           && j !=k && j !=l
                                                                                                    && k !=l,
    err_msg_res("registers must be different: a=" INTPTR_FORMAT ", b=" INTPTR_FORMAT
                ", c=" INTPTR_FORMAT ", d=" INTPTR_FORMAT ", e=" INTPTR_FORMAT
                ", f=" INTPTR_FORMAT ", g=" INTPTR_FORMAT ", h=" INTPTR_FORMAT
                ", i=" INTPTR_FORMAT ", j=" INTPTR_FORMAT ", k=" INTPTR_FORMAT
                ", l=" INTPTR_FORMAT "",
                p2i(a), p2i(b), p2i(c), p2i(d), p2i(e), p2i(f), p2i(g), p2i(h), p2i(i), p2i(j), p2i(k), p2i(l))
  );
}
#endif // SHARE_VM_ASM_REGISTER_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Canonicalizer.cpp
#include "precompiled.hpp"
#include "c1/c1_Canonicalizer.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciArray.hpp"
#include "runtime/sharedRuntime.hpp"
class PrintValueVisitor: public ValueVisitor {
  void visit(Value* vp) {
    (*vp)->print_line();
  }
};
void Canonicalizer::set_canonical(Value x) {
  assert(x != NULL, "value must exist");
  if (canonical() != x) {
#ifndef PRODUCT
    if (!x->has_printable_bci()) {
      x->set_printable_bci(bci());
    }
#endif
    if (PrintCanonicalization) {
      PrintValueVisitor do_print_value;
      canonical()->input_values_do(&do_print_value);
      canonical()->print_line();
      tty->print_cr("canonicalized to:");
      x->input_values_do(&do_print_value);
      x->print_line();
      tty->cr();
    }
    assert(_canonical->type()->tag() == x->type()->tag(), "types must match");
    _canonical = x;
  }
}
void Canonicalizer::move_const_to_right(Op2* x) {
  if (x->x()->type()->is_constant() && x->is_commutative()) x->swap_operands();
}
void Canonicalizer::do_Op2(Op2* x) {
  if (x->x() == x->y()) {
    switch (x->op()) {
    case Bytecodes::_isub: set_constant(0); return;
    case Bytecodes::_lsub: set_constant(jlong_cast(0)); return;
    case Bytecodes::_iand: // fall through
    case Bytecodes::_land: // fall through
    case Bytecodes::_ior:  // fall through
    case Bytecodes::_lor : set_canonical(x->x()); return;
    case Bytecodes::_ixor: set_constant(0); return;
    case Bytecodes::_lxor: set_constant(jlong_cast(0)); return;
    }
  }
  if (x->x()->type()->is_constant() && x->y()->type()->is_constant()) {
    switch (x->type()->tag()) {
      case intTag:
        { jint a = x->x()->type()->as_IntConstant()->value();
          jint b = x->y()->type()->as_IntConstant()->value();
          switch (x->op()) {
            case Bytecodes::_iadd: set_constant(a + b); return;
            case Bytecodes::_isub: set_constant(a - b); return;
            case Bytecodes::_imul: set_constant(a * b); return;
            case Bytecodes::_idiv:
              if (b != 0) {
                if (a == min_jint && b == -1) {
                  set_constant(min_jint);
                } else {
                  set_constant(a / b);
                }
                return;
              }
              break;
            case Bytecodes::_irem:
              if (b != 0) {
                if (a == min_jint && b == -1) {
                  set_constant(0);
                } else {
                  set_constant(a % b);
                }
                return;
              }
              break;
            case Bytecodes::_iand: set_constant(a & b); return;
            case Bytecodes::_ior : set_constant(a | b); return;
            case Bytecodes::_ixor: set_constant(a ^ b); return;
          }
        }
        break;
      case longTag:
        { jlong a = x->x()->type()->as_LongConstant()->value();
          jlong b = x->y()->type()->as_LongConstant()->value();
          switch (x->op()) {
            case Bytecodes::_ladd: set_constant(a + b); return;
            case Bytecodes::_lsub: set_constant(a - b); return;
            case Bytecodes::_lmul: set_constant(a * b); return;
            case Bytecodes::_ldiv:
              if (b != 0) {
                set_constant(SharedRuntime::ldiv(b, a));
                return;
              }
              break;
            case Bytecodes::_lrem:
              if (b != 0) {
                set_constant(SharedRuntime::lrem(b, a));
                return;
              }
              break;
            case Bytecodes::_land: set_constant(a & b); return;
            case Bytecodes::_lor : set_constant(a | b); return;
            case Bytecodes::_lxor: set_constant(a ^ b); return;
          }
        }
        break;
    }
  }
  move_const_to_right(x);
  if (x->y()->type()->is_constant()) {
    switch (x->type()->tag()) {
      case intTag:
        if (x->y()->type()->as_IntConstant()->value() == 0) {
          switch (x->op()) {
            case Bytecodes::_iadd: set_canonical(x->x()); return;
            case Bytecodes::_isub: set_canonical(x->x()); return;
            case Bytecodes::_imul: set_constant(0); return;
            case Bytecodes::_iand: set_constant(0); return;
            case Bytecodes::_ior : set_canonical(x->x()); return;
          }
        }
        break;
      case longTag:
        if (x->y()->type()->as_LongConstant()->value() == (jlong)0) {
          switch (x->op()) {
            case Bytecodes::_ladd: set_canonical(x->x()); return;
            case Bytecodes::_lsub: set_canonical(x->x()); return;
            case Bytecodes::_lmul: set_constant((jlong)0); return;
            case Bytecodes::_land: set_constant((jlong)0); return;
            case Bytecodes::_lor : set_canonical(x->x()); return;
          }
        }
        break;
    }
  }
}
void Canonicalizer::do_Phi            (Phi*             x) {}
void Canonicalizer::do_Constant       (Constant*        x) {}
void Canonicalizer::do_Local          (Local*           x) {}
void Canonicalizer::do_LoadField      (LoadField*       x) {}
static bool in_current_block(Value v) {
  int max_distance = 4;
  while (max_distance > 0 && v != NULL && v->as_BlockEnd() == NULL) {
    v = v->next();
    max_distance--;
  }
  return v == NULL;
}
void Canonicalizer::do_StoreField     (StoreField*      x) {
  Convert* conv = x->value()->as_Convert();
  if (conv) {
    Value value = NULL;
    BasicType type = x->field()->type()->basic_type();
    switch (conv->op()) {
    case Bytecodes::_i2b: if (type == T_BYTE)  value = conv->value(); break;
    case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) value = conv->value(); break;
    case Bytecodes::_i2c: if (type == T_CHAR  || type == T_BYTE)  value = conv->value(); break;
    }
    if (value != NULL && in_current_block(conv)) {
      set_canonical(new StoreField(x->obj(), x->offset(), x->field(), value, x->is_static(),
                                   x->state_before(), x->needs_patching()));
      return;
    }
  }
}
void Canonicalizer::do_ArrayLength    (ArrayLength*     x) {
  NewArray* array = x->array()->as_NewArray();
  if (array != NULL && array->length() != NULL) {
    Constant* length = array->length()->as_Constant();
    if (length != NULL) {
      assert(length->type()->as_IntConstant() != NULL, "array length must be integer");
      set_constant(length->type()->as_IntConstant()->value());
    }
  } else {
    LoadField* lf = x->array()->as_LoadField();
    if (lf != NULL) {
      ciField* field = lf->field();
      if (field->is_constant() && field->is_static()) {
        ciObject* c = field->constant_value().as_object();
        if (c->is_array()) {
          ciArray* array = (ciArray*) c;
          set_constant(array->length());
        }
      }
    }
  }
}
void Canonicalizer::do_LoadIndexed    (LoadIndexed*     x) {}
void Canonicalizer::do_StoreIndexed   (StoreIndexed*    x) {
  Convert* conv = x->value()->as_Convert();
  if (conv) {
    Value value = NULL;
    BasicType type = x->elt_type();
    switch (conv->op()) {
    case Bytecodes::_i2b: if (type == T_BYTE)  value = conv->value(); break;
    case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) value = conv->value(); break;
    case Bytecodes::_i2c: if (type == T_CHAR  || type == T_BYTE) value = conv->value(); break;
    }
    if (value != NULL && in_current_block(conv)) {
      set_canonical(new StoreIndexed(x->array(), x->index(), x->length(),
                                     x->elt_type(), value, x->state_before(),
                                     x->check_boolean()));
      return;
    }
  }
}
void Canonicalizer::do_NegateOp(NegateOp* x) {
  ValueType* t = x->x()->type();
  if (t->is_constant()) {
    switch (t->tag()) {
      case intTag   : set_constant(-t->as_IntConstant   ()->value()); return;
      case longTag  : set_constant(-t->as_LongConstant  ()->value()); return;
      case floatTag : set_constant(-t->as_FloatConstant ()->value()); return;
      case doubleTag: set_constant(-t->as_DoubleConstant()->value()); return;
      default       : ShouldNotReachHere();
    }
  }
}
void Canonicalizer::do_ArithmeticOp   (ArithmeticOp*    x) { do_Op2(x); }
void Canonicalizer::do_ShiftOp        (ShiftOp*         x) {
  ValueType* t = x->x()->type();
  ValueType* t2 = x->y()->type();
  if (t->is_constant()) {
    switch (t->tag()) {
    case intTag   : if (t->as_IntConstant()->value() == 0)         { set_constant(0); return; } break;
    case longTag  : if (t->as_LongConstant()->value() == (jlong)0) { set_constant(jlong_cast(0)); return; } break;
    default       : ShouldNotReachHere();
    }
    if (t2->is_constant()) {
      if (t->tag() == intTag) {
        int value = t->as_IntConstant()->value();
        int shift = t2->as_IntConstant()->value() & 31;
        jint mask = ~(~0 << (32 - shift));
        if (shift == 0) mask = ~0;
        switch (x->op()) {
          case Bytecodes::_ishl:  set_constant(value << shift); return;
          case Bytecodes::_ishr:  set_constant(value >> shift); return;
          case Bytecodes::_iushr: set_constant((value >> shift) & mask); return;
        }
      } else if (t->tag() == longTag) {
        jlong value = t->as_LongConstant()->value();
        int shift = t2->as_IntConstant()->value() & 63;
        jlong mask = ~(~jlong_cast(0) << (64 - shift));
        if (shift == 0) mask = ~jlong_cast(0);
        switch (x->op()) {
          case Bytecodes::_lshl:  set_constant(value << shift); return;
          case Bytecodes::_lshr:  set_constant(value >> shift); return;
          case Bytecodes::_lushr: set_constant((value >> shift) & mask); return;
        }
      }
    }
  }
  if (t2->is_constant()) {
    switch (t2->tag()) {
      case intTag   : if (t2->as_IntConstant()->value() == 0)  set_canonical(x->x()); return;
      case longTag  : if (t2->as_LongConstant()->value() == (jlong)0)  set_canonical(x->x()); return;
      default       : ShouldNotReachHere();
    }
  }
}
void Canonicalizer::do_LogicOp        (LogicOp*         x) { do_Op2(x); }
void Canonicalizer::do_CompareOp      (CompareOp*       x) {
  if (x->x() == x->y()) {
    switch (x->x()->type()->tag()) {
      case longTag: set_constant(0); break;
      case floatTag: {
        FloatConstant* fc = x->x()->type()->as_FloatConstant();
        if (fc) {
          if (g_isnan(fc->value())) {
            set_constant(x->op() == Bytecodes::_fcmpl ? -1 : 1);
          } else {
            set_constant(0);
          }
        }
        break;
      }
      case doubleTag: {
        DoubleConstant* dc = x->x()->type()->as_DoubleConstant();
        if (dc) {
          if (g_isnan(dc->value())) {
            set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1);
          } else {
            set_constant(0);
          }
        }
        break;
      }
    }
  } else if (x->x()->type()->is_constant() && x->y()->type()->is_constant()) {
    switch (x->x()->type()->tag()) {
      case longTag: {
        jlong vx = x->x()->type()->as_LongConstant()->value();
        jlong vy = x->y()->type()->as_LongConstant()->value();
        if (vx == vy)
          set_constant(0);
        else if (vx < vy)
          set_constant(-1);
        else
          set_constant(1);
        break;
      }
      case floatTag: {
        float vx = x->x()->type()->as_FloatConstant()->value();
        float vy = x->y()->type()->as_FloatConstant()->value();
        if (g_isnan(vx) || g_isnan(vy))
          set_constant(x->op() == Bytecodes::_fcmpl ? -1 : 1);
        else if (vx == vy)
          set_constant(0);
        else if (vx < vy)
          set_constant(-1);
        else
          set_constant(1);
        break;
      }
      case doubleTag: {
        double vx = x->x()->type()->as_DoubleConstant()->value();
        double vy = x->y()->type()->as_DoubleConstant()->value();
        if (g_isnan(vx) || g_isnan(vy))
          set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1);
        else if (vx == vy)
          set_constant(0);
        else if (vx < vy)
          set_constant(-1);
        else
          set_constant(1);
        break;
      }
    }
  }
}
void Canonicalizer::do_IfInstanceOf(IfInstanceOf*    x) {}
void Canonicalizer::do_IfOp(IfOp* x) {
  move_const_to_right(x);
}
void Canonicalizer::do_Intrinsic      (Intrinsic*       x) {
  switch (x->id()) {
  case vmIntrinsics::_floatToRawIntBits   : {
    FloatConstant* c = x->argument_at(0)->type()->as_FloatConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jfloat(c->value());
      set_constant(v.get_jint());
    }
    break;
  }
  case vmIntrinsics::_intBitsToFloat      : {
    IntConstant* c = x->argument_at(0)->type()->as_IntConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jint(c->value());
      set_constant(v.get_jfloat());
    }
    break;
  }
  case vmIntrinsics::_doubleToRawLongBits : {
    DoubleConstant* c = x->argument_at(0)->type()->as_DoubleConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jdouble(c->value());
      set_constant(v.get_jlong());
    }
    break;
  }
  case vmIntrinsics::_longBitsToDouble    : {
    LongConstant* c = x->argument_at(0)->type()->as_LongConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jlong(c->value());
      set_constant(v.get_jdouble());
    }
    break;
  }
  case vmIntrinsics::_isInstance          : {
    assert(x->number_of_arguments() == 2, "wrong type");
    InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
    if (c != NULL && !c->value()->is_null_object()) {
      ciType* t = c->value()->as_instance()->java_mirror_type();
      if (t->is_klass()) {
        InstanceOf* i = new InstanceOf(t->as_klass(), x->argument_at(1), x->state_before());
        set_canonical(i);
        do_InstanceOf(i);
      } else {
        assert(t->is_primitive_type(), "should be a primitive type");
        set_constant(0);
      }
    }
    break;
  }
  }
}
void Canonicalizer::do_Convert        (Convert*         x) {
  if (x->value()->type()->is_constant()) {
    switch (x->op()) {
    case Bytecodes::_i2b:  set_constant((int)((x->value()->type()->as_IntConstant()->value() << 24) >> 24)); break;
    case Bytecodes::_i2s:  set_constant((int)((x->value()->type()->as_IntConstant()->value() << 16) >> 16)); break;
    case Bytecodes::_i2c:  set_constant((int)(x->value()->type()->as_IntConstant()->value() & ((1<<16)-1))); break;
    case Bytecodes::_i2l:  set_constant((jlong)(x->value()->type()->as_IntConstant()->value()));             break;
    case Bytecodes::_i2f:  set_constant((float)(x->value()->type()->as_IntConstant()->value()));             break;
    case Bytecodes::_i2d:  set_constant((double)(x->value()->type()->as_IntConstant()->value()));            break;
    case Bytecodes::_l2i:  set_constant((int)(x->value()->type()->as_LongConstant()->value()));              break;
    case Bytecodes::_l2f:  set_constant(SharedRuntime::l2f(x->value()->type()->as_LongConstant()->value())); break;
    case Bytecodes::_l2d:  set_constant(SharedRuntime::l2d(x->value()->type()->as_LongConstant()->value())); break;
    case Bytecodes::_f2d:  set_constant((double)(x->value()->type()->as_FloatConstant()->value()));          break;
    case Bytecodes::_f2i:  set_constant(SharedRuntime::f2i(x->value()->type()->as_FloatConstant()->value())); break;
    case Bytecodes::_f2l:  set_constant(SharedRuntime::f2l(x->value()->type()->as_FloatConstant()->value())); break;
    case Bytecodes::_d2f:  set_constant((float)(x->value()->type()->as_DoubleConstant()->value()));          break;
    case Bytecodes::_d2i:  set_constant(SharedRuntime::d2i(x->value()->type()->as_DoubleConstant()->value())); break;
    case Bytecodes::_d2l:  set_constant(SharedRuntime::d2l(x->value()->type()->as_DoubleConstant()->value())); break;
    default:
      ShouldNotReachHere();
    }
  }
  Value value = x->value();
  BasicType type = T_ILLEGAL;
  LoadField* lf = value->as_LoadField();
  if (lf) {
    type = lf->field_type();
  } else {
    LoadIndexed* li = value->as_LoadIndexed();
    if (li) {
      type = li->elt_type();
    } else {
      Convert* conv = value->as_Convert();
      if (conv) {
        switch (conv->op()) {
          case Bytecodes::_i2b: type = T_BYTE;  break;
          case Bytecodes::_i2s: type = T_SHORT; break;
          case Bytecodes::_i2c: type = T_CHAR;  break;
        }
      }
    }
  }
  if (type != T_ILLEGAL) {
    switch (x->op()) {
      case Bytecodes::_i2b: if (type == T_BYTE)                    set_canonical(x->value()); break;
      case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) set_canonical(x->value()); break;
      case Bytecodes::_i2c: if (type == T_CHAR)                    set_canonical(x->value()); break;
    }
  } else {
    Op2* op2 = x->value()->as_Op2();
    if (op2 && op2->op() == Bytecodes::_iand && op2->y()->type()->is_constant()) {
      jint safebits = 0;
      jint mask = op2->y()->type()->as_IntConstant()->value();
      switch (x->op()) {
        case Bytecodes::_i2b: safebits = 0x7f;   break;
        case Bytecodes::_i2s: safebits = 0x7fff; break;
        case Bytecodes::_i2c: safebits = 0xffff; break;
      }
      if (safebits && (mask & ~safebits) == 0) {
        set_canonical(x->value());
      }
    }
  }
}
void Canonicalizer::do_NullCheck      (NullCheck*       x) {
  if (x->obj()->as_NewArray() != NULL || x->obj()->as_NewInstance() != NULL) {
    set_canonical(x->obj());
  } else {
    Constant* con = x->obj()->as_Constant();
    if (con) {
      ObjectType* c = con->type()->as_ObjectType();
      if (c && c->is_loaded()) {
        ObjectConstant* oc = c->as_ObjectConstant();
        if (!oc || !oc->value()->is_null_object()) {
          set_canonical(con);
        }
      }
    }
  }
}
void Canonicalizer::do_TypeCast       (TypeCast*        x) {}
void Canonicalizer::do_Invoke         (Invoke*          x) {}
void Canonicalizer::do_NewInstance    (NewInstance*     x) {}
void Canonicalizer::do_NewTypeArray   (NewTypeArray*    x) {}
void Canonicalizer::do_NewObjectArray (NewObjectArray*  x) {}
void Canonicalizer::do_NewMultiArray  (NewMultiArray*   x) {}
void Canonicalizer::do_CheckCast      (CheckCast*       x) {
  if (x->klass()->is_loaded()) {
    Value obj = x->obj();
    ciType* klass = obj->exact_type();
    if (klass == NULL) klass = obj->declared_type();
    if (klass != NULL && klass->is_loaded() && klass->is_subtype_of(x->klass())) {
      set_canonical(obj);
      return;
    }
    if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) {
      set_canonical(obj);
    }
  }
}
void Canonicalizer::do_InstanceOf     (InstanceOf*      x) {
  if (x->klass()->is_loaded()) {
    Value obj = x->obj();
    ciType* exact = obj->exact_type();
    if (exact != NULL && exact->is_loaded() && (obj->as_NewInstance() || obj->as_NewArray())) {
      set_constant(exact->is_subtype_of(x->klass()) ? 1 : 0);
      return;
    }
    if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) {
      set_constant(0);
    }
  }
}
void Canonicalizer::do_MonitorEnter   (MonitorEnter*    x) {}
void Canonicalizer::do_MonitorExit    (MonitorExit*     x) {}
void Canonicalizer::do_BlockBegin     (BlockBegin*      x) {}
void Canonicalizer::do_Goto           (Goto*            x) {}
static bool is_true(jlong x, If::Condition cond, jlong y) {
  switch (cond) {
    case If::eql: return x == y;
    case If::neq: return x != y;
    case If::lss: return x <  y;
    case If::leq: return x <= y;
    case If::gtr: return x >  y;
    case If::geq: return x >= y;
  }
  ShouldNotReachHere();
  return false;
}
static bool is_safepoint(BlockEnd* x, BlockBegin* sux) {
  return x->is_safepoint() && (sux->bci() < x->state_before()->bci());
}
void Canonicalizer::do_If(If* x) {
  if (x->x()->type()->is_constant()) x->swap_operands();
  const Value l = x->x(); ValueType* lt = l->type();
  const Value r = x->y(); ValueType* rt = r->type();
  if (l == r && !lt->is_float_kind()) {
    BlockBegin* sux = NULL;
    switch (x->cond()) {
    case If::eql: sux = x->sux_for(true);  break;
    case If::neq: sux = x->sux_for(false); break;
    case If::lss: sux = x->sux_for(false); break;
    case If::leq: sux = x->sux_for(true);  break;
    case If::gtr: sux = x->sux_for(false); break;
    case If::geq: sux = x->sux_for(true);  break;
    default: ShouldNotReachHere();
    }
    set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
    return;
  }
  if (lt->is_constant() && rt->is_constant()) {
    if (x->x()->as_Constant() != NULL) {
      BlockBegin* sux = x->x()->as_Constant()->compare(x->cond(), x->y(),
                                                       x->sux_for(true),
                                                       x->sux_for(false));
      if (sux != NULL) {
        set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
      }
    }
  } else if (rt->as_IntConstant() != NULL) {
    const jint rc = rt->as_IntConstant()->value();
    if (l->as_CompareOp() != NULL) {
      CompareOp* cmp = l->as_CompareOp();
      bool unordered_is_less = cmp->op() == Bytecodes::_fcmpl || cmp->op() == Bytecodes::_dcmpl;
      BlockBegin* lss_sux = x->sux_for(is_true(-1, x->cond(), rc)); // successor for a < b
      BlockBegin* eql_sux = x->sux_for(is_true( 0, x->cond(), rc)); // successor for a = b
      BlockBegin* gtr_sux = x->sux_for(is_true(+1, x->cond(), rc)); // successor for a > b
      BlockBegin* nan_sux = unordered_is_less ? lss_sux : gtr_sux ; // successor for unordered
      if (lss_sux == eql_sux && eql_sux == gtr_sux) {
        set_canonical(new Goto(lss_sux, x->state_before(), x->is_safepoint()));
      } else {
        If::Condition cond = If::eql;
        BlockBegin* tsux = NULL;
        BlockBegin* fsux = NULL;
             if (lss_sux == eql_sux) { cond = If::leq; tsux = lss_sux; fsux = gtr_sux; }
        else if (lss_sux == gtr_sux) { cond = If::neq; tsux = lss_sux; fsux = eql_sux; }
        else if (eql_sux == gtr_sux) { cond = If::geq; tsux = eql_sux; fsux = lss_sux; }
        else                         { ShouldNotReachHere();                           }
        If* canon = new If(cmp->x(), cond, nan_sux == tsux, cmp->y(), tsux, fsux, cmp->state_before(), x->is_safepoint());
        if (cmp->x() == cmp->y()) {
          do_If(canon);
        } else {
          if (compilation()->profile_branches()) {
            switch(cmp->op()) {
              case Bytecodes::_fcmpl: case Bytecodes::_fcmpg:
              case Bytecodes::_dcmpl: case Bytecodes::_dcmpg:
                set_canonical(x);
                return;
            }
          }
          set_bci(cmp->state_before()->bci());
          set_canonical(canon);
        }
      }
    } else if (l->as_InstanceOf() != NULL) {
      return;
      InstanceOf* inst = l->as_InstanceOf();
      BlockBegin* is_inst_sux = x->sux_for(is_true(1, x->cond(), rc)); // successor for instanceof == 1
      BlockBegin* no_inst_sux = x->sux_for(is_true(0, x->cond(), rc)); // successor for instanceof == 0
      if (is_inst_sux == no_inst_sux && inst->is_loaded()) {
        set_canonical(new Goto(is_inst_sux, x->state_before(), x->is_safepoint()));
      } else {
        set_canonical(new IfInstanceOf(inst->klass(), inst->obj(), true, inst->state_before()->bci(), is_inst_sux, no_inst_sux));
      }
    }
  } else if (rt == objectNull && (l->as_NewInstance() || l->as_NewArray())) {
    if (x->cond() == Instruction::eql) {
      BlockBegin* sux = x->fsux();
      set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
    } else {
      assert(x->cond() == Instruction::neq, "only other valid case");
      BlockBegin* sux = x->tsux();
      set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
    }
  }
}
void Canonicalizer::do_TableSwitch(TableSwitch* x) {
  if (x->tag()->type()->is_constant()) {
    int v = x->tag()->type()->as_IntConstant()->value();
    BlockBegin* sux = x->default_sux();
    if (v >= x->lo_key() && v <= x->hi_key()) {
      sux = x->sux_at(v - x->lo_key());
    }
    set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
  } else if (x->number_of_sux() == 1) {
    return;
    set_canonical(new Goto(x->default_sux(), x->state_before(), x->is_safepoint()));
  } else if (x->number_of_sux() == 2) {
    return;
    assert(x->lo_key() == x->hi_key(), "keys must be the same");
    Constant* key = new Constant(new IntConstant(x->lo_key()));
    set_canonical(new If(x->tag(), If::eql, true, key, x->sux_at(0), x->default_sux(), x->state_before(), x->is_safepoint()));
  }
}
void Canonicalizer::do_LookupSwitch(LookupSwitch* x) {
  if (x->tag()->type()->is_constant()) {
    int v = x->tag()->type()->as_IntConstant()->value();
    BlockBegin* sux = x->default_sux();
    for (int i = 0; i < x->length(); i++) {
      if (v == x->key_at(i)) {
        sux = x->sux_at(i);
      }
    }
    set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
  } else if (x->number_of_sux() == 1) {
    return;
    set_canonical(new Goto(x->default_sux(), x->state_before(), x->is_safepoint()));
  } else if (x->number_of_sux() == 2) {
    return;
    assert(x->length() == 1, "length must be the same");
    Constant* key = new Constant(new IntConstant(x->key_at(0)));
    set_canonical(new If(x->tag(), If::eql, true, key, x->sux_at(0), x->default_sux(), x->state_before(), x->is_safepoint()));
  }
}
void Canonicalizer::do_Return         (Return*          x) {}
void Canonicalizer::do_Throw          (Throw*           x) {}
void Canonicalizer::do_Base           (Base*            x) {}
void Canonicalizer::do_OsrEntry       (OsrEntry*        x) {}
void Canonicalizer::do_ExceptionObject(ExceptionObject* x) {}
static bool match_index_and_scale(Instruction*  instr,
                                  Instruction** index,
                                  int*          log2_scale) {
#ifndef _LP64
  Convert* convert = instr->as_Convert();
  if (convert != NULL && convert->op() == Bytecodes::_i2l) {
    assert(convert->value()->type() == intType, "invalid input type");
    instr = convert->value();
  }
#endif
  ShiftOp* shift = instr->as_ShiftOp();
  if (shift != NULL) {
    if (shift->op() == Bytecodes::_lshl) {
      assert(shift->x()->type() == longType, "invalid input type");
    } else {
#ifndef _LP64
      if (shift->op() == Bytecodes::_ishl) {
        assert(shift->x()->type() == intType, "invalid input type");
      } else {
        return false;
      }
#else
      return false;
#endif
    }
    Constant* con = shift->y()->as_Constant();
    if (con == NULL) return false;
    IntConstant* val = con->type()->as_IntConstant();
    assert(val != NULL, "Should be an int constant");
    int tmp_scale = val->value();
    if (tmp_scale >= 0 && tmp_scale < 4) {
      return true;
    } else {
      return false;
    }
  }
  ArithmeticOp* arith = instr->as_ArithmeticOp();
  if (arith != NULL) {
    Constant* con = arith->x()->as_Constant();
    if (con != NULL) {
    } else {
      con = arith->y()->as_Constant();
      if (con == NULL) return false;
    }
    long const_value;
    if (arith->op() == Bytecodes::_lmul) {
      assert((*index)->type() == longType, "invalid input type");
      LongConstant* val = con->type()->as_LongConstant();
      assert(val != NULL, "expecting a long constant");
      const_value = val->value();
    } else {
#ifndef _LP64
      if (arith->op() == Bytecodes::_imul) {
        assert((*index)->type() == intType, "invalid input type");
        IntConstant* val = con->type()->as_IntConstant();
        assert(val != NULL, "expecting an int constant");
        const_value = val->value();
      } else {
        return false;
      }
#else
      return false;
#endif
    }
    switch (const_value) {
    case 1: *log2_scale = 0; return true;
    case 2: *log2_scale = 1; return true;
    case 4: *log2_scale = 2; return true;
    case 8: *log2_scale = 3; return true;
    default:            return false;
    }
  }
  return false;
}
static bool match(UnsafeRawOp* x,
                  Instruction** base,
                  Instruction** index,
                  int*          log2_scale) {
  ArithmeticOp* root = x->base()->as_ArithmeticOp();
  if (root == NULL) return false;
  if (root->op() != Bytecodes::_ladd) return false;
  bool match_found = false;
  if (match_index_and_scale(root->y(), index, log2_scale)) {
    match_found = true;
  } else if (match_index_and_scale(root->x(), index, log2_scale)) {
    match_found = true;
  } else if (NOT_LP64(root->y()->as_Convert() != NULL) LP64_ONLY(false)) {
    Convert* convert = root->y()->as_Convert();
    if (convert->op() == Bytecodes::_i2l) {
      assert(convert->value()->type() == intType, "should be an int");
      match_found = true;
    }
  }
  if (!match_found) {
  }
#ifdef AARCH64
  if (*log2_scale != 0 &&
        (1 << *log2_scale) != type2aelembytes(x->basic_type(), true))
    return false;
#endif
  return !root->is_pinned();
}
void Canonicalizer::do_UnsafeRawOp(UnsafeRawOp* x) {
  Instruction* base = NULL;
  Instruction* index = NULL;
  int          log2_scale;
  if (match(x, &base, &index, &log2_scale)) {
    x->set_base(base);
    x->set_index(index);
    x->set_log2_scale(log2_scale);
    if (PrintUnsafeOptimization) {
      tty->print_cr("Canonicalizer: UnsafeRawOp id %d: base = id %d, index = id %d, log2_scale = %d",
                    x->id(), x->base()->id(), x->index()->id(), x->log2_scale());
    }
  }
}
void Canonicalizer::do_RoundFP(RoundFP* x) {}
void Canonicalizer::do_UnsafeGetRaw(UnsafeGetRaw* x) { if (OptimizeUnsafes) do_UnsafeRawOp(x); }
void Canonicalizer::do_UnsafePutRaw(UnsafePutRaw* x) { if (OptimizeUnsafes) do_UnsafeRawOp(x); }
void Canonicalizer::do_UnsafeGetObject(UnsafeGetObject* x) {}
void Canonicalizer::do_UnsafePutObject(UnsafePutObject* x) {}
void Canonicalizer::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {}
void Canonicalizer::do_UnsafePrefetchRead (UnsafePrefetchRead*  x) {}
void Canonicalizer::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {}
void Canonicalizer::do_ProfileCall(ProfileCall* x) {}
void Canonicalizer::do_ProfileReturnType(ProfileReturnType* x) {}
void Canonicalizer::do_ProfileInvoke(ProfileInvoke* x) {}
void Canonicalizer::do_RuntimeCall(RuntimeCall* x) {}
void Canonicalizer::do_RangeCheckPredicate(RangeCheckPredicate* x) {}
#ifdef ASSERT
void Canonicalizer::do_Assert(Assert* x) {}
#endif
void Canonicalizer::do_MemBar(MemBar* x) {}
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Canonicalizer.hpp
#ifndef SHARE_VM_C1_C1_CANONICALIZER_HPP
#define SHARE_VM_C1_C1_CANONICALIZER_HPP
#include "c1/c1_Instruction.hpp"
class Canonicalizer: InstructionVisitor {
 private:
  Compilation *_compilation;
  Instruction* _canonical;
  int _bci;
  Compilation *compilation()                     { return _compilation; }
  void set_canonical(Value x);
  void set_bci(int bci)                          { _bci = bci; }
  void set_constant(jint x)                      { set_canonical(new Constant(new IntConstant(x))); }
  void set_constant(jlong x)                     { set_canonical(new Constant(new LongConstant(x))); }
  void set_constant(jfloat x)                    { set_canonical(new Constant(new FloatConstant(x))); }
  void set_constant(jdouble x)                   { set_canonical(new Constant(new DoubleConstant(x))); }
  void move_const_to_right(Op2* x);
  void do_Op2(Op2* x);
  void do_UnsafeRawOp(UnsafeRawOp* x);
  void unsafe_raw_match(UnsafeRawOp* x,
                        Instruction** base,
                        Instruction** index,
                        int* scale);
 public:
  Canonicalizer(Compilation* c, Value x, int bci) : _compilation(c), _canonical(x), _bci(bci) {
    NOT_PRODUCT(x->set_printable_bci(bci));
    if (CanonicalizeNodes) x->visit(this);
  }
  Value canonical() const                        { return _canonical; }
  int bci() const                                { return _bci; }
  virtual void do_Phi            (Phi*             x);
  virtual void do_Constant       (Constant*        x);
  virtual void do_Local          (Local*           x);
  virtual void do_LoadField      (LoadField*       x);
  virtual void do_StoreField     (StoreField*      x);
  virtual void do_ArrayLength    (ArrayLength*     x);
  virtual void do_LoadIndexed    (LoadIndexed*     x);
  virtual void do_StoreIndexed   (StoreIndexed*    x);
  virtual void do_NegateOp       (NegateOp*        x);
  virtual void do_ArithmeticOp   (ArithmeticOp*    x);
  virtual void do_ShiftOp        (ShiftOp*         x);
  virtual void do_LogicOp        (LogicOp*         x);
  virtual void do_CompareOp      (CompareOp*       x);
  virtual void do_IfOp           (IfOp*            x);
  virtual void do_IfInstanceOf   (IfInstanceOf*    x);
  virtual void do_Convert        (Convert*         x);
  virtual void do_NullCheck      (NullCheck*       x);
  virtual void do_TypeCast       (TypeCast*        x);
  virtual void do_Invoke         (Invoke*          x);
  virtual void do_NewInstance    (NewInstance*     x);
  virtual void do_NewTypeArray   (NewTypeArray*    x);
  virtual void do_NewObjectArray (NewObjectArray*  x);
  virtual void do_NewMultiArray  (NewMultiArray*   x);
  virtual void do_CheckCast      (CheckCast*       x);
  virtual void do_InstanceOf     (InstanceOf*      x);
  virtual void do_MonitorEnter   (MonitorEnter*    x);
  virtual void do_MonitorExit    (MonitorExit*     x);
  virtual void do_Intrinsic      (Intrinsic*       x);
  virtual void do_BlockBegin     (BlockBegin*      x);
  virtual void do_Goto           (Goto*            x);
  virtual void do_If             (If*              x);
  virtual void do_TableSwitch    (TableSwitch*     x);
  virtual void do_LookupSwitch   (LookupSwitch*    x);
  virtual void do_Return         (Return*          x);
  virtual void do_Throw          (Throw*           x);
  virtual void do_Base           (Base*            x);
  virtual void do_OsrEntry       (OsrEntry*        x);
  virtual void do_ExceptionObject(ExceptionObject* x);
  virtual void do_RoundFP        (RoundFP*         x);
  virtual void do_UnsafeGetRaw   (UnsafeGetRaw*    x);
  virtual void do_UnsafePutRaw   (UnsafePutRaw*    x);
  virtual void do_UnsafeGetObject(UnsafeGetObject* x);
  virtual void do_UnsafePutObject(UnsafePutObject* x);
  virtual void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x);
  virtual void do_UnsafePrefetchRead (UnsafePrefetchRead*  x);
  virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x);
  virtual void do_ProfileCall    (ProfileCall*     x);
  virtual void do_ProfileReturnType (ProfileReturnType*  x);
  virtual void do_ProfileInvoke  (ProfileInvoke*   x);
  virtual void do_RuntimeCall    (RuntimeCall*     x);
  virtual void do_MemBar         (MemBar*          x);
  virtual void do_RangeCheckPredicate(RangeCheckPredicate* x);
#ifdef ASSERT
  virtual void do_Assert         (Assert*          x);
#endif
};
#endif // SHARE_VM_C1_C1_CANONICALIZER_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_CFGPrinter.cpp
#include "precompiled.hpp"
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_ValueStack.hpp"
#ifndef PRODUCT
class CFGPrinterOutput : public CHeapObj<mtCompiler> {
 private:
  outputStream* _output;
  Compilation*  _compilation;
  bool _do_print_HIR;
  bool _do_print_LIR;
  class PrintBlockClosure: public BlockClosure {
    void block_do(BlockBegin* block) { if (block != NULL) CFGPrinter::output()->print_block(block); }
  };
  outputStream* output() { assert(_output != NULL, ""); return _output; }
  void inc_indent();
  void dec_indent();
  void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
  void print_begin(const char* tag);
  void print_end(const char* tag);
  char* method_name(ciMethod* method, bool short_name = false);
 public:
  CFGPrinterOutput();
  void set_compilation(Compilation* compilation) { _compilation = compilation; }
  void set_print_flags(bool do_print_HIR, bool do_print_LIR) { _do_print_HIR = do_print_HIR; _do_print_LIR = do_print_LIR; }
  void print_compilation();
  void print_intervals(IntervalList* intervals, const char* name);
  void print_state(BlockBegin* block);
  void print_operand(Value instr);
  void print_HIR(Value instr);
  void print_HIR(BlockBegin* block);
  void print_LIR(BlockBegin* block);
  void print_block(BlockBegin* block);
  void print_cfg(BlockList* blocks, const char* name);
  void print_cfg(IR* blocks, const char* name);
};
CFGPrinterOutput* CFGPrinter::_output = NULL;
void CFGPrinter::print_compilation(Compilation* compilation) {
  if (_output == NULL) {
    _output = new CFGPrinterOutput();
  }
  output()->set_compilation(compilation);
  output()->print_compilation();
}
void CFGPrinter::print_cfg(BlockList* blocks, const char* name, bool do_print_HIR, bool do_print_LIR) {
  output()->set_print_flags(do_print_HIR, do_print_LIR);
  output()->print_cfg(blocks, name);
}
void CFGPrinter::print_cfg(IR* blocks, const char* name, bool do_print_HIR, bool do_print_LIR) {
  output()->set_print_flags(do_print_HIR, do_print_LIR);
  output()->print_cfg(blocks, name);
}
void CFGPrinter::print_intervals(IntervalList* intervals, const char* name) {
  output()->print_intervals(intervals, name);
}
CFGPrinterOutput::CFGPrinterOutput()
 : _output(new(ResourceObj::C_HEAP, mtCompiler) fileStream("output.cfg"))
{
}
void CFGPrinterOutput::inc_indent() {
  output()->inc();
  output()->inc();
}
void CFGPrinterOutput::dec_indent() {
  output()->dec();
  output()->dec();
}
void CFGPrinterOutput::print(const char* format, ...) {
  output()->indent();
  va_list ap;
  va_start(ap, format);
  output()->vprint_cr(format, ap);
  va_end(ap);
}
void CFGPrinterOutput::print_begin(const char* tag) {
  output()->indent();
  output()->print_cr("begin_%s", tag);
  inc_indent();
}
void CFGPrinterOutput::print_end(const char* tag) {
  dec_indent();
  output()->indent();
  output()->print_cr("end_%s", tag);
}
char* CFGPrinterOutput::method_name(ciMethod* method, bool short_name) {
  stringStream name;
  if (short_name) {
    method->print_short_name(&name);
  } else {
    method->print_name(&name);
  }
  return name.as_string();
}
void CFGPrinterOutput::print_compilation() {
  print_begin("compilation");
  print("name \"%s\"", method_name(_compilation->method(), true));
  print("method \"%s\"", method_name(_compilation->method()));
  print("date " INT64_FORMAT, (int64_t) os::javaTimeMillis());
  print_end("compilation");
}
void CFGPrinterOutput::print_state(BlockBegin* block) {
  print_begin("states");
  InstructionPrinter ip(true, output());
  ValueStack* state = block->state();
  int index;
  Value value;
  for_each_state(state) {
    print_begin("locals");
    print("size %d", state->locals_size());
    print("method \"%s\"", method_name(state->scope()->method()));
    for_each_local_value(state, index, value) {
      ip.print_phi(index, value, block);
      print_operand(value);
      output()->cr();
    }
    print_end("locals");
    if (state->stack_size() > 0) {
      print_begin("stack");
      print("size %d", state->stack_size());
      print("method \"%s\"", method_name(state->scope()->method()));
      for_each_stack_value(state, index, value) {
        ip.print_phi(index, value, block);
        print_operand(value);
        output()->cr();
      }
      print_end("stack");
    }
    if (state->locks_size() > 0) {
      print_begin("locks");
      print("size %d", state->locks_size());
      print("method \"%s\"", method_name(state->scope()->method()));
      for_each_lock_value(state, index, value) {
        ip.print_phi(index, value, block);
        print_operand(value);
        output()->cr();
      }
      print_end("locks");
    }
  }
  print_end("states");
}
void CFGPrinterOutput::print_operand(Value instr) {
  if (instr->operand()->is_virtual()) {
    output()->print(" \"");
    instr->operand()->print(output());
    output()->print("\" ");
  }
}
void CFGPrinterOutput::print_HIR(Value instr) {
  InstructionPrinter ip(true, output());
  if (instr->is_pinned()) {
    output()->put('.');
  }
  output()->print("%d %d ", instr->printable_bci(), instr->use_count());
  print_operand(instr);
  ip.print_temp(instr);
  output()->print(" ");
  ip.print_instr(instr);
  output()->print_cr(" <|@");
}
void CFGPrinterOutput::print_HIR(BlockBegin* block) {
  print_begin("HIR");
  Value cur = block->next();
  while (cur != NULL) {
    print_HIR(cur);
    cur = cur->next();
  }
  print_end("HIR");
}
void CFGPrinterOutput::print_LIR(BlockBegin* block) {
  print_begin("LIR");
  for (int i = 0; i < block->lir()->length(); i++) {
    block->lir()->at(i)->print_on(output());
    output()->print_cr(" <|@ ");
  }
  print_end("LIR");
}
void CFGPrinterOutput::print_block(BlockBegin* block) {
  print_begin("block");
  print("name \"B%d\"", block->block_id());
  print("from_bci %d", block->bci());
  print("to_bci %d", (block->end() == NULL ? -1 : block->end()->printable_bci()));
  output()->indent();
  output()->print("predecessors ");
  int i;
  for (i = 0; i < block->number_of_preds(); i++) {
    output()->print("\"B%d\" ", block->pred_at(i)->block_id());
  }
  output()->cr();
  output()->indent();
  output()->print("successors ");
  for (i = 0; i < block->number_of_sux(); i++) {
    output()->print("\"B%d\" ", block->sux_at(i)->block_id());
  }
  output()->cr();
  output()->indent();
  output()->print("xhandlers");
  for (i = 0; i < block->number_of_exception_handlers(); i++) {
    output()->print("\"B%d\" ", block->exception_handler_at(i)->block_id());
  }
  output()->cr();
  output()->indent();
  output()->print("flags ");
  if (block->is_set(BlockBegin::std_entry_flag))                output()->print("\"std\" ");
  if (block->is_set(BlockBegin::osr_entry_flag))                output()->print("\"osr\" ");
  if (block->is_set(BlockBegin::exception_entry_flag))          output()->print("\"ex\" ");
  if (block->is_set(BlockBegin::subroutine_entry_flag))         output()->print("\"sr\" ");
  if (block->is_set(BlockBegin::backward_branch_target_flag))   output()->print("\"bb\" ");
  if (block->is_set(BlockBegin::parser_loop_header_flag))       output()->print("\"plh\" ");
  if (block->is_set(BlockBegin::critical_edge_split_flag))      output()->print("\"ces\" ");
  if (block->is_set(BlockBegin::linear_scan_loop_header_flag))  output()->print("\"llh\" ");
  if (block->is_set(BlockBegin::linear_scan_loop_end_flag))     output()->print("\"lle\" ");
  output()->cr();
  if (block->dominator() != NULL) {
    print("dominator \"B%d\"", block->dominator()->block_id());
  }
  if (block->loop_index() != -1) {
    print("loop_index %d", block->loop_index());
    print("loop_depth %d", block->loop_depth());
  }
  if (block->first_lir_instruction_id() != -1) {
    print("first_lir_id %d", block->first_lir_instruction_id());
    print("last_lir_id %d", block->last_lir_instruction_id());
  }
  if (_do_print_HIR) {
    print_state(block);
    print_HIR(block);
  }
  if (_do_print_LIR) {
    print_LIR(block);
  }
  print_end("block");
}
void CFGPrinterOutput::print_cfg(BlockList* blocks, const char* name) {
  print_begin("cfg");
  print("name \"%s\"", name);
  PrintBlockClosure print_block;
  blocks->iterate_forward(&print_block);
  print_end("cfg");
  output()->flush();
}
void CFGPrinterOutput::print_cfg(IR* blocks, const char* name) {
  print_begin("cfg");
  print("name \"%s\"", name);
  PrintBlockClosure print_block;
  blocks->iterate_preorder(&print_block);
  print_end("cfg");
  output()->flush();
}
void CFGPrinterOutput::print_intervals(IntervalList* intervals, const char* name) {
  print_begin("intervals");
  print("name \"%s\"", name);
  for (int i = 0; i < intervals->length(); i++) {
    if (intervals->at(i) != NULL) {
      intervals->at(i)->print(output());
    }
  }
  print_end("intervals");
  output()->flush();
}
#endif
C:\hotspot-69087d08d473\src\share\vm/c1/c1_CFGPrinter.hpp
#ifndef SHARE_VM_C1_C1_CFGPRINTER_HPP
#define SHARE_VM_C1_C1_CFGPRINTER_HPP
#include "c1/c1_Compilation.hpp"
#include "c1/c1_Instruction.hpp"
#ifndef PRODUCT
class CFGPrinterOutput;
class IntervalList;
class CFGPrinter : public AllStatic {
private:
  static CFGPrinterOutput* _output;
public:
  static CFGPrinterOutput* output() { assert(_output != NULL, ""); return _output; }
  static void print_compilation(Compilation* compilation);
  static void print_cfg(BlockList* blocks, const char* name, bool do_print_HIR, bool do_print_LIR);
  static void print_cfg(IR* blocks, const char* name, bool do_print_HIR, bool do_print_LIR);
  static void print_intervals(IntervalList* intervals, const char* name);
};
#endif
#endif // SHARE_VM_C1_C1_CFGPRINTER_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_CodeStubs.hpp
#ifndef SHARE_VM_C1_C1_CODESTUBS_HPP
#define SHARE_VM_C1_C1_CODESTUBS_HPP
#include "c1/c1_FrameMap.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_Runtime1.hpp"
#include "utilities/array.hpp"
#include "utilities/macros.hpp"
class CodeEmitInfo;
class LIR_Assembler;
class LIR_OpVisitState;
class CodeStub: public CompilationResourceObj {
 protected:
  Label _entry;                                  // label at the stub entry point
  Label _continuation;                           // label where stub continues, if any
 public:
  CodeStub() {}
  void assert_no_unbound_labels()                { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); }
  virtual void emit_code(LIR_Assembler* e) = 0;
  virtual CodeEmitInfo* info() const             { return NULL; }
  virtual bool is_exception_throw_stub() const   { return false; }
  virtual bool is_range_check_stub() const       { return false; }
  virtual bool is_divbyzero_stub() const         { return false; }
  virtual bool is_simple_exception_stub() const  { return false; }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const = 0;
#endif
  Label* entry()                                 { return &_entry; }
  Label* continuation()                          { return &_continuation; }
  virtual void visit(LIR_OpVisitState* visit) {
#ifndef PRODUCT
    if (LIRTracePeephole && Verbose) {
      tty->print("no visitor for ");
      print_name(tty);
      tty->cr();
    }
#endif
  }
};
define_array(CodeStubArray, CodeStub*)
define_stack(_CodeStubList, CodeStubArray)
class CodeStubList: public _CodeStubList {
 public:
  CodeStubList(): _CodeStubList() {}
  void append(CodeStub* stub) {
    if (!contains(stub)) {
      _CodeStubList::append(stub);
    }
  }
};
class CounterOverflowStub: public CodeStub {
 private:
  CodeEmitInfo* _info;
  int           _bci;
  LIR_Opr       _method;
public:
  CounterOverflowStub(CodeEmitInfo* info, int bci, LIR_Opr method) :  _info(info), _bci(bci), _method(method) {
  }
  virtual void emit_code(LIR_Assembler* e);
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
    visitor->do_input(_method);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); }
#endif // PRODUCT
};
class ConversionStub: public CodeStub {
 private:
  Bytecodes::Code _bytecode;
  LIR_Opr         _input;
  LIR_Opr         _result;
  static float float_zero;
  static double double_zero;
 public:
  ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result)
    : _bytecode(bytecode), _input(input), _result(result) {
  }
  Bytecodes::Code bytecode() { return _bytecode; }
  LIR_Opr         input()    { return _input; }
  LIR_Opr         result()   { return _result; }
  virtual void emit_code(LIR_Assembler* e);
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case();
    visitor->do_input(_input);
    visitor->do_output(_result);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("ConversionStub"); }
#endif // PRODUCT
};
class RangeCheckStub: public CodeStub {
 private:
  CodeEmitInfo* _info;
  LIR_Opr       _index;
  bool          _throw_index_out_of_bounds_exception;
 public:
  RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, bool throw_index_out_of_bounds_exception = false);
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual bool is_exception_throw_stub() const   { return true; }
  virtual bool is_range_check_stub() const       { return true; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
    visitor->do_input(_index);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); }
#endif // PRODUCT
};
class PredicateFailedStub: public CodeStub {
 private:
  CodeEmitInfo* _info;
 public:
  PredicateFailedStub(CodeEmitInfo* info);
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("PredicateFailedStub"); }
#endif // PRODUCT
};
class DivByZeroStub: public CodeStub {
 private:
  CodeEmitInfo* _info;
  int           _offset;
 public:
  DivByZeroStub(CodeEmitInfo* info)
    : _info(info), _offset(-1) {
  }
  DivByZeroStub(int offset, CodeEmitInfo* info)
    : _info(info), _offset(offset) {
  }
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual bool is_exception_throw_stub() const   { return true; }
  virtual bool is_divbyzero_stub() const         { return true; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); }
#endif // PRODUCT
};
class ImplicitNullCheckStub: public CodeStub {
 private:
  CodeEmitInfo* _info;
  int           _offset;
 public:
  ImplicitNullCheckStub(int offset, CodeEmitInfo* info)
    : _offset(offset), _info(info) {
  }
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual bool is_exception_throw_stub() const   { return true; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); }
#endif // PRODUCT
};
class NewInstanceStub: public CodeStub {
 private:
  ciInstanceKlass* _klass;
  LIR_Opr          _klass_reg;
  LIR_Opr          _result;
  CodeEmitInfo*    _info;
  Runtime1::StubID _stub_id;
 public:
  NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id);
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
    visitor->do_input(_klass_reg);
    visitor->do_output(_result);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); }
#endif // PRODUCT
};
class NewTypeArrayStub: public CodeStub {
 private:
  LIR_Opr       _klass_reg;
  LIR_Opr       _length;
  LIR_Opr       _result;
  CodeEmitInfo* _info;
 public:
  NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
    visitor->do_input(_klass_reg);
    visitor->do_input(_length);
    assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); }
#endif // PRODUCT
};
class NewObjectArrayStub: public CodeStub {
 private:
  LIR_Opr        _klass_reg;
  LIR_Opr        _length;
  LIR_Opr        _result;
  CodeEmitInfo*  _info;
 public:
  NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
    visitor->do_input(_klass_reg);
    visitor->do_input(_length);
    assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); }
#endif // PRODUCT
};
class MonitorAccessStub: public CodeStub {
 protected:
  LIR_Opr _obj_reg;
  LIR_Opr _lock_reg;
 public:
  MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) {
    _obj_reg  = obj_reg;
    _lock_reg  = lock_reg;
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); }
#endif // PRODUCT
};
class MonitorEnterStub: public MonitorAccessStub {
 private:
  CodeEmitInfo* _info;
 public:
  MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info);
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_input(_obj_reg);
    visitor->do_input(_lock_reg);
    visitor->do_slow_case(_info);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); }
#endif // PRODUCT
};
class MonitorExitStub: public MonitorAccessStub {
 private:
  bool _compute_lock;
  int  _monitor_ix;
 public:
  MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix)
    : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg),
      _compute_lock(compute_lock), _monitor_ix(monitor_ix) { }
  virtual void emit_code(LIR_Assembler* e);
  virtual void visit(LIR_OpVisitState* visitor) {
    assert(_obj_reg->is_illegal(), "unused");
    if (_compute_lock) {
      visitor->do_temp(_lock_reg);
    } else {
      visitor->do_input(_lock_reg);
    }
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); }
#endif // PRODUCT
};
class PatchingStub: public CodeStub {
 public:
  enum PatchID {
    access_field_id,
    load_klass_id,
    load_mirror_id,
    load_appendix_id
  };
  enum constants {
    patch_info_size = 3
  };
 private:
  PatchID       _id;
  address       _pc_start;
  int           _bytes_to_copy;
  Label         _patched_code_entry;
  Label         _patch_site_entry;
  Label         _patch_site_continuation;
  Register      _obj;
  CodeEmitInfo* _info;
  int           _index;  // index of the patchable oop or Klass* in nmethod oop or metadata table if needed
  static int    _patch_info_offset;
  void align_patch_site(MacroAssembler* masm);
 public:
  static int patch_info_offset() { return _patch_info_offset; }
  PatchingStub(MacroAssembler* masm, PatchID id, int index = -1):
      _id(id)
    , _info(NULL)
    , _index(index) {
    if (os::is_MP()) {
      align_patch_site(masm);
    }
    _pc_start = masm->pc();
    masm->bind(_patch_site_entry);
  }
  void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
    _info = info;
    _obj = obj;
    masm->bind(_patch_site_continuation);
    _bytes_to_copy = masm->pc() - pc_start();
    if (_id == PatchingStub::access_field_id) {
      int field_offset = 0;
      switch (patch_code) {
      case lir_patch_low:         field_offset = lo_word_offset_in_bytes; break;
      case lir_patch_high:        field_offset = hi_word_offset_in_bytes; break;
      case lir_patch_normal:      field_offset = 0;                       break;
      default: ShouldNotReachHere();
      }
      NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());
      n_move->set_offset(field_offset);
    } else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) {
      assert(_obj != noreg, "must have register object for load_klass/load_mirror");
#ifdef ASSERT
      nativeMovConstReg_at(pc_start());
#endif
    } else {
      ShouldNotReachHere();
    }
    assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes");
  }
  address pc_start() const                       { return _pc_start; }
  PatchID id() const                             { return _id; }
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("PatchingStub"); }
#endif // PRODUCT
};
class DeoptimizeStub : public CodeStub {
private:
  CodeEmitInfo* _info;
public:
  DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {}
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const           { return _info; }
  virtual bool is_exception_throw_stub() const { return true; }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case(_info);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); }
#endif // PRODUCT
};
class SimpleExceptionStub: public CodeStub {
 private:
  LIR_Opr          _obj;
  Runtime1::StubID _stub;
  CodeEmitInfo*    _info;
 public:
  SimpleExceptionStub(Runtime1::StubID stub, LIR_Opr obj, CodeEmitInfo* info):
    _obj(obj), _info(info), _stub(stub) {
  }
  void set_obj(LIR_Opr obj) {
    _obj = obj;
  }
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const             { return _info; }
  virtual bool is_exception_throw_stub() const   { return true; }
  virtual bool is_simple_exception_stub() const  { return true; }
  virtual void visit(LIR_OpVisitState* visitor) {
    if (_obj->is_valid()) visitor->do_input(_obj);
    visitor->do_slow_case(_info);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); }
#endif // PRODUCT
};
class ArrayStoreExceptionStub: public SimpleExceptionStub {
 private:
  CodeEmitInfo* _info;
 public:
  ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {}
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }
#endif // PRODUCT
};
class ArrayCopyStub: public CodeStub {
 private:
  LIR_OpArrayCopy* _op;
 public:
  ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) { }
  LIR_Opr src() const                         { return _op->src(); }
  LIR_Opr src_pos() const                     { return _op->src_pos(); }
  LIR_Opr dst() const                         { return _op->dst(); }
  LIR_Opr dst_pos() const                     { return _op->dst_pos(); }
  LIR_Opr length() const                      { return _op->length(); }
  LIR_Opr tmp() const                         { return _op->tmp(); }
  virtual void emit_code(LIR_Assembler* e);
  virtual CodeEmitInfo* info() const          { return _op->info(); }
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case();
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); }
#endif // PRODUCT
};
#if INCLUDE_ALL_GCS
class G1PreBarrierStub: public CodeStub {
 private:
  bool _do_load;
  LIR_Opr _addr;
  LIR_Opr _pre_val;
  LIR_PatchCode _patch_code;
  CodeEmitInfo* _info;
 public:
  G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) :
    _addr(addr), _pre_val(pre_val), _do_load(true),
    _patch_code(patch_code), _info(info)
  {
    assert(_pre_val->is_register(), "should be temporary register");
    assert(_addr->is_address(), "should be the address of the field");
  }
  G1PreBarrierStub(LIR_Opr pre_val) :
    _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false),
    _patch_code(lir_patch_none), _info(NULL)
  {
    assert(_pre_val->is_register(), "should be a register");
  }
  LIR_Opr addr() const { return _addr; }
  LIR_Opr pre_val() const { return _pre_val; }
  LIR_PatchCode patch_code() const { return _patch_code; }
  CodeEmitInfo* info() const { return _info; }
  bool do_load() const { return _do_load; }
  virtual void emit_code(LIR_Assembler* e);
  virtual void visit(LIR_OpVisitState* visitor) {
    if (_do_load) {
      if (_info != NULL)
        visitor->do_slow_case(_info);
      else
        visitor->do_slow_case();
      visitor->do_input(_addr);
      visitor->do_temp(_pre_val);
    } else {
      visitor->do_slow_case();
      visitor->do_input(_pre_val);
    }
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); }
#endif // PRODUCT
};
class G1PostBarrierStub: public CodeStub {
 private:
  LIR_Opr _addr;
  LIR_Opr _new_val;
  static jbyte* _byte_map_base;
  static jbyte* byte_map_base_slow();
  static jbyte* byte_map_base() {
    if (_byte_map_base == NULL) {
      _byte_map_base = byte_map_base_slow();
    }
    return _byte_map_base;
  }
 public:
  G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { }
  LIR_Opr addr() const { return _addr; }
  LIR_Opr new_val() const { return _new_val; }
  virtual void emit_code(LIR_Assembler* e);
  virtual void visit(LIR_OpVisitState* visitor) {
    visitor->do_slow_case();
    visitor->do_input(_addr);
    visitor->do_input(_new_val);
  }
#ifndef PRODUCT
  virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); }
#endif // PRODUCT
};
#endif // INCLUDE_ALL_GCS
#endif // SHARE_VM_C1_C1_CODESTUBS_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Compilation.cpp
#include "precompiled.hpp"
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_Compilation.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_LIRAssembler.hpp"
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "c1/c1_ValueMap.hpp"
#include "c1/c1_ValueStack.hpp"
#include "code/debugInfoRec.hpp"
#include "compiler/compileLog.hpp"
#include "c1/c1_RangeCheckElimination.hpp"
typedef enum {
  _t_compile,
  _t_setup,
  _t_buildIR,
  _t_optimize_blocks,
  _t_optimize_null_checks,
  _t_rangeCheckElimination,
  _t_emit_lir,
  _t_linearScan,
  _t_lirGeneration,
  _t_lir_schedule,
  _t_codeemit,
  _t_codeinstall,
  max_phase_timers
} TimerName;
static const char * timer_name[] = {
  "compile",
  "setup",
  "buildIR",
  "optimize_blocks",
  "optimize_null_checks",
  "rangeCheckElimination",
  "emit_lir",
  "linearScan",
  "lirGeneration",
  "lir_schedule",
  "codeemit",
  "codeinstall"
};
static elapsedTimer timers[max_phase_timers];
static int totalInstructionNodes = 0;
class PhaseTraceTime: public TraceTime {
 private:
  JavaThread* _thread;
  CompileLog* _log;
  TimerName _timer;
 public:
  PhaseTraceTime(TimerName timer)
  : TraceTime("", &timers[timer], CITime || CITimeEach, Verbose),
    _log(NULL), _timer(timer)
  {
    if (Compilation::current() != NULL) {
      _log = Compilation::current()->log();
    }
    if (_log != NULL) {
      _log->begin_head("phase name='%s'", timer_name[_timer]);
      _log->stamp();
      _log->end_head();
    }
  }
  ~PhaseTraceTime() {
    if (_log != NULL)
      _log->done("phase name='%s'", timer_name[_timer]);
  }
};
#ifndef PRODUCT
void Compilation::maybe_print_current_instruction() {
  if (_current_instruction != NULL && _last_instruction_printed != _current_instruction) {
    _last_instruction_printed = _current_instruction;
    _current_instruction->print_line();
  }
}
#endif // PRODUCT
DebugInformationRecorder* Compilation::debug_info_recorder() const {
  return _env->debug_info();
}
Dependencies* Compilation::dependency_recorder() const {
  return _env->dependencies();
}
void Compilation::initialize() {
  OopRecorder* ooprec = new OopRecorder(_env->arena());
  _env->set_oop_recorder(ooprec);
  _env->set_debug_info(new DebugInformationRecorder(ooprec));
  debug_info_recorder()->set_oopmaps(new OopMapSet());
  _env->set_dependencies(new Dependencies(_env));
}
void Compilation::build_hir() {
  CHECK_BAILOUT();
  CompileLog* log = this->log();
  if (log != NULL) {
    log->begin_head("parse method='%d' ",
                    log->identify(_method));
    log->stamp();
    log->end_head();
  }
  _hir = new IR(this, method(), osr_bci());
  if (log)  log->done("parse");
  if (!_hir->is_valid()) {
    bailout("invalid parsing");
    return;
  }
#ifndef PRODUCT
  if (PrintCFGToFile) {
    CFGPrinter::print_cfg(_hir, "After Generation of HIR", true, false);
  }
#endif
#ifndef PRODUCT
  if (PrintCFG || PrintCFG0) { tty->print_cr("CFG after parsing"); _hir->print(true); }
  if (PrintIR  || PrintIR0 ) { tty->print_cr("IR after parsing"); _hir->print(false); }
#endif
  _hir->verify();
  if (UseC1Optimizations) {
    NEEDS_CLEANUP
    PhaseTraceTime timeit(_t_optimize_blocks);
    _hir->optimize_blocks();
  }
  _hir->verify();
  _hir->split_critical_edges();
#ifndef PRODUCT
  if (PrintCFG || PrintCFG1) { tty->print_cr("CFG after optimizations"); _hir->print(true); }
  if (PrintIR  || PrintIR1 ) { tty->print_cr("IR after optimizations"); _hir->print(false); }
#endif
  _hir->verify();
  _hir->compute_code();
  if (UseGlobalValueNumbering) {
    int instructions = Instruction::number_of_instructions();
    GlobalValueNumbering gvn(_hir);
    assert(instructions == Instruction::number_of_instructions(),
           "shouldn't have created an instructions");
  }
  _hir->verify();
#ifndef PRODUCT
  if (PrintCFGToFile) {
    CFGPrinter::print_cfg(_hir, "Before RangeCheckElimination", true, false);
  }
#endif
  if (RangeCheckElimination) {
    if (_hir->osr_entry() == NULL) {
      PhaseTraceTime timeit(_t_rangeCheckElimination);
      RangeCheckElimination::eliminate(_hir);
    }
  }
#ifndef PRODUCT
  if (PrintCFGToFile) {
    CFGPrinter::print_cfg(_hir, "After RangeCheckElimination", true, false);
  }
#endif
  if (UseC1Optimizations) {
    NEEDS_CLEANUP
    PhaseTraceTime timeit(_t_optimize_null_checks);
    _hir->eliminate_null_checks();
  }
  _hir->verify();
  _hir->compute_use_counts();
#ifndef PRODUCT
  if (PrintCFG || PrintCFG2) { tty->print_cr("CFG before code generation"); _hir->code()->print(true); }
  if (PrintIR  || PrintIR2 ) { tty->print_cr("IR before code generation"); _hir->code()->print(false, true); }
#endif
  _hir->verify();
}
void Compilation::emit_lir() {
  CHECK_BAILOUT();
  LIRGenerator gen(this, method());
  {
    PhaseTraceTime timeit(_t_lirGeneration);
    hir()->iterate_linear_scan_order(&gen);
  }
  CHECK_BAILOUT();
  {
    PhaseTraceTime timeit(_t_linearScan);
    LinearScan* allocator = new LinearScan(hir(), &gen, frame_map());
    set_allocator(allocator);
    allocator->do_linear_scan();
    CHECK_BAILOUT();
    _max_spills = allocator->max_spills();
  }
  if (BailoutAfterLIR) {
    if (PrintLIR && !bailed_out()) {
      print_LIR(hir()->code());
    }
    bailout("Bailing out because of -XX:+BailoutAfterLIR");
  }
}
void Compilation::emit_code_epilog(LIR_Assembler* assembler) {
  CHECK_BAILOUT();
  CodeOffsets* code_offsets = assembler->offsets();
  assembler->emit_slow_case_stubs();
  CHECK_BAILOUT();
  assembler->emit_exception_entries(exception_info_list());
  CHECK_BAILOUT();
  code_offsets->set_value(CodeOffsets::Exceptions, assembler->emit_exception_handler());
  CHECK_BAILOUT();
  code_offsets->set_value(CodeOffsets::Deopt, assembler->emit_deopt_handler());
  CHECK_BAILOUT();
  if (has_method_handle_invokes()) {
    code_offsets->set_value(CodeOffsets::DeoptMH, assembler->emit_deopt_handler());
    CHECK_BAILOUT();
  }
  offsets()->set_value(CodeOffsets::UnwindHandler, assembler->emit_unwind_handler());
  masm()->flush();
}
bool Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) {
  int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo));
  char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size);
  code->insts()->initialize_shared_locs((relocInfo*)locs_buffer,
                                        locs_buffer_size / sizeof(relocInfo));
  code->initialize_consts_size(Compilation::desired_max_constant_size());
  int stub_size = (call_stub_estimate * LIR_Assembler::call_stub_size) +
                   LIR_Assembler::exception_handler_size +
                   (2 * LIR_Assembler::deopt_handler_size);
  if (stub_size >= code->insts_capacity()) return false;
  code->initialize_stubs_size(stub_size);
  return true;
}
int Compilation::emit_code_body() {
  if (!setup_code_buffer(code(), allocator()->num_calls())) {
    BAILOUT_("size requested greater than avail code buffer size", 0);
  }
  code()->initialize_oop_recorder(env()->oop_recorder());
  _masm = new C1_MacroAssembler(code());
  _masm->set_oop_recorder(env()->oop_recorder());
  LIR_Assembler lir_asm(this);
  lir_asm.emit_code(hir()->code());
  CHECK_BAILOUT_(0);
  emit_code_epilog(&lir_asm);
  CHECK_BAILOUT_(0);
  generate_exception_handler_table();
#ifndef PRODUCT
  if (PrintExceptionHandlers && Verbose) {
    exception_handler_table()->print();
  }
#endif /* PRODUCT */
  return frame_map()->framesize();
}
int Compilation::compile_java_method() {
  assert(!method()->is_native(), "should not reach here");
  if (BailoutOnExceptionHandlers) {
    if (method()->has_exception_handlers()) {
      bailout("linear scan can't handle exception handlers");
    }
  }
  CHECK_BAILOUT_(no_frame_size);
  if (is_profiling() && !method()->ensure_method_data()) {
    BAILOUT_("mdo allocation failed", no_frame_size);
  }
  {
    PhaseTraceTime timeit(_t_buildIR);
    build_hir();
  }
  if (BailoutAfterHIR) {
    BAILOUT_("Bailing out because of -XX:+BailoutAfterHIR", no_frame_size);
  }
  {
    PhaseTraceTime timeit(_t_emit_lir);
    _frame_map = new FrameMap(method(), hir()->number_of_locks(), MAX2(4, hir()->max_stack()));
    emit_lir();
  }
  CHECK_BAILOUT_(no_frame_size);
  {
    PhaseTraceTime timeit(_t_codeemit);
    return emit_code_body();
  }
}
void Compilation::install_code(int frame_size) {
  assert(frame_size == frame_map()->framesize(), "must match");
  assert(in_bytes(frame_map()->framesize_in_bytes()) % sizeof(intptr_t) == 0, "must be at least pointer aligned");
  _env->register_method(
    method(),
    osr_bci(),
    &_offsets,
    in_bytes(_frame_map->sp_offset_for_orig_pc()),
    code(),
    in_bytes(frame_map()->framesize_in_bytes()) / sizeof(intptr_t),
    debug_info_recorder()->_oopmaps,
    exception_handler_table(),
    implicit_exception_table(),
    compiler(),
    _env->comp_level(),
    has_unsafe_access(),
    SharedRuntime::is_wide_vector(max_vector_size())
  );
}
void Compilation::compile_method() {
  initialize();
  if (!method()->can_be_compiled()) {
    bailout("Bailing out because method is not compilable");
    return;
  }
  if (_env->jvmti_can_hotswap_or_post_breakpoint()) {
    dependency_recorder()->assert_evol_method(method());
  }
  if (method()->break_at_execute()) {
    BREAKPOINT;
  }
#ifndef PRODUCT
  if (PrintCFGToFile) {
    CFGPrinter::print_compilation(this);
  }
#endif
  int frame_size = compile_java_method();
  CHECK_BAILOUT();
  if (InstallMethods) {
    PhaseTraceTime timeit(_t_codeinstall);
    install_code(frame_size);
  }
  if (log() != NULL) // Print code cache state into compiler log
    log()->code_cache_state();
  totalInstructionNodes += Instruction::number_of_instructions();
}
void Compilation::generate_exception_handler_table() {
  ExceptionInfoList* info_list = exception_info_list();
  if (info_list->length() == 0) {
    return;
  }
  const int num_handlers = 5;
  GrowableArray<intptr_t>* bcis = new GrowableArray<intptr_t>(num_handlers);
  GrowableArray<intptr_t>* scope_depths = new GrowableArray<intptr_t>(num_handlers);
  GrowableArray<intptr_t>* pcos = new GrowableArray<intptr_t>(num_handlers);
  for (int i = 0; i < info_list->length(); i++) {
    ExceptionInfo* info = info_list->at(i);
    XHandlers* handlers = info->exception_handlers();
    bcis->trunc_to(0);
    scope_depths->trunc_to(0);
    pcos->trunc_to(0);
    for (int i = 0; i < handlers->length(); i++) {
      XHandler* handler = handlers->handler_at(i);
      assert(handler->entry_pco() != -1, "must have been generated");
      int e = bcis->find(handler->handler_bci());
      if (e >= 0 && scope_depths->at(e) == handler->scope_count()) {
        continue;
      }
      bcis->append(handler->handler_bci());
      if (handler->handler_bci() == -1) {
        scope_depths->append(0);
      } else {
        scope_depths->append(handler->scope_count());
    }
      pcos->append(handler->entry_pco());
      if (handler->is_catch_all()) {
        assert(i == handlers->length() - 1, "catch all must be last handler");
  }
    }
    exception_handler_table()->add_subtable(info->pco(), bcis, scope_depths, pcos);
  }
}
Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
                         int osr_bci, BufferBlob* buffer_blob)
: _compiler(compiler)
, _env(env)
, _log(env->log())
, _method(method)
, _osr_bci(osr_bci)
, _hir(NULL)
, _max_spills(-1)
, _frame_map(NULL)
, _masm(NULL)
, _has_exception_handlers(false)
, _has_fpu_code(true)   // pessimistic assumption
, _would_profile(false)
, _has_unsafe_access(false)
, _has_method_handle_invokes(false)
, _bailout_msg(NULL)
, _exception_info_list(NULL)
, _allocator(NULL)
, _next_id(0)
, _next_block_id(0)
, _code(buffer_blob)
, _has_access_indexed(false)
, _current_instruction(NULL)
, _interpreter_frame_size(0)
#ifndef PRODUCT
, _last_instruction_printed(NULL)
#endif // PRODUCT
{
  PhaseTraceTime timeit(_t_compile);
  _arena = Thread::current()->resource_area();
  _env->set_compiler_data(this);
  _exception_info_list = new ExceptionInfoList();
  _implicit_exception_table.set_size(0);
  compile_method();
  if (bailed_out()) {
    _env->record_method_not_compilable(bailout_msg(), !TieredCompilation);
    if (is_profiling()) {
      _method->ensure_method_data();
    }
  } else if (is_profiling()) {
    ciMethodData *md = method->method_data_or_null();
    if (md != NULL) {
      md->set_would_profile(_would_profile);
    }
  }
}
Compilation::~Compilation() {
  _env->set_compiler_data(NULL);
}
void Compilation::add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers) {
#ifndef PRODUCT
  if (PrintExceptionHandlers && Verbose) {
    tty->print_cr("  added exception scope for pco %d", pco);
  }
#endif
  exception_info_list()->push(new ExceptionInfo(pco, exception_handlers));
}
void Compilation::notice_inlined_method(ciMethod* method) {
  _env->notice_inlined_method(method);
}
void Compilation::bailout(const char* msg) {
  assert(msg != NULL, "bailout message must exist");
  if (!bailed_out()) {
    if (PrintCompilation || PrintBailouts) tty->print_cr("compilation bailout: %s", msg);
    _bailout_msg = msg;
  }
}
ciKlass* Compilation::cha_exact_type(ciType* type) {
  if (type != NULL && type->is_loaded() && type->is_instance_klass()) {
    ciInstanceKlass* ik = type->as_instance_klass();
    assert(ik->exact_klass() == NULL, "no cha for final klass");
    if (DeoptC1 && UseCHA && !(ik->has_subklass() || ik->is_interface())) {
      dependency_recorder()->assert_leaf_type(ik);
      return ik;
    }
  }
  return NULL;
}
void Compilation::print_timers() {
  float total = timers[_t_setup].seconds() + timers[_t_buildIR].seconds() + timers[_t_emit_lir].seconds() + timers[_t_lir_schedule].seconds() + timers[_t_codeemit].seconds() + timers[_t_codeinstall].seconds();
  tty->print_cr("    Detailed C1 Timings");
  tty->print_cr("       Setup time:        %6.3f s (%4.1f%%)",    timers[_t_setup].seconds(),           (timers[_t_setup].seconds() / total) * 100.0);
  tty->print_cr("       Build IR:          %6.3f s (%4.1f%%)",    timers[_t_buildIR].seconds(),         (timers[_t_buildIR].seconds() / total) * 100.0);
  float t_optimizeIR = timers[_t_optimize_blocks].seconds() + timers[_t_optimize_null_checks].seconds();
  tty->print_cr("         Optimize:           %6.3f s (%4.1f%%)", t_optimizeIR,                         (t_optimizeIR / total) * 100.0);
  tty->print_cr("         RCE:                %6.3f s (%4.1f%%)", timers[_t_rangeCheckElimination].seconds(),      (timers[_t_rangeCheckElimination].seconds() / total) * 100.0);
  tty->print_cr("       Emit LIR:          %6.3f s (%4.1f%%)",    timers[_t_emit_lir].seconds(),        (timers[_t_emit_lir].seconds() / total) * 100.0);
  tty->print_cr("         LIR Gen:          %6.3f s (%4.1f%%)",   timers[_t_lirGeneration].seconds(), (timers[_t_lirGeneration].seconds() / total) * 100.0);
  tty->print_cr("         Linear Scan:      %6.3f s (%4.1f%%)",   timers[_t_linearScan].seconds(),    (timers[_t_linearScan].seconds() / total) * 100.0);
  NOT_PRODUCT(LinearScan::print_timers(timers[_t_linearScan].seconds()));
  tty->print_cr("       LIR Schedule:      %6.3f s (%4.1f%%)",    timers[_t_lir_schedule].seconds(),  (timers[_t_lir_schedule].seconds() / total) * 100.0);
  tty->print_cr("       Code Emission:     %6.3f s (%4.1f%%)",    timers[_t_codeemit].seconds(),        (timers[_t_codeemit].seconds() / total) * 100.0);
  tty->print_cr("       Code Installation: %6.3f s (%4.1f%%)",    timers[_t_codeinstall].seconds(),     (timers[_t_codeinstall].seconds() / total) * 100.0);
  tty->print_cr("       Instruction Nodes: %6d nodes",    totalInstructionNodes);
  NOT_PRODUCT(LinearScan::print_statistics());
}
#ifndef PRODUCT
void Compilation::compile_only_this_method() {
  ResourceMark rm;
  fileStream stream(fopen("c1_compile_only", "wt"));
  stream.print_cr("# c1 compile only directives");
  compile_only_this_scope(&stream, hir()->top_scope());
}
void Compilation::compile_only_this_scope(outputStream* st, IRScope* scope) {
  st->print("CompileOnly=");
  scope->method()->holder()->name()->print_symbol_on(st);
  st->print(".");
  scope->method()->name()->print_symbol_on(st);
  st->cr();
}
void Compilation::exclude_this_method() {
  fileStream stream(fopen(".hotspot_compiler", "at"));
  stream.print("exclude ");
  method()->holder()->name()->print_symbol_on(&stream);
  stream.print(" ");
  method()->name()->print_symbol_on(&stream);
  stream.cr();
  stream.cr();
}
#endif
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Compilation.hpp
#ifndef SHARE_VM_C1_C1_COMPILATION_HPP
#define SHARE_VM_C1_C1_COMPILATION_HPP
#include "ci/ciEnv.hpp"
#include "ci/ciMethodData.hpp"
#include "code/exceptionHandlerTable.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/deoptimization.hpp"
class CompilationResourceObj;
class XHandlers;
class ExceptionInfo;
class DebugInformationRecorder;
class FrameMap;
class IR;
class IRScope;
class Instruction;
class LinearScan;
class OopMap;
class LIR_Emitter;
class LIR_Assembler;
class CodeEmitInfo;
class ciEnv;
class ciMethod;
class ValueStack;
class LIR_OprDesc;
class C1_MacroAssembler;
class CFGPrinter;
typedef LIR_OprDesc* LIR_Opr;
define_array(BasicTypeArray, BasicType)
define_stack(BasicTypeList, BasicTypeArray)
define_array(ExceptionInfoArray, ExceptionInfo*)
define_stack(ExceptionInfoList,  ExceptionInfoArray)
class Compilation: public StackObj {
  friend class CompilationResourceObj;
 private:
  Arena* _arena;
  int _next_id;
  int _next_block_id;
  AbstractCompiler*  _compiler;
  ciEnv*             _env;
  CompileLog*        _log;
  ciMethod*          _method;
  int                _osr_bci;
  IR*                _hir;
  int                _max_spills;
  FrameMap*          _frame_map;
  C1_MacroAssembler* _masm;
  bool               _has_exception_handlers;
  bool               _has_fpu_code;
  bool               _has_unsafe_access;
  bool               _would_profile;
  bool               _has_method_handle_invokes;  // True if this method has MethodHandle invokes.
  const char*        _bailout_msg;
  ExceptionInfoList* _exception_info_list;
  ExceptionHandlerTable _exception_handler_table;
  ImplicitExceptionTable _implicit_exception_table;
  LinearScan*        _allocator;
  CodeOffsets        _offsets;
  CodeBuffer         _code;
  bool               _has_access_indexed;
  int                _interpreter_frame_size; // Stack space needed in case of a deoptimization
  void initialize();
  void build_hir();
  void emit_lir();
  void emit_code_epilog(LIR_Assembler* assembler);
  int  emit_code_body();
  int  compile_java_method();
  void install_code(int frame_size);
  void compile_method();
  void generate_exception_handler_table();
  ExceptionInfoList* exception_info_list() const { return _exception_info_list; }
  ExceptionHandlerTable* exception_handler_table() { return &_exception_handler_table; }
  LinearScan* allocator()                          { return _allocator;      }
  void        set_allocator(LinearScan* allocator) { _allocator = allocator; }
  Instruction*       _current_instruction;       // the instruction currently being processed
#ifndef PRODUCT
  Instruction*       _last_instruction_printed;  // the last instruction printed during traversal
#endif // PRODUCT
 public:
  Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
              int osr_bci, BufferBlob* buffer_blob);
  ~Compilation();
  static Compilation* current() {
    return (Compilation*) ciEnv::current()->compiler_data();
  }
  ciEnv* env() const                             { return _env; }
  CompileLog* log() const                        { return _log; }
  AbstractCompiler* compiler() const             { return _compiler; }
  bool has_exception_handlers() const            { return _has_exception_handlers; }
  bool has_fpu_code() const                      { return _has_fpu_code; }
  bool has_unsafe_access() const                 { return _has_unsafe_access; }
  int max_vector_size() const                    { return 0; }
  ciMethod* method() const                       { return _method; }
  int osr_bci() const                            { return _osr_bci; }
  bool is_osr_compile() const                    { return osr_bci() >= 0; }
  IR* hir() const                                { return _hir; }
  int max_spills() const                         { return _max_spills; }
  FrameMap* frame_map() const                    { return _frame_map; }
  CodeBuffer* code()                             { return &_code; }
  C1_MacroAssembler* masm() const                { return _masm; }
  CodeOffsets* offsets()                         { return &_offsets; }
  Arena* arena()                                 { return _arena; }
  bool has_access_indexed()                      { return _has_access_indexed; }
  int get_next_id()                              { return _next_id++; }
  int number_of_instructions() const             { return _next_id; }
  int get_next_block_id()                        { return _next_block_id++; }
  int number_of_blocks() const                   { return _next_block_id; }
  void set_has_exception_handlers(bool f)        { _has_exception_handlers = f; }
  void set_has_fpu_code(bool f)                  { _has_fpu_code = f; }
  void set_has_unsafe_access(bool f)             { _has_unsafe_access = f; }
  void set_would_profile(bool f)                 { _would_profile = f; }
  void set_has_access_indexed(bool f)            { _has_access_indexed = f; }
  void add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers);
  void notice_inlined_method(ciMethod* method);
  bool     has_method_handle_invokes() const { return _has_method_handle_invokes;     }
  void set_has_method_handle_invokes(bool z) {        _has_method_handle_invokes = z; }
  DebugInformationRecorder* debug_info_recorder() const; // = _env->debug_info();
  Dependencies* dependency_recorder() const; // = _env->dependencies()
  ImplicitExceptionTable* implicit_exception_table()     { return &_implicit_exception_table; }
  Instruction* current_instruction() const       { return _current_instruction; }
  Instruction* set_current_instruction(Instruction* instr) {
    Instruction* previous = _current_instruction;
    _current_instruction = instr;
    return previous;
  }
#ifndef PRODUCT
  void maybe_print_current_instruction();
#endif // PRODUCT
  void bailout(const char* msg);
  bool bailed_out() const                        { return _bailout_msg != NULL; }
  const char* bailout_msg() const                { return _bailout_msg; }
  static int desired_max_code_buffer_size() {
#ifndef PPC
    return (int) NMethodSizeLimit;  // default 256K or 512K
#else
    return MIN2((unsigned int)NMethodSizeLimit,32*K);
#endif
  }
  static int desired_max_constant_size() {
    return desired_max_code_buffer_size() / 10;
  }
  static bool setup_code_buffer(CodeBuffer* cb, int call_stub_estimate);
  static void print_timers();
#ifndef PRODUCT
  void compile_only_this_method();
  void compile_only_this_scope(outputStream* st, IRScope* scope);
  void exclude_this_method();
#endif // PRODUCT
  bool is_profiling() {
    return env()->comp_level() == CompLevel_full_profile ||
           env()->comp_level() == CompLevel_limited_profile;
  }
  bool count_invocations() { return is_profiling(); }
  bool count_backedges()   { return is_profiling(); }
  bool profile_branches() {
    return env()->comp_level() == CompLevel_full_profile &&
      C1UpdateMethodData && C1ProfileBranches;
  }
  bool profile_calls() {
    return env()->comp_level() == CompLevel_full_profile &&
      C1UpdateMethodData && C1ProfileCalls;
  }
  bool profile_inlined_calls() {
    return profile_calls() && C1ProfileInlinedCalls;
  }
  bool profile_checkcasts() {
    return env()->comp_level() == CompLevel_full_profile &&
      C1UpdateMethodData && C1ProfileCheckcasts;
  }
  bool profile_parameters() {
    return env()->comp_level() == CompLevel_full_profile &&
      C1UpdateMethodData && MethodData::profile_parameters();
  }
  bool profile_arguments() {
    return env()->comp_level() == CompLevel_full_profile &&
      C1UpdateMethodData && MethodData::profile_arguments();
  }
  bool profile_return() {
    return env()->comp_level() == CompLevel_full_profile &&
      C1UpdateMethodData && MethodData::profile_return();
  }
  bool is_optimistic() const                             {
    return !TieredCompilation &&
      (RangeCheckElimination || UseLoopInvariantCodeMotion) &&
      method()->method_data()->trap_count(Deoptimization::Reason_none) == 0;
  }
  ciKlass* cha_exact_type(ciType* type);
  void dump_inline_data(outputStream* out) { /* do nothing now */ }
  void update_interpreter_frame_size(int size) {
    if (_interpreter_frame_size < size) {
      _interpreter_frame_size = size;
    }
  }
  int interpreter_frame_size() const {
    return _interpreter_frame_size;
  }
};
#define BAILOUT(msg)               { bailout(msg); return;              }
#define BAILOUT_(msg, res)         { bailout(msg); return res;          }
#define CHECK_BAILOUT()            { if (bailed_out()) return;          }
#define CHECK_BAILOUT_(res)        { if (bailed_out()) return res;      }
class InstructionMark: public StackObj {
 private:
  Compilation* _compilation;
  Instruction*  _previous;
 public:
  InstructionMark(Compilation* compilation, Instruction* instr) {
    _compilation = compilation;
    _previous = _compilation->set_current_instruction(instr);
  }
  ~InstructionMark() {
    _compilation->set_current_instruction(_previous);
  }
};
class CompilationResourceObj ALLOCATION_SUPER_CLASS_SPEC {
 public:
  void* operator new(size_t size) throw() { return Compilation::current()->arena()->Amalloc(size); }
  void* operator new(size_t size, Arena* arena) throw() {
    return arena->Amalloc(size);
  }
  void  operator delete(void* p) {} // nothing to do
};
class ExceptionInfo: public CompilationResourceObj {
 private:
  int             _pco;                // PC of potentially exception-throwing instruction
  XHandlers*      _exception_handlers; // flat list of exception handlers covering this PC
 public:
  ExceptionInfo(int pco, XHandlers* exception_handlers)
    : _pco(pco)
    , _exception_handlers(exception_handlers)
  { }
  int pco()                                      { return _pco; }
  XHandlers* exception_handlers()                { return _exception_handlers; }
};
#endif // SHARE_VM_C1_C1_COMPILATION_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Compiler.cpp
#include "precompiled.hpp"
#include "c1/c1_Compilation.hpp"
#include "c1/c1_Compiler.hpp"
#include "c1/c1_FrameMap.hpp"
#include "c1/c1_GraphBuilder.hpp"
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "c1/c1_Runtime1.hpp"
#include "c1/c1_ValueType.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerOracle.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/arguments.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/sharedRuntime.hpp"
Compiler::Compiler () {}
void Compiler::init_c1_runtime() {
  BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
  Arena* arena = new (mtCompiler) Arena(mtCompiler);
  Runtime1::initialize(buffer_blob);
  FrameMap::initialize();
  ValueType::initialize(arena);
  GraphBuilder::initialize();
  Interval::initialize(arena);
}
void Compiler::initialize() {
  BufferBlob* buffer_blob = init_buffer_blob();
  if (should_perform_init()) {
    if (buffer_blob == NULL) {
      set_state(failed);
    } else {
      init_c1_runtime();
      set_state(initialized);
    }
  }
}
BufferBlob* Compiler::init_buffer_blob() {
  assert (CompilerThread::current()->get_buffer_blob() == NULL, "Should initialize only once");
  int code_buffer_size = Compilation::desired_max_code_buffer_size() +
    Compilation::desired_max_constant_size();
  BufferBlob* buffer_blob = BufferBlob::create("C1 temporary CodeBuffer", code_buffer_size);
  if (buffer_blob != NULL) {
    CompilerThread::current()->set_buffer_blob(buffer_blob);
  }
  return buffer_blob;
}
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
  BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
  assert(buffer_blob != NULL, "Must exist");
  {
    ResourceMark rm;
    Compilation c(this, env, method, entry_bci, buffer_blob);
  }
}
void Compiler::print_timers() {
  Compilation::print_timers();
}
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Compiler.hpp
#ifndef SHARE_VM_C1_C1_COMPILER_HPP
#define SHARE_VM_C1_C1_COMPILER_HPP
#include "compiler/abstractCompiler.hpp"
class Compiler: public AbstractCompiler {
 private:
  static void init_c1_runtime();
  BufferBlob* init_buffer_blob();
 public:
  Compiler();
  ~Compiler();
  virtual const char* name()                     { return "C1"; }
  virtual bool is_c1()                           { return true; };
  virtual bool supports_native()                 { return true; }
  virtual bool supports_osr   ()                 { return true; }
  virtual void initialize();
  virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
  virtual void print_timers();
};
#endif // SHARE_VM_C1_C1_COMPILER_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Defs.cpp
#include "precompiled.hpp"
#include "c1/c1_Defs.hpp"
C:\hotspot-69087d08d473\src\share\vm/c1/c1_Defs.hpp
#ifndef SHARE_VM_C1_C1_DEFS_HPP
#define SHARE_VM_C1_C1_DEFS_HPP
#include "utilities/globalDefinitions.hpp"
#ifdef TARGET_ARCH_x86
# include "register_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "register_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "register_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "register_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "register_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "register_ppc.hpp"
#endif
enum {
  no_frame_size            = -1
};
#ifdef TARGET_ARCH_x86
# include "c1_Defs_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "c1_Defs_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "c1_Defs_sparc.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "c1_Defs_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "c1_Defs_ppc.hpp"
#endif
enum {
  lo_word_offset_in_bytes = pd_lo_word_offset_in_bytes,
  hi_word_offset_in_bytes = pd_hi_word_offset_in_bytes
};
enum {
  strict_fp_requires_explicit_rounding = pd_strict_fp_requires_explicit_rounding
};
enum {
  float_saved_as_double = pd_float_saved_as_double
};
#endif // SHARE_VM_C1_C1_DEFS_HPP
C:\hotspot-69087d08d473\src\share\vm/c1/c1_FpuStackSim.hpp
#ifndef SHARE_VM_C1_C1_FPUSTACKSIM_HPP
#define SHARE_VM_C1_C1_FPUSTACKSIM_HPP
#include "c1/c1_FrameMap.hpp"
#include "memory/allocation.hpp"
class FpuStackSim;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值