c1_IR.hpp 14.3 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
 *
 */

// An XHandler is a C1 internal description for an exception handler

class XHandler: public CompilationResourceObj {
 private:
  ciExceptionHandler* _desc;

  BlockBegin*         _entry_block;  // Entry block of xhandler
  LIR_List*           _entry_code;   // LIR-operations that must be executed before jumping to entry_block
  int                 _entry_pco;    // pco where entry_code (or entry_block if no entry_code) starts
  int                 _phi_operand;  // For resolving of phi functions at begin of entry_block
  int                 _scope_count;  // for filling ExceptionRangeEntry::scope_count

#ifdef ASSERT
  int                 _lir_op_id;    // op_id of the LIR-operation throwing to this handler
#endif

 public:
  // creation
  XHandler(ciExceptionHandler* desc)
    : _desc(desc)
    , _entry_block(NULL)
    , _entry_code(NULL)
    , _entry_pco(-1)
    , _phi_operand(-1)
    , _scope_count(-1)
#ifdef ASSERT
    , _lir_op_id(-1)
#endif
  { }

  XHandler(XHandler* other)
    : _desc(other->_desc)
    , _entry_block(other->_entry_block)
    , _entry_code(other->_entry_code)
    , _entry_pco(other->_entry_pco)
    , _phi_operand(other->_phi_operand)
    , _scope_count(other->_scope_count)
#ifdef ASSERT
    , _lir_op_id(other->_lir_op_id)
#endif
  { }

  // accessors for data of ciExceptionHandler
  int  beg_bci() const                           { return _desc->start(); }
  int  end_bci() const                           { return _desc->limit(); }
  int  handler_bci() const                       { return _desc->handler_bci(); }
  bool is_catch_all() const                      { return _desc->is_catch_all(); }
  int  catch_type() const                        { return _desc->catch_klass_index(); }
  ciInstanceKlass* catch_klass() const           { return _desc->catch_klass(); }
  bool covers(int bci) const                     { return beg_bci() <= bci && bci < end_bci(); }

  // accessors for additional fields
  BlockBegin* entry_block() const                { return _entry_block; }
  LIR_List*   entry_code() const                 { return _entry_code; }
  int         entry_pco() const                  { return _entry_pco; }
  int         phi_operand() const                { assert(_phi_operand != -1, "not set"); return _phi_operand; }
  int         scope_count() const                { assert(_scope_count != -1, "not set"); return _scope_count; }
  DEBUG_ONLY(int lir_op_id() const               { return _lir_op_id; });

  void set_entry_block(BlockBegin* entry_block) {
    assert(entry_block->is_set(BlockBegin::exception_entry_flag), "must be an exception handler entry");
    assert(entry_block->bci() == handler_bci(), "bci's must correspond");
    _entry_block = entry_block;
  }
  void set_entry_code(LIR_List* entry_code)      { _entry_code = entry_code; }
  void set_entry_pco(int entry_pco)              { _entry_pco = entry_pco; }
  void set_phi_operand(int phi_operand)          { _phi_operand = phi_operand; }
  void set_scope_count(int scope_count)          { _scope_count = scope_count; }
  DEBUG_ONLY(void set_lir_op_id(int lir_op_id)   { _lir_op_id = lir_op_id; });

  bool equals(XHandler* other) const;
};

define_array(_XHandlerArray, XHandler*)
define_stack(_XHandlerList, _XHandlerArray)


// XHandlers is the C1 internal list of exception handlers for a method
class XHandlers: public CompilationResourceObj {
 private:
  _XHandlerList    _list;

 public:
  // creation
  XHandlers() : _list()                          { }
  XHandlers(ciMethod* method);
  XHandlers(XHandlers* other);

  // accessors
  int       length() const                       { return _list.length(); }
  XHandler* handler_at(int i) const              { return _list.at(i); }
  bool      has_handlers() const                 { return _list.length() > 0; }
  void      append(XHandler* h)                  { _list.append(h); }
  XHandler* remove_last()                        { return _list.pop(); }

  bool      could_catch(ciInstanceKlass* klass, bool type_is_exact) const;
  bool      equals(XHandlers* others) const;
};


class IRScope;
define_array(IRScopeArray, IRScope*)
define_stack(IRScopeList, IRScopeArray)

