src/share/vm/c1/c1_GraphBuilder.hpp

changeset 435
a61af66fc99e
child 894
3a86a8dcf27c
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/c1/c1_GraphBuilder.hpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,390 @@
     1.4 +/*
     1.5 + * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +class MemoryBuffer;
    1.29 +
    1.30 +class GraphBuilder VALUE_OBJ_CLASS_SPEC {
    1.31 + private:
    1.32 +  // Per-scope data. These are pushed and popped as we descend into
    1.33 +  // inlined methods. Currently in order to generate good code in the
    1.34 +  // inliner we have to attempt to inline methods directly into the
    1.35 +  // basic block we are parsing; this adds complexity.
    1.36 +  class ScopeData: public CompilationResourceObj {
    1.37 +   private:
    1.38 +    ScopeData*  _parent;
    1.39 +    // bci-to-block mapping
    1.40 +    BlockList*   _bci2block;
    1.41 +    // Scope
    1.42 +    IRScope*     _scope;
    1.43 +    // Whether this scope or any parent scope has exception handlers
    1.44 +    bool         _has_handler;
    1.45 +    // The bytecodes
    1.46 +    ciBytecodeStream* _stream;
    1.47 +
    1.48 +    // Work list
    1.49 +    BlockList*   _work_list;
    1.50 +
    1.51 +    // Maximum inline size for this scope
    1.52 +    intx         _max_inline_size;
    1.53 +    // Expression stack depth at point where inline occurred
    1.54 +    int          _caller_stack_size;
    1.55 +
    1.56 +    // The continuation point for the inline. Currently only used in
    1.57 +    // multi-block inlines, but eventually would like to use this for
    1.58 +    // all inlines for uniformity and simplicity; in this case would
    1.59 +    // get the continuation point from the BlockList instead of
    1.60 +    // fabricating it anew because Invokes would be considered to be
    1.61 +    // BlockEnds.
    1.62 +    BlockBegin*  _continuation;
    1.63 +
    1.64 +    // Without return value of inlined method on stack
    1.65 +    ValueStack*  _continuation_state;
    1.66 +
    1.67 +    // Was this ScopeData created only for the parsing and inlining of
    1.68 +    // a jsr?
    1.69 +    bool         _parsing_jsr;
    1.70 +    // We track the destination bci of the jsr only to determine
    1.71 +    // bailout conditions, since we only handle a subset of all of the
    1.72 +    // possible jsr-ret control structures. Recursive invocations of a
    1.73 +    // jsr are disallowed by the verifier.
    1.74 +    int          _jsr_entry_bci;
    1.75 +    // We need to track the local variable in which the return address
    1.76 +    // was stored to ensure we can handle inlining the jsr, because we
    1.77 +    // don't handle arbitrary jsr/ret constructs.
    1.78 +    int          _jsr_ret_addr_local;
    1.79 +    // If we are parsing a jsr, the continuation point for rets
    1.80 +    BlockBegin*  _jsr_continuation;
    1.81 +    // Cloned XHandlers for jsr-related ScopeDatas
    1.82 +    XHandlers*   _jsr_xhandlers;
    1.83 +
    1.84 +    // Number of returns seen in this scope
    1.85 +    int          _num_returns;
    1.86 +
    1.87 +    // In order to generate profitable code for inlining, we currently
    1.88 +    // have to perform an optimization for single-block inlined
    1.89 +    // methods where we continue parsing into the same block. This
    1.90 +    // allows us to perform CSE across inlined scopes and to avoid
    1.91 +    // storing parameters to the stack. Having a global register
    1.92 +    // allocator and being able to perform global CSE would allow this
    1.93 +    // code to be removed and thereby simplify the inliner.
    1.94 +    BlockBegin*  _cleanup_block;       // The block to which the return was added
    1.95 +    Instruction* _cleanup_return_prev; // Instruction before return instruction
    1.96 +    ValueStack*  _cleanup_state;       // State of that block (not yet pinned)
    1.97 +
    1.98 +   public:
    1.99 +    ScopeData(ScopeData* parent);
   1.100 +
   1.101 +    ScopeData* parent() const                      { return _parent;            }
   1.102 +
   1.103 +    BlockList* bci2block() const                   { return _bci2block;         }
   1.104 +    void       set_bci2block(BlockList* bci2block) { _bci2block = bci2block;    }
   1.105 +
   1.106 +    // NOTE: this has a different effect when parsing jsrs
   1.107 +    BlockBegin* block_at(int bci);
   1.108 +
   1.109 +    IRScope* scope() const                         { return _scope;             }
   1.110 +    // Has side-effect of setting has_handler flag
   1.111 +    void set_scope(IRScope* scope);
   1.112 +
   1.113 +    // Whether this or any parent scope has exception handlers
   1.114 +    bool has_handler() const                       { return _has_handler;       }
   1.115 +    void set_has_handler()                         { _has_handler = true;       }
   1.116 +
   1.117 +    // Exception handlers list to be used for this scope
   1.118 +    XHandlers* xhandlers() const;
   1.119 +
   1.120 +    // How to get a block to be parsed
   1.121 +    void add_to_work_list(BlockBegin* block);
   1.122 +    // How to remove the next block to be parsed; returns NULL if none left
   1.123 +    BlockBegin* remove_from_work_list();
   1.124 +    // Indicates parse is over
   1.125 +    bool is_work_list_empty() const;
   1.126 +
   1.127 +    ciBytecodeStream* stream()                     { return _stream;            }
   1.128 +    void set_stream(ciBytecodeStream* stream)      { _stream = stream;          }
   1.129 +
   1.130 +    intx max_inline_size() const                   { return _max_inline_size;   }
   1.131 +    int  caller_stack_size() const;
   1.132 +
   1.133 +    BlockBegin* continuation() const               { return _continuation;      }
   1.134 +    void set_continuation(BlockBegin* cont)        { _continuation = cont;      }
   1.135 +
   1.136 +    ValueStack* continuation_state() const         { return _continuation_state; }
   1.137 +    void set_continuation_state(ValueStack* s)     { _continuation_state = s; }
   1.138 +
   1.139 +    // Indicates whether this ScopeData was pushed only for the
   1.140 +    // parsing and inlining of a jsr
   1.141 +    bool parsing_jsr() const                       { return _parsing_jsr;       }
   1.142 +    void set_parsing_jsr()                         { _parsing_jsr = true;       }
   1.143 +    int  jsr_entry_bci() const                     { return _jsr_entry_bci;     }
   1.144 +    void set_jsr_entry_bci(int bci)                { _jsr_entry_bci = bci;      }
   1.145 +    void set_jsr_return_address_local(int local_no){ _jsr_ret_addr_local = local_no; }
   1.146 +    int  jsr_return_address_local() const          { return _jsr_ret_addr_local; }
   1.147 +    // Must be called after scope is set up for jsr ScopeData
   1.148 +    void setup_jsr_xhandlers();
   1.149 +
   1.150 +    // The jsr continuation is only used when parsing_jsr is true, and
   1.151 +    // is different from the "normal" continuation since we can end up
   1.152 +    // doing a return (rather than a ret) from within a subroutine
   1.153 +    BlockBegin* jsr_continuation() const           { return _jsr_continuation;  }
   1.154 +    void set_jsr_continuation(BlockBegin* cont)    { _jsr_continuation = cont;  }
   1.155 +
   1.156 +    int num_returns();
   1.157 +    void incr_num_returns();
   1.158 +
   1.159 +    void set_inline_cleanup_info(BlockBegin* block,
   1.160 +                                 Instruction* return_prev,
   1.161 +                                 ValueStack* return_state);
   1.162 +    BlockBegin*  inline_cleanup_block() const      { return _cleanup_block; }
   1.163 +    Instruction* inline_cleanup_return_prev() const{ return _cleanup_return_prev; }
   1.164 +    ValueStack*  inline_cleanup_state() const      { return _cleanup_state; }
   1.165 +  };
   1.166 +
   1.167 +  // for all GraphBuilders
   1.168 +  static bool       _is_initialized;             // true if trap tables were initialized, false otherwise
   1.169 +  static bool       _can_trap[Bytecodes::number_of_java_codes];
   1.170 +  static bool       _is_async[Bytecodes::number_of_java_codes];
   1.171 +
   1.172 +  // for each instance of GraphBuilder
   1.173 +  ScopeData*        _scope_data;                 // Per-scope data; used for inlining
   1.174 +  Compilation*      _compilation;                // the current compilation
   1.175 +  ValueMap*         _vmap;                       // the map of values encountered (for CSE)
   1.176 +  MemoryBuffer*     _memory;
   1.177 +  const char*       _inline_bailout_msg;         // non-null if most recent inline attempt failed
   1.178 +  int               _instruction_count;          // for bailing out in pathological jsr/ret cases
   1.179 +  BlockBegin*       _start;                      // the start block
   1.180 +  BlockBegin*       _osr_entry;                  // the osr entry block block
   1.181 +  ValueStack*       _initial_state;              // The state for the start block
   1.182 +
   1.183 +  // for each call to connect_to_end; can also be set by inliner
   1.184 +  BlockBegin*       _block;                      // the current block
   1.185 +  ValueStack*       _state;                      // the current execution state
   1.186 +  ValueStack*       _exception_state;            // state that will be used by handle_exception
   1.187 +  Instruction*      _last;                       // the last instruction added
   1.188 +  bool              _skip_block;                 // skip processing of the rest of this block
   1.189 +
   1.190 +  // accessors
   1.191 +  ScopeData*        scope_data() const           { return _scope_data; }
   1.192 +  Compilation*      compilation() const          { return _compilation; }
   1.193 +  BlockList*        bci2block() const            { return scope_data()->bci2block(); }
   1.194 +  ValueMap*         vmap() const                 { assert(UseLocalValueNumbering, "should not access otherwise"); return _vmap; }
   1.195 +  bool              has_handler() const          { return scope_data()->has_handler(); }
   1.196 +
   1.197 +  BlockBegin*       block() const                { return _block; }
   1.198 +  ValueStack*       state() const                { return _state; }
   1.199 +  void              set_state(ValueStack* state) { _state = state; }
   1.200 +  IRScope*          scope() const                { return scope_data()->scope(); }
   1.201 +  ValueStack*       exception_state() const      { return _exception_state; }
   1.202 +  void              set_exception_state(ValueStack* s) { _exception_state = s; }
   1.203 +  ciMethod*         method() const               { return scope()->method(); }
   1.204 +  ciBytecodeStream* stream() const               { return scope_data()->stream(); }
   1.205 +  Instruction*      last() const                 { return _last; }
   1.206 +  Bytecodes::Code   code() const                 { return stream()->cur_bc(); }
   1.207 +  int               bci() const                  { return stream()->cur_bci(); }
   1.208 +  int               next_bci() const             { return stream()->next_bci(); }
   1.209 +
   1.210 +  // unified bailout support
   1.211 +  void bailout(const char* msg) const            { compilation()->bailout(msg); }
   1.212 +  bool bailed_out() const                        { return compilation()->bailed_out(); }
   1.213 +
   1.214 +  // stack manipulation helpers
   1.215 +  void ipush(Value t) const                      { state()->ipush(t); }
   1.216 +  void lpush(Value t) const                      { state()->lpush(t); }
   1.217 +  void fpush(Value t) const                      { state()->fpush(t); }
   1.218 +  void dpush(Value t) const                      { state()->dpush(t); }
   1.219 +  void apush(Value t) const                      { state()->apush(t); }
   1.220 +  void  push(ValueType* type, Value t) const     { state()-> push(type, t); }
   1.221 +
   1.222 +  Value ipop()                                   { return state()->ipop(); }
   1.223 +  Value lpop()                                   { return state()->lpop(); }
   1.224 +  Value fpop()                                   { return state()->fpop(); }
   1.225 +  Value dpop()                                   { return state()->dpop(); }
   1.226 +  Value apop()                                   { return state()->apop(); }
   1.227 +  Value  pop(ValueType* type)                    { return state()-> pop(type); }
   1.228 +
   1.229 +  // instruction helpers
   1.230 +  void load_constant();
   1.231 +  void load_local(ValueType* type, int index);
   1.232 +  void store_local(ValueType* type, int index);
   1.233 +  void store_local(ValueStack* state, Value value, ValueType* type, int index);
   1.234 +  void load_indexed (BasicType type);
   1.235 +  void store_indexed(BasicType type);
   1.236 +  void stack_op(Bytecodes::Code code);
   1.237 +  void arithmetic_op(ValueType* type, Bytecodes::Code code, ValueStack* lock_stack = NULL);
   1.238 +  void negate_op(ValueType* type);
   1.239 +  void shift_op(ValueType* type, Bytecodes::Code code);
   1.240 +  void logic_op(ValueType* type, Bytecodes::Code code);
   1.241 +  void compare_op(ValueType* type, Bytecodes::Code code);
   1.242 +  void convert(Bytecodes::Code op, BasicType from, BasicType to);
   1.243 +  void increment();
   1.244 +  void _goto(int from_bci, int to_bci);
   1.245 +  void if_node(Value x, If::Condition cond, Value y, ValueStack* stack_before);
   1.246 +  void if_zero(ValueType* type, If::Condition cond);
   1.247 +  void if_null(ValueType* type, If::Condition cond);
   1.248 +  void if_same(ValueType* type, If::Condition cond);
   1.249 +  void jsr(int dest);
   1.250 +  void ret(int local_index);
   1.251 +  void table_switch();
   1.252 +  void lookup_switch();
   1.253 +  void method_return(Value x);
   1.254 +  void call_register_finalizer();
   1.255 +  void access_field(Bytecodes::Code code);
   1.256 +  void invoke(Bytecodes::Code code);
   1.257 +  void new_instance(int klass_index);
   1.258 +  void new_type_array();
   1.259 +  void new_object_array();
   1.260 +  void check_cast(int klass_index);
   1.261 +  void instance_of(int klass_index);
   1.262 +  void monitorenter(Value x, int bci);
   1.263 +  void monitorexit(Value x, int bci);
   1.264 +  void new_multi_array(int dimensions);
   1.265 +  void throw_op(int bci);
   1.266 +  Value round_fp(Value fp_value);
   1.267 +
   1.268 +  // stack/code manipulation helpers
   1.269 +  Instruction* append_with_bci(Instruction* instr, int bci);
   1.270 +  Instruction* append(Instruction* instr);
   1.271 +  Instruction* append_split(StateSplit* instr);
   1.272 +
   1.273 +  // other helpers
   1.274 +  static bool is_initialized()                   { return _is_initialized; }
   1.275 +  static bool is_async(Bytecodes::Code code) {
   1.276 +    assert(0 <= code && code < Bytecodes::number_of_java_codes, "illegal bytecode");
   1.277 +    return _is_async[code];
   1.278 +  }
   1.279 +  BlockBegin* block_at(int bci)                  { return scope_data()->block_at(bci); }
   1.280 +  XHandlers* handle_exception(int bci);
   1.281 +  void connect_to_end(BlockBegin* beg);
   1.282 +  void null_check(Value value);
   1.283 +  void eliminate_redundant_phis(BlockBegin* start);
   1.284 +  BlockEnd* iterate_bytecodes_for_block(int bci);
   1.285 +  void iterate_all_blocks(bool start_in_current_block_for_inlining = false);
   1.286 +  Dependencies* dependency_recorder() const; // = compilation()->dependencies()
   1.287 +  bool direct_compare(ciKlass* k);
   1.288 +
   1.289 +  void kill_field(ciField* field);
   1.290 +  void kill_array(Value value);
   1.291 +  void kill_all();
   1.292 +
   1.293 +  ValueStack* lock_stack();
   1.294 +
   1.295 +  //
   1.296 +  // Inlining support
   1.297 +  //
   1.298 +
   1.299 +  // accessors
   1.300 +  bool parsing_jsr() const                               { return scope_data()->parsing_jsr();           }
   1.301 +  BlockBegin* continuation() const                       { return scope_data()->continuation();          }
   1.302 +  ValueStack* continuation_state() const                 { return scope_data()->continuation_state();    }
   1.303 +  BlockBegin* jsr_continuation() const                   { return scope_data()->jsr_continuation();      }
   1.304 +  int caller_stack_size() const                          { return scope_data()->caller_stack_size();     }
   1.305 +  void set_continuation(BlockBegin* continuation)        { scope_data()->set_continuation(continuation); }
   1.306 +  void set_inline_cleanup_info(BlockBegin* block,
   1.307 +                               Instruction* return_prev,
   1.308 +                               ValueStack* return_state) { scope_data()->set_inline_cleanup_info(block,
   1.309 +                                                                                                  return_prev,
   1.310 +                                                                                                  return_state); }
   1.311 +  BlockBegin*  inline_cleanup_block() const              { return scope_data()->inline_cleanup_block();  }
   1.312 +  Instruction* inline_cleanup_return_prev() const        { return scope_data()->inline_cleanup_return_prev(); }
   1.313 +  ValueStack*  inline_cleanup_state() const              { return scope_data()->inline_cleanup_state();  }
   1.314 +  void incr_num_returns()                                { scope_data()->incr_num_returns();             }
   1.315 +  int  num_returns() const                               { return scope_data()->num_returns();           }
   1.316 +  intx max_inline_size() const                           { return scope_data()->max_inline_size();       }
   1.317 +  int  inline_level() const                              { return scope()->level();                      }
   1.318 +  int  recursive_inline_level(ciMethod* callee) const;
   1.319 +
   1.320 +  // inlining of synchronized methods
   1.321 +  void inline_sync_entry(Value lock, BlockBegin* sync_handler);
   1.322 +  void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false);
   1.323 +
   1.324 +  // inliners
   1.325 +  bool try_inline(ciMethod* callee, bool holder_known);
   1.326 +  bool try_inline_intrinsics(ciMethod* callee);
   1.327 +  bool try_inline_full      (ciMethod* callee, bool holder_known);
   1.328 +  bool try_inline_jsr(int jsr_dest_bci);
   1.329 +
   1.330 +  // helpers
   1.331 +  void inline_bailout(const char* msg);
   1.332 +  BlockBegin* header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state);
   1.333 +  BlockBegin* setup_start_block(int osr_bci, BlockBegin* std_entry, BlockBegin* osr_entry, ValueStack* init_state);
   1.334 +  void setup_osr_entry_block();
   1.335 +  void clear_inline_bailout();
   1.336 +  ValueStack* state_at_entry();
   1.337 +  void push_root_scope(IRScope* scope, BlockList* bci2block, BlockBegin* start);
   1.338 +  void push_scope(ciMethod* callee, BlockBegin* continuation);
   1.339 +  void push_scope_for_jsr(BlockBegin* jsr_continuation, int jsr_dest_bci);
   1.340 +  void pop_scope();
   1.341 +  void pop_scope_for_jsr();
   1.342 +
   1.343 +  bool append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile);
   1.344 +  bool append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_volatile);
   1.345 +  bool append_unsafe_get_raw(ciMethod* callee, BasicType t);
   1.346 +  bool append_unsafe_put_raw(ciMethod* callee, BasicType t);
   1.347 +  bool append_unsafe_prefetch(ciMethod* callee, bool is_store, bool is_static);
   1.348 +  void append_unsafe_CAS(ciMethod* callee);
   1.349 +
   1.350 +  NOT_PRODUCT(void print_inline_result(ciMethod* callee, bool res);)
   1.351 +
   1.352 +  // methodDataOop profiling helpers
   1.353 +  void profile_call(Value recv, ciKlass* predicted_holder);
   1.354 +  void profile_invocation(ciMethod* method);
   1.355 +  void profile_bci(int bci);
   1.356 +
   1.357 +  // Helpers for generation of profile information
   1.358 +  bool profile_branches() {
   1.359 +    return _compilation->env()->comp_level() == CompLevel_fast_compile &&
   1.360 +      Tier1UpdateMethodData && Tier1ProfileBranches;
   1.361 +  }
   1.362 +  bool profile_calls() {
   1.363 +    return _compilation->env()->comp_level() == CompLevel_fast_compile &&
   1.364 +      Tier1UpdateMethodData && Tier1ProfileCalls;
   1.365 +  }
   1.366 +  bool profile_inlined_calls() {
   1.367 +    return profile_calls() && Tier1ProfileInlinedCalls;
   1.368 +  }
   1.369 +  bool profile_checkcasts() {
   1.370 +    return _compilation->env()->comp_level() == CompLevel_fast_compile &&
   1.371 +      Tier1UpdateMethodData && Tier1ProfileCheckcasts;
   1.372 +  }
   1.373 +
   1.374 + public:
   1.375 +  NOT_PRODUCT(void print_stats();)
   1.376 +
   1.377 +  // initialization
   1.378 +  static void initialize();
   1.379 +
   1.380 +  // public
   1.381 +  static bool can_trap(ciMethod* method, Bytecodes::Code code) {
   1.382 +    assert(0 <= code && code < Bytecodes::number_of_java_codes, "illegal bytecode");
   1.383 +    if (_can_trap[code]) return true;
   1.384 +    // special handling for finalizer registration
   1.385 +    return code == Bytecodes::_return && method->intrinsic_id() == vmIntrinsics::_Object_init;
   1.386 +  }
   1.387 +
   1.388 +  // creation
   1.389 +  GraphBuilder(Compilation* compilation, IRScope* scope);
   1.390 +  static void sort_top_into_worklist(BlockList* worklist, BlockBegin* top);
   1.391 +
   1.392 +  BlockBegin* start() const                      { return _start; }
   1.393 +};

mercurial