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 */