src/share/vm/opto/callGenerator.hpp

changeset 435
a61af66fc99e
child 1515
7c57aead6d3e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/opto/callGenerator.hpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,266 @@
     1.4 +/*
     1.5 + * Copyright 2000-2005 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 +//---------------------------CallGenerator-------------------------------------
    1.29 +// The subclasses of this class handle generation of ideal nodes for
    1.30 +// call sites and method entry points.
    1.31 +
    1.32 +class CallGenerator : public ResourceObj {
    1.33 + public:
    1.34 +  enum {
    1.35 +    xxxunusedxxx
    1.36 +  };
    1.37 +
    1.38 + private:
    1.39 +  ciMethod*             _method;                // The method being called.
    1.40 +
    1.41 + protected:
    1.42 +  CallGenerator(ciMethod* method);
    1.43 +
    1.44 + public:
    1.45 +  // Accessors
    1.46 +  ciMethod*         method() const              { return _method; }
    1.47 +
    1.48 +  // is_inline: At least some code implementing the method is copied here.
    1.49 +  virtual bool      is_inline() const           { return false; }
    1.50 +  // is_intrinsic: There's a method-specific way of generating the inline code.
    1.51 +  virtual bool      is_intrinsic() const        { return false; }
    1.52 +  // is_parse: Bytecodes implementing the specific method are copied here.
    1.53 +  virtual bool      is_parse() const            { return false; }
    1.54 +  // is_virtual: The call uses the receiver type to select or check the method.
    1.55 +  virtual bool      is_virtual() const          { return false; }
    1.56 +  // is_deferred: The decision whether to inline or not is deferred.
    1.57 +  virtual bool      is_deferred() const         { return false; }
    1.58 +  // is_predicted: Uses an explicit check against a predicted type.
    1.59 +  virtual bool      is_predicted() const        { return false; }
    1.60 +  // is_trap: Does not return to the caller.  (E.g., uncommon trap.)
    1.61 +  virtual bool      is_trap() const             { return false; }
    1.62 +
    1.63 +  // Note:  It is possible for a CG to be both inline and virtual.
    1.64 +  // (The hashCode intrinsic does a vtable check and an inlined fast path.)
    1.65 +
    1.66 +  // Utilities:
    1.67 +  const TypeFunc*   tf() const;
    1.68 +
    1.69 +  // The given jvms has state and arguments for a call to my method.
    1.70 +  // Edges after jvms->argoff() carry all (pre-popped) argument values.
    1.71 +  //
    1.72 +  // Update the map with state and return values (if any) and return it.
    1.73 +  // The return values (0, 1, or 2) must be pushed on the map's stack,
    1.74 +  // and the sp of the jvms incremented accordingly.
    1.75 +  //
    1.76 +  // The jvms is returned on success.  Alternatively, a copy of the
    1.77 +  // given jvms, suitably updated, may be returned, in which case the
    1.78 +  // caller should discard the original jvms.
    1.79 +  //
    1.80 +  // The non-Parm edges of the returned map will contain updated global state,
    1.81 +  // and one or two edges before jvms->sp() will carry any return values.
    1.82 +  // Other map edges may contain locals or monitors, and should not
    1.83 +  // be changed in meaning.
    1.84 +  //
    1.85 +  // If the call traps, the returned map must have a control edge of top.
    1.86 +  // If the call can throw, the returned map must report has_exceptions().
    1.87 +  //
    1.88 +  // If the result is NULL, it means that this CallGenerator was unable
    1.89 +  // to handle the given call, and another CallGenerator should be consulted.
    1.90 +  virtual JVMState* generate(JVMState* jvms) = 0;
    1.91 +
    1.92 +  // How to generate a call site that is inlined:
    1.93 +  static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
    1.94 +  // How to generate code for an on-stack replacement handler.
    1.95 +  static CallGenerator* for_osr(ciMethod* m, int osr_bci);
    1.96 +
    1.97 +  // How to generate vanilla out-of-line call sites:
    1.98 +  static CallGenerator* for_direct_call(ciMethod* m);   // static, special
    1.99 +  static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index);  // virtual, interface
   1.100 +
   1.101 +  // How to make a call but defer the decision whether to inline or not.
   1.102 +  static CallGenerator* for_warm_call(WarmCallInfo* ci,
   1.103 +                                      CallGenerator* if_cold,
   1.104 +                                      CallGenerator* if_hot);
   1.105 +
   1.106 +  // How to make a call that optimistically assumes a receiver type:
   1.107 +  static CallGenerator* for_predicted_call(ciKlass* predicted_receiver,
   1.108 +                                           CallGenerator* if_missed,
   1.109 +                                           CallGenerator* if_hit,
   1.110 +                                           float hit_prob);
   1.111 +
   1.112 +  // How to make a call that gives up and goes back to the interpreter:
   1.113 +  static CallGenerator* for_uncommon_trap(ciMethod* m,
   1.114 +                                          Deoptimization::DeoptReason reason,
   1.115 +                                          Deoptimization::DeoptAction action);
   1.116 +
   1.117 +  // Registry for intrinsics:
   1.118 +  static CallGenerator* for_intrinsic(ciMethod* m);
   1.119 +  static void register_intrinsic(ciMethod* m, CallGenerator* cg);
   1.120 +};
   1.121 +
   1.122 +class InlineCallGenerator : public CallGenerator {
   1.123 +  virtual bool      is_inline() const           { return true; }
   1.124 +
   1.125 + protected:
   1.126 +  InlineCallGenerator(ciMethod* method) : CallGenerator(method) { }
   1.127 +};
   1.128 +
   1.129 +
   1.130 +//---------------------------WarmCallInfo--------------------------------------
   1.131 +// A struct to collect information about a given call site.
   1.132 +// Helps sort call sites into "hot", "medium", and "cold".
   1.133 +// Participates in the queueing of "medium" call sites for possible inlining.
   1.134 +class WarmCallInfo : public ResourceObj {
   1.135 + private:
   1.136 +
   1.137 +  CallNode*     _call;   // The CallNode which may be inlined.
   1.138 +  CallGenerator* _hot_cg;// CG for expanding the call node
   1.139 +
   1.140 +  // These are the metrics we use to evaluate call sites:
   1.141 +
   1.142 +  float         _count;  // How often do we expect to reach this site?
   1.143 +  float         _profit; // How much time do we expect to save by inlining?
   1.144 +  float         _work;   // How long do we expect the average call to take?
   1.145 +  float         _size;   // How big do we expect the inlined code to be?
   1.146 +
   1.147 +  float         _heat;   // Combined score inducing total order on call sites.
   1.148 +  WarmCallInfo* _next;   // Next cooler call info in pending queue.
   1.149 +
   1.150 +  // Count is the number of times this call site is expected to be executed.
   1.151 +  // Large count is favorable for inlining, because the extra compilation
   1.152 +  // work will be amortized more completely.
   1.153 +
   1.154 +  // Profit is a rough measure of the amount of time we expect to save
   1.155 +  // per execution of this site if we inline it.  (1.0 == call overhead)
   1.156 +  // Large profit favors inlining.  Negative profit disables inlining.
   1.157 +
   1.158 +  // Work is a rough measure of the amount of time a typical out-of-line
   1.159 +  // call from this site is expected to take.  (1.0 == call, no-op, return)
   1.160 +  // Small work is somewhat favorable for inlining, since methods with
   1.161 +  // short "hot" traces are more likely to inline smoothly.
   1.162 +
   1.163 +  // Size is the number of graph nodes we expect this method to produce,
   1.164 +  // not counting the inlining of any further warm calls it may include.
   1.165 +  // Small size favors inlining, since small methods are more likely to
   1.166 +  // inline smoothly.  The size is estimated by examining the native code
   1.167 +  // if available.  The method bytecodes are also examined, assuming
   1.168 +  // empirically observed node counts for each kind of bytecode.
   1.169 +
   1.170 +  // Heat is the combined "goodness" of a site's inlining.  If we were
   1.171 +  // omniscient, it would be the difference of two sums of future execution
   1.172 +  // times of code emitted for this site (amortized across multiple sites if
   1.173 +  // sharing applies).  The two sums are for versions of this call site with
   1.174 +  // and without inlining.
   1.175 +
   1.176 +  // We approximate this mythical quantity by playing with averages,
   1.177 +  // rough estimates, and assumptions that history repeats itself.
   1.178 +  // The basic formula count * profit is heuristically adjusted
   1.179 +  // by looking at the expected compilation and execution times of
   1.180 +  // of the inlined call.
   1.181 +
   1.182 +  // Note:  Some of these metrics may not be present in the final product,
   1.183 +  // but exist in development builds to experiment with inline policy tuning.
   1.184 +
   1.185 +  // This heuristic framework does not model well the very significant
   1.186 +  // effects of multiple-level inlining.  It is possible to see no immediate
   1.187 +  // profit from inlining X->Y, but to get great profit from a subsequent
   1.188 +  // inlining X->Y->Z.
   1.189 +
   1.190 +  // This framework does not take well into account the problem of N**2 code
   1.191 +  // size in a clique of mutually inlinable methods.
   1.192 +
   1.193 +  WarmCallInfo*  next() const          { return _next; }
   1.194 +  void       set_next(WarmCallInfo* n) { _next = n; }
   1.195 +
   1.196 +  static WarmCallInfo* _always_hot;
   1.197 +  static WarmCallInfo* _always_cold;
   1.198 +
   1.199 + public:
   1.200 +  // Because WarmInfo objects live over the entire lifetime of the
   1.201 +  // Compile object, they are allocated into the comp_arena, which
   1.202 +  // does not get resource marked or reset during the compile process
   1.203 +  void *operator new( size_t x, Compile* C ) { return C->comp_arena()->Amalloc(x); }
   1.204 +  void operator delete( void * ) { } // fast deallocation
   1.205 +
   1.206 +  static WarmCallInfo* always_hot();
   1.207 +  static WarmCallInfo* always_cold();
   1.208 +
   1.209 +  WarmCallInfo() {
   1.210 +    _call = NULL;
   1.211 +    _hot_cg = NULL;
   1.212 +    _next = NULL;
   1.213 +    _count = _profit = _work = _size = _heat = 0;
   1.214 +  }
   1.215 +
   1.216 +  CallNode* call() const { return _call; }
   1.217 +  float count()    const { return _count; }
   1.218 +  float size()     const { return _size; }
   1.219 +  float work()     const { return _work; }
   1.220 +  float profit()   const { return _profit; }
   1.221 +  float heat()     const { return _heat; }
   1.222 +
   1.223 +  void set_count(float x)     { _count = x; }
   1.224 +  void set_size(float x)      { _size = x; }
   1.225 +  void set_work(float x)      { _work = x; }
   1.226 +  void set_profit(float x)    { _profit = x; }
   1.227 +  void set_heat(float x)      { _heat = x; }
   1.228 +
   1.229 +  // Load initial heuristics from profiles, etc.
   1.230 +  // The heuristics can be tweaked further by the caller.
   1.231 +  void init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor);
   1.232 +
   1.233 +  static float MAX_VALUE() { return +1.0e10; }
   1.234 +  static float MIN_VALUE() { return -1.0e10; }
   1.235 +
   1.236 +  float compute_heat() const;
   1.237 +
   1.238 +  void set_call(CallNode* call)      { _call = call; }
   1.239 +  void set_hot_cg(CallGenerator* cg) { _hot_cg = cg; }
   1.240 +
   1.241 +  // Do not queue very hot or very cold calls.
   1.242 +  // Make very cold ones out of line immediately.
   1.243 +  // Inline very hot ones immediately.
   1.244 +  // These queries apply various tunable limits
   1.245 +  // to the above metrics in a systematic way.
   1.246 +  // Test for coldness before testing for hotness.
   1.247 +  bool is_cold() const;
   1.248 +  bool is_hot() const;
   1.249 +
   1.250 +  // Force a warm call to be hot.  This worklists the call node for inlining.
   1.251 +  void make_hot();
   1.252 +
   1.253 +  // Force a warm call to be cold.  This worklists the call node for out-of-lining.
   1.254 +  void make_cold();
   1.255 +
   1.256 +  // A reproducible total ordering, in which heat is the major key.
   1.257 +  bool warmer_than(WarmCallInfo* that);
   1.258 +
   1.259 +  // List management.  These methods are called with the list head,
   1.260 +  // and return the new list head, inserting or removing the receiver.
   1.261 +  WarmCallInfo* insert_into(WarmCallInfo* head);
   1.262 +  WarmCallInfo* remove_from(WarmCallInfo* head);
   1.263 +
   1.264 +#ifndef PRODUCT
   1.265 +  void print() const;
   1.266 +  void print_all() const;
   1.267 +  int count_all() const;
   1.268 +#endif
   1.269 +};

mercurial