1 /*
   2  * Copyright (c) 1999, 2010, 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 #ifndef SHARE_VM_SHARK_SHARKVALUE_HPP
  27 #define SHARE_VM_SHARK_SHARKVALUE_HPP
  28 
  29 #include "ci/ciType.hpp"
  30 #include "memory/allocation.hpp"
  31 #include "shark/llvmHeaders.hpp"
  32 #include "shark/llvmValue.hpp"
  33 #include "shark/sharkType.hpp"
  34 
  35 // Items on the stack and in local variables are tracked using
  36 // SharkValue objects.
  37 //
  38 // All SharkValues are one of two core types, SharkNormalValue
  39 // and SharkAddressValue, but no code outside this file should
  40 // ever refer to those directly.  The split is because of the
  41 // way JSRs are handled: the typeflow pass expands them into
  42 // multiple copies, so the return addresses pushed by jsr and
  43 // popped by ret only exist at compile time.  Having separate
  44 // classes for these allows us to check that our jsr handling
  45 // is correct, via assertions.
  46 //
  47 // There is one more type, SharkPHIValue, which is a subclass
  48 // of SharkNormalValue with a couple of extra methods.  Use of
  49 // SharkPHIValue outside of this file is acceptable, so long
  50 // as it is obtained via SharkValue::as_phi().
  51 
  52 class SharkBuilder;
  53 class SharkPHIValue;
  54 
  55 class SharkValue : public ResourceObj {
  56  protected:
  57   SharkValue() {}
  58 
  59   // Cloning
  60  public:
  61   virtual SharkValue* clone() const = 0;
  62 
  63   // Casting
  64  public:
  65   virtual bool           is_phi() const;
  66   virtual SharkPHIValue* as_phi();
  67 
  68   // Comparison
  69  public:
  70   virtual bool equal_to(SharkValue* other) const = 0;
  71 
  72   // Type access
  73  public:
  74   virtual BasicType basic_type() const = 0;
  75   virtual ciType*   type()       const;
  76 
  77   virtual bool is_jint()    const;
  78   virtual bool is_jlong()   const;
  79   virtual bool is_jfloat()  const;
  80   virtual bool is_jdouble() const;
  81   virtual bool is_jobject() const;
  82   virtual bool is_jarray()  const;
  83   virtual bool is_address() const;
  84 
  85   virtual int size() const = 0;
  86 
  87   bool is_one_word() const {
  88     return size() == 1;
  89   }
  90   bool is_two_word() const {
  91     return size() == 2;
  92   }
  93 
  94   // Typed conversion from SharkValues
  95  public:
  96   virtual llvm::Value* jint_value()    const;
  97   virtual llvm::Value* jlong_value()   const;
  98   virtual llvm::Value* jfloat_value()  const;
  99   virtual llvm::Value* jdouble_value() const;
 100   virtual llvm::Value* jobject_value() const;
 101   virtual llvm::Value* jarray_value()  const;
 102   virtual int          address_value() const;
 103 
 104   // Typed conversion to SharkValues
 105  public:
 106   static SharkValue* create_jint(llvm::Value* value, bool zero_checked) {
 107     assert(value->getType() == SharkType::jint_type(), "should be");
 108     return create_generic(ciType::make(T_INT), value, zero_checked);
 109   }
 110   static SharkValue* create_jlong(llvm::Value* value, bool zero_checked) {
 111     assert(value->getType() == SharkType::jlong_type(), "should be");
 112     return create_generic(ciType::make(T_LONG), value, zero_checked);
 113   }
 114   static SharkValue* create_jfloat(llvm::Value* value) {
 115     assert(value->getType() == SharkType::jfloat_type(), "should be");
 116     return create_generic(ciType::make(T_FLOAT), value, false);
 117   }
 118   static SharkValue* create_jdouble(llvm::Value* value) {
 119     assert(value->getType() == SharkType::jdouble_type(), "should be");
 120     return create_generic(ciType::make(T_DOUBLE), value, false);
 121   }
 122   static SharkValue* create_jobject(llvm::Value* value, bool zero_checked) {
 123     assert(value->getType() == SharkType::oop_type(), "should be");
 124     return create_generic(ciType::make(T_OBJECT), value, zero_checked);
 125   }
 126 
 127   // Typed conversion from constants of various types
 128  public:
 129   static SharkValue* jint_constant(jint value) {
 130     return create_jint(LLVMValue::jint_constant(value), value != 0);
 131   }
 132   static SharkValue* jlong_constant(jlong value) {
 133     return create_jlong(LLVMValue::jlong_constant(value), value != 0);
 134   }
 135   static SharkValue* jfloat_constant(jfloat value) {
 136     return create_jfloat(LLVMValue::jfloat_constant(value));
 137   }
 138   static SharkValue* jdouble_constant(jdouble value) {
 139     return create_jdouble(LLVMValue::jdouble_constant(value));
 140   }
 141   static SharkValue* null() {
 142     return create_jobject(LLVMValue::null(), false);
 143   }
 144   static inline SharkValue* address_constant(int bci);
 145 
 146   // Type-losing conversions -- use with care!
 147  public:
 148   virtual llvm::Value* generic_value() const = 0;
 149   virtual llvm::Value* intptr_value(SharkBuilder* builder) const;
 150 
 151   static inline SharkValue* create_generic(ciType*      type,
 152                                            llvm::Value* value,
 153                                            bool         zero_checked);
 154   static inline SharkValue* create_phi(ciType*              type,
 155                                        llvm::PHINode*       phi,
 156                                        const SharkPHIValue* parent = NULL);
 157 
 158   // Phi-style stuff
 159  public:
 160   virtual void addIncoming(SharkValue* value, llvm::BasicBlock* block);
 161   virtual SharkValue* merge(SharkBuilder*     builder,
 162                             SharkValue*       other,
 163                             llvm::BasicBlock* other_block,
 164                             llvm::BasicBlock* this_block,
 165                             const char*       name) = 0;
 166 
 167   // Repeated null and divide-by-zero check removal
 168  public:
 169   virtual bool zero_checked() const;
 170   virtual void set_zero_checked(bool zero_checked);
 171 };
 172 
 173 class SharkNormalValue : public SharkValue {
 174   friend class SharkValue;
 175 
 176  protected:
 177   SharkNormalValue(ciType* type, llvm::Value* value, bool zero_checked)
 178     : _type(type), _llvm_value(value), _zero_checked(zero_checked) {}
 179 
 180  private:
 181   ciType*      _type;
 182   llvm::Value* _llvm_value;
 183   bool         _zero_checked;
 184 
 185  private:
 186   llvm::Value* llvm_value() const {
 187     return _llvm_value;
 188   }
 189 
 190   // Cloning
 191  public:
 192   SharkValue* clone() const;
 193 
 194   // Comparison
 195  public:
 196   bool equal_to(SharkValue* other) const;
 197 
 198   // Type access
 199  public:
 200   ciType*   type()       const;
 201   BasicType basic_type() const;
 202   int       size()       const;
 203 
 204  public:
 205   bool is_jint()    const;
 206   bool is_jlong()   const;
 207   bool is_jfloat()  const;
 208   bool is_jdouble() const;
 209   bool is_jobject() const;
 210   bool is_jarray()  const;
 211 
 212   // Typed conversions to LLVM values
 213  public:
 214   llvm::Value* jint_value()    const;
 215   llvm::Value* jlong_value()   const;
 216   llvm::Value* jfloat_value()  const;
 217   llvm::Value* jdouble_value() const;
 218   llvm::Value* jobject_value() const;
 219   llvm::Value* jarray_value()  const;
 220 
 221   // Type-losing conversions, use with care
 222  public:
 223   llvm::Value* generic_value() const;
 224   llvm::Value* intptr_value(SharkBuilder* builder) const;
 225 
 226   // Phi-style stuff
 227  public:
 228   SharkValue* merge(SharkBuilder*     builder,
 229                     SharkValue*       other,
 230                     llvm::BasicBlock* other_block,
 231                     llvm::BasicBlock* this_block,
 232                     const char*       name);
 233 
 234   // Repeated null and divide-by-zero check removal
 235  public:
 236   bool zero_checked() const;
 237   void set_zero_checked(bool zero_checked);
 238 };
 239 
 240 class SharkPHIValue : public SharkNormalValue {
 241   friend class SharkValue;
 242 
 243  protected:
 244   SharkPHIValue(ciType* type, llvm::PHINode* phi, const SharkPHIValue *parent)
 245     : SharkNormalValue(type, phi, parent && parent->zero_checked()),
 246       _parent(parent),
 247       _all_incomers_zero_checked(true) {}
 248 
 249  private:
 250   const SharkPHIValue* _parent;
 251   bool                 _all_incomers_zero_checked;
 252 
 253  private:
 254   const SharkPHIValue* parent() const {
 255     return _parent;
 256   }
 257   bool is_clone() const {
 258     return parent() != NULL;
 259   }
 260 
 261  public:
 262   bool all_incomers_zero_checked() const {
 263     if (is_clone())
 264       return parent()->all_incomers_zero_checked();
 265 
 266     return _all_incomers_zero_checked;
 267   }
 268 
 269   // Cloning
 270  public:
 271   SharkValue* clone() const;
 272 
 273   // Casting
 274  public:
 275   bool           is_phi() const;
 276   SharkPHIValue* as_phi();
 277 
 278   // Phi-style stuff
 279  public:
 280   void addIncoming(SharkValue *value, llvm::BasicBlock* block);
 281 };
 282 
 283 class SharkAddressValue : public SharkValue {
 284   friend class SharkValue;
 285 
 286  protected:
 287   SharkAddressValue(int bci)
 288     : _bci(bci) {}
 289 
 290  private:
 291   int _bci;
 292 
 293   // Cloning
 294  public:
 295   SharkValue* clone() const;
 296 
 297   // Comparison
 298  public:
 299   bool equal_to(SharkValue* other) const;
 300 
 301   // Type access
 302  public:
 303   BasicType basic_type() const;
 304   int       size()       const;
 305   bool      is_address() const;
 306 
 307   // Typed conversion from SharkValues
 308  public:
 309   int address_value() const;
 310 
 311   // Type-losing conversion -- use with care!
 312  public:
 313   llvm::Value* generic_value() const;
 314 
 315   // Phi-style stuff
 316  public:
 317   void addIncoming(SharkValue *value, llvm::BasicBlock* block);
 318   SharkValue* merge(SharkBuilder*     builder,
 319                     SharkValue*       other,
 320                     llvm::BasicBlock* other_block,
 321                     llvm::BasicBlock* this_block,
 322                     const char*       name);
 323 };
 324 
 325 // SharkValue methods that can't be declared above
 326 
 327 inline SharkValue* SharkValue::create_generic(ciType*      type,
 328                                               llvm::Value* value,
 329                                               bool         zero_checked) {
 330   return new SharkNormalValue(type, value, zero_checked);
 331 }
 332 
 333 inline SharkValue* SharkValue::create_phi(ciType*              type,
 334                                           llvm::PHINode*       phi,
 335                                           const SharkPHIValue* parent) {
 336   return new SharkPHIValue(type, phi, parent);
 337 }
 338 
 339 inline SharkValue* SharkValue::address_constant(int bci) {
 340   return new SharkAddressValue(bci);
 341 }
 342 
 343 #endif // SHARE_VM_SHARK_SHARKVALUE_HPP