--- /dev/null 2010-06-22 09:23:59.198002222 +0100 +++ new/hotspot/src/share/vm/shark/sharkValue.hpp 2010-06-22 09:53:21.000000000 +0100 @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright 2008, 2009 Red Hat, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +// Items on the stack and in local variables are tracked using +// SharkValue objects. +// +// All SharkValues are one of two core types, SharkNormalValue +// and SharkAddressValue, but no code outside this file should +// ever refer to those directly. The split is because of the +// way JSRs are handled: the typeflow pass expands them into +// multiple copies, so the return addresses pushed by jsr and +// popped by ret only exist at compile time. Having separate +// classes for these allows us to check that our jsr handling +// is correct, via assertions. +// +// There is one more type, SharkPHIValue, which is a subclass +// of SharkNormalValue with a couple of extra methods. Use of +// SharkPHIValue outside of this file is acceptable, so long +// as it is obtained via SharkValue::as_phi(). + +class SharkBuilder; +class SharkPHIValue; + +class SharkValue : public ResourceObj { + protected: + SharkValue() {} + + // Cloning + public: + virtual SharkValue* clone() const = 0; + + // Casting + public: + virtual bool is_phi() const; + virtual SharkPHIValue* as_phi(); + + // Comparison + public: + virtual bool equal_to(SharkValue* other) const = 0; + + // Type access + public: + virtual BasicType basic_type() const = 0; + virtual ciType* type() const; + + virtual bool is_jint() const; + virtual bool is_jlong() const; + virtual bool is_jfloat() const; + virtual bool is_jdouble() const; + virtual bool is_jobject() const; + virtual bool is_jarray() const; + virtual bool is_address() const; + + virtual int size() const = 0; + + bool is_one_word() const { + return size() == 1; + } + bool is_two_word() const { + return size() == 2; + } + + // Typed conversion from SharkValues + public: + virtual llvm::Value* jint_value() const; + virtual llvm::Value* jlong_value() const; + virtual llvm::Value* jfloat_value() const; + virtual llvm::Value* jdouble_value() const; + virtual llvm::Value* jobject_value() const; + virtual llvm::Value* jarray_value() const; + virtual int address_value() const; + + // Typed conversion to SharkValues + public: + static SharkValue* create_jint(llvm::Value* value, bool zero_checked) { + assert(value->getType() == SharkType::jint_type(), "should be"); + return create_generic(ciType::make(T_INT), value, zero_checked); + } + static SharkValue* create_jlong(llvm::Value* value, bool zero_checked) { + assert(value->getType() == SharkType::jlong_type(), "should be"); + return create_generic(ciType::make(T_LONG), value, zero_checked); + } + static SharkValue* create_jfloat(llvm::Value* value) { + assert(value->getType() == SharkType::jfloat_type(), "should be"); + return create_generic(ciType::make(T_FLOAT), value, false); + } + static SharkValue* create_jdouble(llvm::Value* value) { + assert(value->getType() == SharkType::jdouble_type(), "should be"); + return create_generic(ciType::make(T_DOUBLE), value, false); + } + static SharkValue* create_jobject(llvm::Value* value, bool zero_checked) { + assert(value->getType() == SharkType::oop_type(), "should be"); + return create_generic(ciType::make(T_OBJECT), value, zero_checked); + } + + // Typed conversion from constants of various types + public: + static SharkValue* jint_constant(jint value) { + return create_jint(LLVMValue::jint_constant(value), value != 0); + } + static SharkValue* jlong_constant(jlong value) { + return create_jlong(LLVMValue::jlong_constant(value), value != 0); + } + static SharkValue* jfloat_constant(jfloat value) { + return create_jfloat(LLVMValue::jfloat_constant(value)); + } + static SharkValue* jdouble_constant(jdouble value) { + return create_jdouble(LLVMValue::jdouble_constant(value)); + } + static SharkValue* null() { + return create_jobject(LLVMValue::null(), false); + } + static inline SharkValue* address_constant(int bci); + + // Type-losing conversions -- use with care! + public: + virtual llvm::Value* generic_value() const = 0; + virtual llvm::Value* intptr_value(SharkBuilder* builder) const; + + static inline SharkValue* create_generic(ciType* type, + llvm::Value* value, + bool zero_checked); + static inline SharkValue* create_phi(ciType* type, + llvm::PHINode* phi, + const SharkPHIValue* parent = NULL); + + // Phi-style stuff + public: + virtual void addIncoming(SharkValue* value, llvm::BasicBlock* block); + virtual SharkValue* merge(SharkBuilder* builder, + SharkValue* other, + llvm::BasicBlock* other_block, + llvm::BasicBlock* this_block, + const char* name) = 0; + + // Repeated null and divide-by-zero check removal + public: + virtual bool zero_checked() const; + virtual void set_zero_checked(bool zero_checked); +}; + +class SharkNormalValue : public SharkValue { + friend class SharkValue; + + protected: + SharkNormalValue(ciType* type, llvm::Value* value, bool zero_checked) + : _type(type), _llvm_value(value), _zero_checked(zero_checked) {} + + private: + ciType* _type; + llvm::Value* _llvm_value; + bool _zero_checked; + + private: + llvm::Value* llvm_value() const { + return _llvm_value; + } + + // Cloning + public: + SharkValue* clone() const; + + // Comparison + public: + bool equal_to(SharkValue* other) const; + + // Type access + public: + ciType* type() const; + BasicType basic_type() const; + int size() const; + + public: + bool is_jint() const; + bool is_jlong() const; + bool is_jfloat() const; + bool is_jdouble() const; + bool is_jobject() const; + bool is_jarray() const; + + // Typed conversions to LLVM values + public: + llvm::Value* jint_value() const; + llvm::Value* jlong_value() const; + llvm::Value* jfloat_value() const; + llvm::Value* jdouble_value() const; + llvm::Value* jobject_value() const; + llvm::Value* jarray_value() const; + + // Type-losing conversions, use with care + public: + llvm::Value* generic_value() const; + llvm::Value* intptr_value(SharkBuilder* builder) const; + + // Phi-style stuff + public: + SharkValue* merge(SharkBuilder* builder, + SharkValue* other, + llvm::BasicBlock* other_block, + llvm::BasicBlock* this_block, + const char* name); + + // Repeated null and divide-by-zero check removal + public: + bool zero_checked() const; + void set_zero_checked(bool zero_checked); +}; + +class SharkPHIValue : public SharkNormalValue { + friend class SharkValue; + + protected: + SharkPHIValue(ciType* type, llvm::PHINode* phi, const SharkPHIValue *parent) + : SharkNormalValue(type, phi, parent && parent->zero_checked()), + _parent(parent), + _all_incomers_zero_checked(true) {} + + private: + const SharkPHIValue* _parent; + bool _all_incomers_zero_checked; + + private: + const SharkPHIValue* parent() const { + return _parent; + } + bool is_clone() const { + return parent() != NULL; + } + + public: + bool all_incomers_zero_checked() const { + if (is_clone()) + return parent()->all_incomers_zero_checked(); + + return _all_incomers_zero_checked; + } + + // Cloning + public: + SharkValue* clone() const; + + // Casting + public: + bool is_phi() const; + SharkPHIValue* as_phi(); + + // Phi-style stuff + public: + void addIncoming(SharkValue *value, llvm::BasicBlock* block); +}; + +class SharkAddressValue : public SharkValue { + friend class SharkValue; + + protected: + SharkAddressValue(int bci) + : _bci(bci) {} + + private: + int _bci; + + // Cloning + public: + SharkValue* clone() const; + + // Comparison + public: + bool equal_to(SharkValue* other) const; + + // Type access + public: + BasicType basic_type() const; + int size() const; + bool is_address() const; + + // Typed conversion from SharkValues + public: + int address_value() const; + + // Type-losing conversion -- use with care! + public: + llvm::Value* generic_value() const; + + // Phi-style stuff + public: + void addIncoming(SharkValue *value, llvm::BasicBlock* block); + SharkValue* merge(SharkBuilder* builder, + SharkValue* other, + llvm::BasicBlock* other_block, + llvm::BasicBlock* this_block, + const char* name); +}; + +// SharkValue methods that can't be declared above + +inline SharkValue* SharkValue::create_generic(ciType* type, + llvm::Value* value, + bool zero_checked) { + return new SharkNormalValue(type, value, zero_checked); +} + +inline SharkValue* SharkValue::create_phi(ciType* type, + llvm::PHINode* phi, + const SharkPHIValue* parent) { + return new SharkPHIValue(type, phi, parent); +} + +inline SharkValue* SharkValue::address_constant(int bci) { + return new SharkAddressValue(bci); +}