1 /*
   2  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_RUNTIME_STACKVALUE_HPP
  26 #define SHARE_RUNTIME_STACKVALUE_HPP
  27 
  28 #include "code/debugInfo.hpp"
  29 #include "code/location.hpp"
  30 #include "runtime/handles.hpp"
  31 
  32 class BasicLock;
  33 class RegisterMap;
  34 
  35 class StackValue : public ResourceObj {
  36  private:
  37   BasicType _type;
  38   intptr_t  _integer_value; // Blank java stack slot value
  39   Handle    _handle_value;  // Java stack slot value interpreted as a Handle
  40  public:
  41 
  42   StackValue(intptr_t value) {
  43     _type              = T_INT;
  44     _integer_value     = value;
  45   }
  46 
  47   StackValue(Handle value, intptr_t scalar_replaced = 0) {
  48     _type                = T_OBJECT;
  49     _integer_value       = scalar_replaced;
  50     _handle_value        = value;
  51     assert(_integer_value == 0 ||  _handle_value.is_null(), "not null object should not be marked as scalar replaced");
  52   }
  53 
  54   StackValue() {
  55     _type           = T_CONFLICT;
  56     _integer_value  = 0;
  57   }
  58 
  59   // Only used during deopt- preserve object type.
  60   StackValue(intptr_t o, BasicType t) {
  61     assert(t == T_OBJECT, "should not be used");
  62     _type          = t;
  63     _integer_value = o;
  64   }
  65 
  66   Handle get_obj() const {
  67     assert(type() == T_OBJECT, "type check");
  68     return _handle_value;
  69   }
  70 
  71   bool obj_is_scalar_replaced() const {
  72     assert(type() == T_OBJECT, "type check");
  73     return _integer_value != 0;
  74   }
  75 
  76   void set_obj(Handle value) {
  77     assert(type() == T_OBJECT, "type check");
  78     _handle_value = value;
  79   }
  80 
  81   intptr_t get_int() const {
  82     assert(type() == T_INT, "type check");
  83     return _integer_value;
  84   }
  85 
  86   // For special case in deopt.
  87   intptr_t get_int(BasicType t) const {
  88     assert(t == T_OBJECT && type() == T_OBJECT, "type check");
  89     return _integer_value;
  90   }
  91 
  92   void set_int(intptr_t value) {
  93     assert(type() == T_INT, "type check");
  94     _integer_value = value;
  95   }
  96 
  97   BasicType type() const { return  _type; }
  98 
  99   bool equal(StackValue *value) {
 100     if (_type != value->_type) return false;
 101     if (_type == T_OBJECT)
 102       return (_handle_value == value->_handle_value);
 103     else {
 104       assert(_type == T_INT, "sanity check");
 105       // [phh] compare only low addressed portions of intptr_t slots
 106       return (*(int *)&_integer_value == *(int *)&value->_integer_value);
 107     }
 108   }
 109 
 110   static BasicLock*  resolve_monitor_lock(const frame* fr, Location location);
 111 
 112   template<typename RegisterMapT>
 113   static StackValue* create_stack_value(const frame* fr, const RegisterMapT* reg_map, ScopeValue* sv) {
 114     return create_stack_value(sv, stack_value_address(fr, reg_map, sv), reg_map->in_cont());
 115   }
 116 
 117   template<typename RegisterMapT>
 118   static address stack_value_address(const frame* fr, const RegisterMapT* reg_map, ScopeValue* sv) {
 119     if (!sv->is_location())
 120       return NULL;
 121     Location loc = ((LocationValue *)sv)->location();
 122     if (loc.type() == Location::invalid)
 123       return NULL;
 124     
 125     address value_addr;
 126     if (!reg_map->in_cont()) {
 127       value_addr = loc.is_register()
 128           // Value was in a callee-save register
 129           ? reg_map->location(VMRegImpl::as_VMReg(loc.register_number()))
 130           // Else value was directly saved on the stack. The frame's original stack pointer,
 131           // before any extension by its callee (due to Compiler1 linkage on SPARC), must be used.
 132           : ((address)fr->unextended_sp()) + loc.stack_offset();
 133 
 134       assert(value_addr == NULL || reg_map->thread()->is_in_usable_stack(value_addr), INTPTR_FORMAT, p2i(value_addr));
 135     } else {
 136       value_addr = loc.is_register()
 137           ? Continuation::reg_to_location(*fr, reg_map->as_RegisterMap(), VMRegImpl::as_VMReg(loc.register_number()), loc.type() == Location::oop || loc.type() == Location::narrowoop)
 138           : Continuation::usp_offset_to_location(*fr, reg_map->as_RegisterMap(), loc.stack_offset(), loc.type() == Location::oop || loc.type() == Location::narrowoop);
 139         
 140       assert(value_addr == NULL || Continuation::is_in_usable_stack(value_addr, reg_map->as_RegisterMap()), INTPTR_FORMAT, p2i(value_addr));
 141     }
 142     return value_addr;
 143   }
 144 
 145 #ifndef PRODUCT
 146  public:
 147   // Printing
 148   void print_on(outputStream* st) const;
 149 #endif
 150 
 151 private:
 152   static StackValue* create_stack_value(ScopeValue* sv, address value_addr, bool in_cont);
 153 };
 154 
 155 #endif // SHARE_RUNTIME_STACKVALUE_HPP