class Compilation;
class IRScope: public CompilationResourceObj {
 private:
  // hierarchy
  Compilation*  _compilation;                    // the current compilation
  IRScope*      _caller;                         // the caller scope, or NULL
  int           _level;                          // the inlining level
  ciMethod*     _method;                         // the corresponding method
  IRScopeList   _callees;                        // the inlined method scopes

  // graph
  XHandlers*    _xhandlers;                      // the exception handlers
  int           _number_of_locks;                // the number of monitor lock slots needed
  bool          _monitor_pairing_ok;             // the monitor pairing info
  BlockBegin*   _start;                          // the start block, successsors are method entries

  BitMap        _requires_phi_function;          // bit is set if phi functions at loop headers are necessary for a local variable

  // helper functions
  BlockBegin* build_graph(Compilation* compilation, int osr_bci);

 public:
  // creation
  IRScope(Compilation* compilation, IRScope* caller, int caller_bci, ciMethod* method, int osr_bci, bool create_graph = false);

  // accessors
  Compilation*  compilation() const              { return _compilation; }
  IRScope*      caller() const                   { return _caller; }
  int           level() const                    { return _level; }
  ciMethod*     method() const                   { return _method; }
  int           max_stack() const;               // NOTE: expensive
  BitMap&       requires_phi_function()          { return _requires_phi_function; }

  // hierarchy
  bool          is_top_scope() const             { return _caller == NULL; }
  void          add_callee(IRScope* callee)      { _callees.append(callee); }
  int           number_of_callees() const        { return _callees.length(); }
  IRScope*      callee_no(int i) const           { return _callees.at(i); }

  // accessors, graph
  bool          is_valid() const                 { return start() != NULL; }
  XHandlers*    xhandlers() const                { return _xhandlers; }
  int           number_of_locks() const          { return _number_of_locks; }
  void          set_min_number_of_locks(int n)   { if (n > _number_of_locks) _number_of_locks = n; }
  bool          monitor_pairing_ok() const       { return _monitor_pairing_ok; }
  BlockBegin*   start() const                    { return _start; }
};


//
// IRScopeDebugInfo records the debug information for a particular IRScope
// in a particular CodeEmitInfo.  This allows the information to be computed
// once early enough for the OopMap to be available to the LIR and also to be
// reemited for different pcs using the same CodeEmitInfo without recomputing
// everything.
//

class IRScopeDebugInfo: public CompilationResourceObj {
 private:
  IRScope*                      _scope;
  int                           _bci;
  GrowableArray<ScopeValue*>*   _locals;
  GrowableArray<ScopeValue*>*   _expressions;
  GrowableArray<MonitorValue*>* _monitors;
  IRScopeDebugInfo*             _caller;

 public:
  IRScopeDebugInfo(IRScope*                      scope,
                   int                           bci,
                   GrowableArray<ScopeValue*>*   locals,
                   GrowableArray<ScopeValue*>*   expressions,
                   GrowableArray<MonitorValue*>* monitors,
                   IRScopeDebugInfo*             caller):
      _scope(scope)
    , _locals(locals)
    , _bci(bci)
    , _expressions(expressions)
    , _monitors(monitors)
    , _caller(caller) {}


  IRScope*                      scope()       { return _scope;       }
  int                           bci()         { return _bci;         }
  GrowableArray<ScopeValue*>*   locals()      { return _locals;      }
  GrowableArray<ScopeValue*>*   expressions() { return _expressions; }
  GrowableArray<MonitorValue*>* monitors()    { return _monitors;    }
  IRScopeDebugInfo*             caller()      { return _caller;      }

217 218 219
  //Whether we should reexecute this bytecode for deopt
  bool should_reexecute();

220
  void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost, bool is_method_handle_invoke = false) {
D
duke 已提交
221 222
    if (caller() != NULL) {
      // Order is significant:  Must record caller first.
223
      caller()->record_debug_info(recorder, pc_offset, false/*topmost*/);
D
duke 已提交
224 225 226 227
    }
    DebugToken* locvals = recorder->create_scope_values(locals());
    DebugToken* expvals = recorder->create_scope_values(expressions());
    DebugToken* monvals = recorder->create_monitor_values(monitors());
228
    // reexecute allowed only for the topmost frame
229
    bool reexecute = topmost ? should_reexecute() : false;
230 231
    bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
    recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
D
duke 已提交
232 233 234 235 236 237 238 239 240 241 242 243
  }
};


