1 /*
  2  * Copyright (c) 1998, 2015, 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_VM_COMPILER_OOPMAP_INLINE_HPP
 26 #define SHARE_VM_COMPILER_OOPMAP_INLINE_HPP
 27 
 28 #include "gc/shared/collectedHeap.hpp"
 29 #include "gc/shared/gc_globals.hpp"
 30 #include "memory/universe.hpp"
 31 #include "oops/compressedOops.hpp"
 32 
 33 inline const ImmutableOopMap* ImmutableOopMapSet::find_map_at_slot(int slot, int pc_offset) const {
 34   assert(slot >= 0 && slot < _count, "bounds count: %d slot: %d", _count, slot);
 35   ImmutableOopMapPair* pairs = get_pairs();
 36   ImmutableOopMapPair* last = &pairs[slot];
 37   assert(last->pc_offset() == pc_offset, "oopmap not found");
 38   return last->get_from(this);
 39 }
 40 
 41 inline const ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const {
 42   return set->oopmap_at_offset(_oopmap_offset);
 43 }
 44 
 45 inline bool SkipNullValue::should_skip(oop val) {
 46   return val == (oop)NULL || CompressedOops::is_base(val);
 47 }
 48 
 49 template <typename OopFnT, typename DerivedOopFnT, typename ValueFilterT>
 50 template <typename RegisterMapT>
 51 void OopMapDo<OopFnT, DerivedOopFnT, ValueFilterT>::iterate_oops_do(const frame *fr, const RegisterMapT *reg_map, const ImmutableOopMap* oopmap) {
 52   NOT_PRODUCT(if (TraceCodeBlobStacks) OopMapSet::trace_codeblob_maps(fr, reg_map->as_RegisterMap());)
 53   assert (fr != NULL, "");
 54 
 55   // handle derived pointers first (otherwise base pointer may be
 56   // changed before derived pointer offset has been collected)
 57   if (_derived_oop_fn != nullptr) {
 58     for (OopMapStream oms(oopmap); !oms.is_done(); oms.next()) {
 59       OopMapValue omv = oms.current();
 60       if (omv.type() != OopMapValue::derived_oop_value)
 61         continue;
 62         
 63   #ifndef COMPILER2
 64       COMPILER1_PRESENT(ShouldNotReachHere();)
 65   #if INCLUDE_JVMCI
 66       if (UseJVMCICompiler) {
 67         ShouldNotReachHere();
 68       }
 69   #endif
 70   #endif // !COMPILER2
 71 
 72       address loc = fr->oopmapreg_to_location(omv.reg(), reg_map);
 73 
 74       DEBUG_ONLY(if (reg_map->should_skip_missing()) continue;)
 75       guarantee(loc != NULL, "missing saved register");
 76       derived_pointer* derived_loc = (derived_pointer*)loc;
 77       oop* base_loc = fr->oopmapreg_to_oop_location(omv.content_reg(), reg_map);
 78       // Ignore NULL oops and decoded NULL narrow oops which
 79       // equal to CompressedOops::base() when a narrow oop
 80       // implicit null check is used in compiled code.
 81       // The narrow_oop_base could be NULL or be the address
 82       // of the page below heap depending on compressed oops mode.
 83       if (base_loc != NULL && *base_loc != (oop)NULL && !CompressedOops::is_base(*base_loc)) {
 84         _derived_oop_fn->do_derived_oop(base_loc, derived_loc);
 85       }
 86     }
 87   }
 88 
 89   // We want coop and oop oop_types
 90   if (_oop_fn != nullptr) {
 91     for (OopMapStream oms(oopmap); !oms.is_done(); oms.next()) {
 92       OopMapValue omv = oms.current();
 93       if (omv.type() != OopMapValue::oop_value && omv.type() != OopMapValue::narrowoop_value)
 94         continue;
 95       oop* loc = fr->oopmapreg_to_oop_location(omv.reg(),reg_map);
 96       // It should be an error if no location can be found for a
 97       // register mentioned as contained an oop of some kind.  Maybe
 98       // this was allowed previously because value_value items might
 99       // be missing?
100 #ifdef ASSERT
101       if (loc == NULL) {
102         if (reg_map->should_skip_missing())
103           continue;
104         VMReg reg = omv.reg();
105         tty->print_cr("missing saved register: reg: " INTPTR_FORMAT " %s loc: %p", reg->value(), reg->name(), loc);
106         fr->print_on(tty);
107       }
108 #endif
109       guarantee(loc != NULL, "missing saved register");
110       if ( omv.type() == OopMapValue::oop_value ) {
111         oop val = *loc;
112         if (ValueFilterT::should_skip(val)) { // TODO: UGLY (basically used to decide if we're freezing/thawing continuation)
113           // Ignore NULL oops and decoded NULL narrow oops which
114           // equal to CompressedOops::base() when a narrow oop
115           // implicit null check is used in compiled code.
116           // The narrow_oop_base could be NULL or be the address
117           // of the page below heap depending on compressed oops mode.
118           continue;
119         }
120         _oop_fn->do_oop(loc);
121       } else if ( omv.type() == OopMapValue::narrowoop_value ) {
122         narrowOop *nl = (narrowOop*)loc;
123 #ifndef VM_LITTLE_ENDIAN
124         VMReg vmReg = omv.reg();
125         if (!vmReg->is_stack()) {
126           // compressed oops in registers only take up 4 bytes of an
127           // 8 byte register but they are in the wrong part of the
128           // word so adjust loc to point at the right place.
129           nl = (narrowOop*)((address)nl + 4);
130         }
131 #endif
132         _oop_fn->do_oop(nl);
133       }
134     }
135   }
136 }
137 
138 
139 template <typename OopFnT, typename DerivedOopFnT, typename ValueFilterT>
140 template <typename RegisterMapT>
141 void OopMapDo<OopFnT, DerivedOopFnT, ValueFilterT>::oops_do(const frame *fr, const RegisterMapT *reg_map, const ImmutableOopMap* oopmap) {
142   iterate_oops_do(fr, reg_map, oopmap);
143 }
144 
145 #endif
146