1 /*
   2  * Copyright (c) 2016, 2016, 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_MEMORY_VTBUFFER_HPP
  26 #define SHARE_VM_MEMORY_VTBUFFER_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "runtime/globals.hpp"
  30 #include "runtime/os.hpp"
  31 #include "utilities/globalDefinitions.hpp"
  32 
  33 class VTBufferChunk : public CMmapObj<VTBufferChunk, mtValueTypes> {
  34   friend class VMStructs;
  35 
  36   static const int MAGIC_NUMBER = 3141592;
  37 
  38 private:
  39   int            _magic;
  40   int            _index;
  41   VTBufferChunk* _prev;
  42   VTBufferChunk* _next;
  43   JavaThread*    _owner;
  44  public:
  45 
  46   VTBufferChunk(JavaThread* thread) {
  47     _magic = MAGIC_NUMBER;
  48     _index = -1;
  49     _prev = NULL;
  50     _next = NULL;
  51     _owner = thread;
  52   }
  53 
  54   int            index() { return _index; }
  55   void           set_index(int index) { _index = index; }
  56   VTBufferChunk* prev() { return _prev; }
  57   void           set_prev(VTBufferChunk* prev) { _prev = prev; }
  58   VTBufferChunk* next() { return _next; }
  59   void           set_next(VTBufferChunk* next) { _next = next; }
  60   JavaThread*    owner() { return _owner; }
  61   void           set_owner(JavaThread* thread) {
  62     assert(thread == NULL || _owner == NULL || _owner == thread, "Sanity check");
  63     _owner = thread;
  64   }
  65 
  66   bool is_valid() {
  67     return _magic == MAGIC_NUMBER && _owner != NULL && _index != -1;
  68   }
  69 
  70   void* first_alloc() { return (void*)((char*)this + align_object_size(sizeof (VTBufferChunk))); }
  71   void* alloc_limit() { return (void*)((char*)this + chunk_size() - 1); }
  72 
  73   static int chunk_size() {
  74     return os::vm_page_size();
  75   }
  76 
  77   static uintptr_t chunk_mask() {
  78     return ~(chunk_size() - 1);
  79   }
  80 
  81   static ByteSize index_offset() { return byte_offset_of(VTBufferChunk, _index); }
  82 
  83   static size_t max_alloc_size() {
  84     return chunk_size() - align_object_size(sizeof (VTBufferChunk));
  85   }
  86 
  87   static VTBufferChunk* chunk(void* address) {
  88     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)address & chunk_mask());
  89     assert(c->is_valid(), "Sanity check");
  90     return c;
  91   }
  92 
  93   static bool check_buffered(void* address) {
  94     assert(address != NULL, "Sanity check");
  95     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)address & chunk_mask());
  96     return c->is_valid();
  97   }
  98 
  99   bool contains(void* address) {
 100     return address > (char*)chunk(address) && address < ((char*)chunk(address) + chunk_size());
 101   }
 102 };
 103 
 104 class VTBuffer : AllStatic {
 105   friend class VMStructs;
 106 private:
 107   static VTBufferChunk* _free_list;
 108   static Mutex* _pool_lock;
 109   static int _pool_counter;
 110   static int _max_pool_counter;
 111   static int _total_allocated;
 112   static int _total_deallocated;
 113   static const int _max_free_list = 64;  // Should be tunable
 114 
 115 public:
 116   static Mutex* lock() { return _pool_lock; }
 117   static oop allocate_value(ValueKlass* k, TRAPS);
 118   static bool allocate_vt_chunk(JavaThread* thread);
 119   static void recycle_chunk(JavaThread* thread, VTBufferChunk* chunk);
 120   static void return_vt_chunk(JavaThread* thread, VTBufferChunk* chunk);
 121 
 122   static int in_pool() { return _pool_counter; }
 123   static int max_in_pool() { return _max_pool_counter; }
 124   static int total_allocated() { return _total_allocated; }
 125   static int total_deallocated() { return _total_deallocated; }
 126 
 127   static bool is_in_vt_buffer(const void* p) {
 128     intptr_t chunk_mask = (~(VTBufferChunk::chunk_size() - 1));
 129     VTBufferChunk* c = (VTBufferChunk*)((intptr_t)p & chunk_mask);
 130     return c->is_valid();
 131   }
 132 
 133   static bool value_belongs_to_frame(oop p, frame *f);
 134   static void recycle_vt_in_frame(JavaThread* thread, frame* f);
 135   static void recycle_vtbuffer(JavaThread *thread, frame f);
 136   static address relocate_value(address old, address previous, int previous_size_in_words);
 137   static oop relocate_return_value(JavaThread* thread, frame fr, oop old);
 138 
 139   static void fix_frame_vt_alloc_ptr(frame fr, VTBufferChunk* chunk);
 140 
 141 };
 142 
 143 struct VT_relocation_entry {
 144   int chunk_index;
 145   address old_ptr;
 146   address new_ptr;
 147 };
 148 
 149 
 150 class BufferedValuesMarking : public BufferedValueClosure {
 151   frame* _frame;
 152   struct VT_relocation_entry* _reloc_table;
 153   int _size;
 154   int* _index;
 155 public:
 156   BufferedValuesMarking(frame* frame, struct VT_relocation_entry* reloc_table, int size, int* index) {
 157     _frame = frame;
 158     _reloc_table = reloc_table;
 159     _size = size;
 160     _index = index;
 161   }
 162   virtual void do_buffered_value(oop* p);
 163 };
 164 
 165 class BufferedValuesPointersUpdate : public BufferedValueClosure {
 166   frame* _frame;
 167 public:
 168   BufferedValuesPointersUpdate(frame* frame) {
 169     _frame = frame;
 170   }
 171   virtual void do_buffered_value(oop* p);
 172 };
 173 
 174 #endif /* SHARE_VM_MEMORY_VTBUFFER_HPP */