1 /*
   2  * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright 2008, 2009 Red Hat, Inc.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 // Class hierarchy:
  27 // - SharkStateScanner
  28 //   - SharkCacherDecacher
  29 //     - SharkDecacher
  30 //       - SharkJavaCallDecacher
  31 //       - SharkVMCallDecacher
  32 //       - SharkTrapDecacher
  33 //     - SharkCacher
  34 //       - SharkJavaCallCacher
  35 //       - SharkVMCallCacher
  36 //       - SharkFunctionEntryCacher
  37 //         - SharkNormalEntryCacher
  38 //         - SharkOSREntryCacher
  39 
  40 class SharkCacherDecacher : public SharkStateScanner {
  41  protected:
  42   SharkCacherDecacher(SharkFunction* function)
  43     : SharkStateScanner(function) {}
  44 
  45   // Helper
  46  protected:
  47   static int adjusted_offset(SharkValue* value, int offset) {
  48     if (value->is_two_word())
  49       offset--;
  50     return offset;
  51   }
  52 };
  53 
  54 class SharkDecacher : public SharkCacherDecacher {
  55  protected:
  56   SharkDecacher(SharkFunction* function, int bci)
  57     : SharkCacherDecacher(function), _bci(bci) {}
  58 
  59  private:
  60   int _bci;
  61 
  62  protected:
  63   int bci() const {
  64     return _bci;
  65   }
  66 
  67  private:
  68   int                           _pc_offset;
  69   OopMap*                       _oopmap;
  70   GrowableArray<ScopeValue*>*   _exparray;
  71   GrowableArray<MonitorValue*>* _monarray;
  72   GrowableArray<ScopeValue*>*   _locarray;
  73 
  74  private:
  75   int pc_offset() const {
  76     return _pc_offset;
  77   }
  78   OopMap* oopmap() const {
  79     return _oopmap;
  80   }
  81   GrowableArray<ScopeValue*>* exparray() const {
  82     return _exparray;
  83   }
  84   GrowableArray<MonitorValue*>* monarray() const {
  85     return _monarray;
  86   }
  87   GrowableArray<ScopeValue*>* locarray() const {
  88     return _locarray;
  89   }
  90 
  91   // Callbacks
  92  protected:
  93   void start_frame();
  94 
  95   void start_stack(int stack_depth);
  96   void process_stack_slot(int index, SharkValue** value, int offset);
  97 
  98   void start_monitors(int num_monitors);
  99   void process_monitor(int index, int box_offset, int obj_offset);
 100 
 101   void process_oop_tmp_slot(llvm::Value** value, int offset);
 102   void process_method_slot(llvm::Value** value, int offset);
 103   void process_pc_slot(int offset);
 104 
 105   void start_locals();
 106   void process_local_slot(int index, SharkValue** value, int offset);
 107 
 108   void end_frame();
 109 
 110   // oopmap and debuginfo helpers
 111  private:
 112   static int oopmap_slot_munge(int offset) {
 113     return SharkStack::oopmap_slot_munge(offset);
 114   }
 115   static VMReg slot2reg(int offset) {
 116     return SharkStack::slot2reg(offset);
 117   }
 118   static Location slot2loc(int offset, Location::Type type) {
 119     return Location::new_stk_loc(type, offset * wordSize);
 120   }
 121   static LocationValue* slot2lv(int offset, Location::Type type) {
 122     return new LocationValue(slot2loc(offset, type));
 123   }
 124   static Location::Type location_type(SharkValue** addr, bool maybe_two_word) {
 125     // low addresses this end
 126     //                           Type       32-bit    64-bit
 127     //   ----------------------------------------------------
 128     //   stack[0]    local[3]    jobject    oop       oop
 129     //   stack[1]    local[2]    NULL       normal    lng
 130     //   stack[2]    local[1]    jlong      normal    invalid
 131     //   stack[3]    local[0]    jint       normal    normal
 132     //
 133     // high addresses this end
 134 
 135     SharkValue *value = *addr;
 136     if (value) {
 137       if (value->is_jobject())
 138         return Location::oop;
 139 #ifdef _LP64
 140       if (value->is_two_word())
 141         return Location::invalid;
 142 #endif // _LP64
 143       return Location::normal;
 144     }
 145     else {
 146       if (maybe_two_word) {
 147         value = *(addr - 1);
 148         if (value && value->is_two_word()) {
 149 #ifdef _LP64
 150           if (value->is_jlong())
 151             return Location::lng;
 152           if (value->is_jdouble())
 153             return Location::dbl;
 154           ShouldNotReachHere();
 155 #else
 156           return Location::normal;
 157 #endif // _LP64
 158         }
 159       }
 160       return Location::invalid;
 161     }
 162   }
 163 
 164   // Stack slot helpers
 165  protected:
 166   virtual bool stack_slot_needs_write(int index, SharkValue* value) = 0;
 167   virtual bool stack_slot_needs_oopmap(int index, SharkValue* value) = 0;
 168   virtual bool stack_slot_needs_debuginfo(int index, SharkValue* value) = 0;
 169 
 170   static Location::Type stack_location_type(int index, SharkValue** addr) {
 171     return location_type(addr, *addr == NULL);
 172   }
 173 
 174   // Local slot helpers
 175  protected:
 176   virtual bool local_slot_needs_write(int index, SharkValue* value) = 0;
 177   virtual bool local_slot_needs_oopmap(int index, SharkValue* value) = 0;
 178   virtual bool local_slot_needs_debuginfo(int index, SharkValue* value) = 0;
 179 
 180   static Location::Type local_location_type(int index, SharkValue** addr) {
 181     return location_type(addr, index > 0);
 182   }
 183 
 184   // Writer helper
 185  protected:
 186   void write_value_to_frame(const llvm::Type* type,
 187                             llvm::Value*      value,
 188                             int               offset);
 189 };
 190 
 191 class SharkJavaCallDecacher : public SharkDecacher {
 192  public:
 193   SharkJavaCallDecacher(SharkFunction* function, int bci, ciMethod* callee)
 194     : SharkDecacher(function, bci), _callee(callee) {}
 195 
 196  private:
 197   ciMethod* _callee;
 198 
 199  protected:
 200   ciMethod* callee() const {
 201     return _callee;
 202   }
 203 
 204   // Stack slot helpers
 205  protected:
 206   bool stack_slot_needs_write(int index, SharkValue* value) {
 207     return value && (index < callee()->arg_size() || value->is_jobject());
 208   }
 209   bool stack_slot_needs_oopmap(int index, SharkValue* value) {
 210     return value && value->is_jobject() && index >= callee()->arg_size();
 211   }
 212   bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
 213     return index >= callee()->arg_size();
 214   }
 215 
 216   // Local slot helpers
 217  protected:
 218   bool local_slot_needs_write(int index, SharkValue* value) {
 219     return value && value->is_jobject();
 220   }
 221   bool local_slot_needs_oopmap(int index, SharkValue* value) {
 222     return value && value->is_jobject();
 223   }
 224   bool local_slot_needs_debuginfo(int index, SharkValue* value) {
 225     return true;
 226   }
 227 };
 228 
 229 class SharkVMCallDecacher : public SharkDecacher {
 230  public:
 231   SharkVMCallDecacher(SharkFunction* function, int bci)
 232     : SharkDecacher(function, bci) {}
 233 
 234   // Stack slot helpers
 235  protected:
 236   bool stack_slot_needs_write(int index, SharkValue* value) {
 237     return value && value->is_jobject();
 238   }
 239   bool stack_slot_needs_oopmap(int index, SharkValue* value) {
 240     return value && value->is_jobject();
 241   }
 242   bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
 243     return true;
 244   }
 245 
 246   // Local slot helpers
 247  protected:
 248   bool local_slot_needs_write(int index, SharkValue* value) {
 249     return value && value->is_jobject();
 250   }
 251   bool local_slot_needs_oopmap(int index, SharkValue* value) {
 252     return value && value->is_jobject();
 253   }
 254   bool local_slot_needs_debuginfo(int index, SharkValue* value) {
 255     return true;
 256   }
 257 };
 258 
 259 class SharkTrapDecacher : public SharkDecacher {
 260  public:
 261   SharkTrapDecacher(SharkFunction* function, int bci)
 262     : SharkDecacher(function, bci) {}
 263 
 264   // Stack slot helpers
 265  protected:
 266   bool stack_slot_needs_write(int index, SharkValue* value) {
 267     return value != NULL;
 268   }
 269   bool stack_slot_needs_oopmap(int index, SharkValue* value) {
 270     return value && value->is_jobject();
 271   }
 272   bool stack_slot_needs_debuginfo(int index, SharkValue* value) {
 273     return true;
 274   }
 275 
 276   // Local slot helpers
 277  protected:
 278   bool local_slot_needs_write(int index, SharkValue* value) {
 279     return value != NULL;
 280   }
 281   bool local_slot_needs_oopmap(int index, SharkValue* value) {
 282     return value && value->is_jobject();
 283   }
 284   bool local_slot_needs_debuginfo(int index, SharkValue* value) {
 285     return true;
 286   }
 287 };
 288 
 289 class SharkCacher : public SharkCacherDecacher {
 290  protected:
 291   SharkCacher(SharkFunction* function)
 292     : SharkCacherDecacher(function) {}
 293 
 294   // Callbacks
 295  protected:
 296   void process_stack_slot(int index, SharkValue** value, int offset);
 297 
 298   void process_oop_tmp_slot(llvm::Value** value, int offset);
 299   virtual void process_method_slot(llvm::Value** value, int offset);
 300 
 301   virtual void process_local_slot(int index, SharkValue** value, int offset);
 302 
 303   // Stack slot helper
 304  protected:
 305   virtual bool stack_slot_needs_read(int index, SharkValue* value) = 0;
 306 
 307   // Local slot helper
 308  protected:
 309   virtual bool local_slot_needs_read(int index, SharkValue* value) {
 310     return value && value->is_jobject();
 311   }
 312 
 313   // Writer helper
 314  protected:
 315   llvm::Value* read_value_from_frame(const llvm::Type* type, int offset);
 316 };
 317 
 318 class SharkJavaCallCacher : public SharkCacher {
 319  public:
 320   SharkJavaCallCacher(SharkFunction* function, ciMethod* callee)
 321     : SharkCacher(function), _callee(callee) {}
 322 
 323  private:
 324   ciMethod* _callee;
 325 
 326  protected:
 327   ciMethod* callee() const {
 328     return _callee;
 329   }
 330 
 331   // Stack slot helper
 332  protected:
 333   bool stack_slot_needs_read(int index, SharkValue* value) {
 334     return value && (index < callee()->return_type()->size() ||
 335                      value->is_jobject());
 336   }
 337 };
 338 
 339 class SharkVMCallCacher : public SharkCacher {
 340  public:
 341   SharkVMCallCacher(SharkFunction* function)
 342     : SharkCacher(function) {}
 343 
 344   // Stack slot helper
 345  protected:
 346   bool stack_slot_needs_read(int index, SharkValue* value) {
 347     return value && value->is_jobject();
 348   }
 349 };
 350 
 351 class SharkFunctionEntryCacher : public SharkCacher {
 352  public:
 353   SharkFunctionEntryCacher(SharkFunction* function, llvm::Value* method)
 354     : SharkCacher(function), _method(method) {}
 355 
 356  private:
 357   llvm::Value* _method;
 358 
 359  private:
 360   llvm::Value* method() const {
 361     return _method;
 362   }
 363 
 364   // Method slot callback
 365  protected:
 366   void process_method_slot(llvm::Value** value, int offset);
 367 
 368   // Stack slot helper
 369  protected:
 370   bool stack_slot_needs_read(int index, SharkValue* value) {
 371     ShouldNotReachHere(); // entry block shouldn't have stack
 372   }
 373 
 374   // Local slot helper
 375  protected:
 376   bool local_slot_needs_read(int index, SharkValue* value) {
 377     return value != NULL;
 378   }
 379 };
 380 
 381 class SharkNormalEntryCacher : public SharkFunctionEntryCacher {
 382  public:
 383   SharkNormalEntryCacher(SharkFunction* function, llvm::Value* method)
 384     : SharkFunctionEntryCacher(function, method) {}
 385 };
 386 
 387 class SharkOSREntryCacher : public SharkFunctionEntryCacher {
 388  public:
 389   SharkOSREntryCacher(SharkFunction* function,
 390                       llvm::Value*   method,
 391                       llvm::Value*   osr_buf)
 392     : SharkFunctionEntryCacher(function, method),
 393       _osr_buf(
 394         builder()->CreateBitCast(
 395           osr_buf,
 396           llvm::PointerType::getUnqual(
 397             llvm::ArrayType::get(
 398               SharkType::intptr_type(),
 399               max_locals() + max_monitors() * 2)))) {}
 400 
 401  private:
 402   llvm::Value* _osr_buf;
 403 
 404  private:
 405   llvm::Value* osr_buf() const {
 406     return _osr_buf;
 407   }
 408 
 409   // Callbacks
 410  protected:
 411   void process_monitor(int index, int box_offset, int obj_offset);
 412   void process_local_slot(int index, SharkValue** value, int offset);
 413 
 414   // Helper
 415  private:
 416   llvm::Value* CreateAddressOfOSRBufEntry(int offset, const llvm::Type* type);
 417 };