class CodeEmitInfo: public CompilationResourceObj {
  friend class LinearScan;
 private:
  IRScopeDebugInfo* _scope_debug_info;
  IRScope*          _scope;
  XHandlers*        _exception_handlers;
  OopMap*           _oop_map;
  ValueStack*       _stack;                      // used by deoptimization (contains also monitors
244
  bool              _is_method_handle_invoke;    // true if the associated call site is a MethodHandle call site.
D
duke 已提交
245 246 247 248 249 250 251

  FrameMap*     frame_map() const                { return scope()->compilation()->frame_map(); }
  Compilation*  compilation() const              { return scope()->compilation(); }

 public:

  // use scope from ValueStack
R
roland 已提交
252
  CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers);
D
duke 已提交
253 254

  // make a copy
R
roland 已提交
255
  CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack = NULL);
D
duke 已提交
256 257 258 259 260 261 262 263 264

  // accessors
  OopMap* oop_map()                              { return _oop_map; }
  ciMethod* method() const                       { return _scope->method(); }
  IRScope* scope() const                         { return _scope; }
  XHandlers* exception_handlers() const          { return _exception_handlers; }
  ValueStack* stack() const                      { return _stack; }

  void add_register_oop(LIR_Opr opr);
265
  void record_debug_info(DebugInformationRecorder* recorder, int pc_offset);
D
duke 已提交
266

267 268
  bool     is_method_handle_invoke() const { return _is_method_handle_invoke;     }
  void set_is_method_handle_invoke(bool x) {        _is_method_handle_invoke = x; }
D
duke 已提交
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
};


class IR: public CompilationResourceObj {
 private:
  Compilation*     _compilation;                 // the current compilation
  IRScope*         _top_scope;                   // the root of the scope hierarchy
  WordSize         _locals_size;                 // the space required for all locals
  int              _num_loops;                   // Total number of loops
  BlockList*       _code;                        // the blocks in code generation order w/ use counts

 public:
  // creation
  IR(Compilation* compilation, ciMethod* method, int osr_bci);

  // accessors
  bool             is_valid() const              { return top_scope()->is_valid(); }
  Compilation*     compilation() const           { return _compilation; }
  IRScope*         top_scope() const             { return _top_scope; }
  int              number_of_locks() const       { return top_scope()->number_of_locks(); }
  ciMethod*        method() const                { return top_scope()->method(); }
  BlockBegin*      start() const                 { return top_scope()->start(); }
  BlockBegin*      std_entry() const             { return start()->end()->as_Base()->std_entry(); }
  BlockBegin*      osr_entry() const             { return start()->end()->as_Base()->osr_entry(); }
  WordSize         locals_size() const           { return _locals_size; }
  int              locals_size_in_words() const  { return in_words(_locals_size); }
  BlockList*       code() const                  { return _code; }
  int              num_loops() const             { return _num_loops; }
  int              max_stack() const             { return top_scope()->max_stack(); } // expensive

  // ir manipulation
  void optimize();
  void compute_predecessors();
  void split_critical_edges();
  void compute_code();
  void compute_use_counts();

  // The linear-scan order and the code emission order are equal, but
  // this may change in future
  BlockList* linear_scan_order() {  assert(_code != NULL, "not computed"); return _code; }

  // iteration
  void iterate_preorder   (BlockClosure* closure);
  void iterate_postorder  (BlockClosure* closure);
  void iterate_linear_scan_order(BlockClosure* closure);

  // debugging
  static void print(BlockBegin* start, bool cfg_only, bool live_only = false) PRODUCT_RETURN;
  void print(bool cfg_only, bool live_only = false)                           PRODUCT_RETURN;
  void verify()                                                               PRODUCT_RETURN;
};


// Globally do instruction substitution and remove substituted
// instructions from the instruction list.
//

326 327
class SubstitutionResolver: public BlockClosure, ValueVisitor {
  virtual void visit(Value* v);
D
duke 已提交
328 329 330 331 332 333 334 335 336 337 338 339

 public:
  SubstitutionResolver(IR* hir) {
    hir->iterate_preorder(this);
  }

  SubstitutionResolver(BlockBegin* block) {
    block->iterate_preorder(this);
  }

  virtual void block_do(BlockBegin* block);
};