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