view src/share/vm/shark/sharkValue.hpp @ 17716:cdb71841f4bc

6498581: ThreadInterruptTest3 produces wrong output on Windows Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set. Reviewed-by: acorn, kvn Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author minqi
date Wed, 26 Feb 2014 15:20:41 -0800
parents f95d63e2154a
children
line wrap: on
line source

/*
 * Copyright (c) 1999, 2010, 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.
 *
 */

#ifndef SHARE_VM_SHARK_SHARKVALUE_HPP
#define SHARE_VM_SHARK_SHARKVALUE_HPP

#include "ci/ciType.hpp"
#include "memory/allocation.hpp"
#include "shark/llvmHeaders.hpp"
#include "shark/llvmValue.hpp"
#include "shark/sharkType.hpp"

// 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);
}

#endif // SHARE_VM_SHARK_SHARKVALUE_HPP