Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/net/MessageBuffer.hpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2020, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#ifndef MESSAGE_BUFFER_H
24
#define MESSAGE_BUFFER_H
25
26
#include "env/jittypes.h"
27
#include "env/TRMemory.hpp"
28
#include "OMR/Bytes.hpp" // for alignNoCheck
29
#include "env/CompilerEnv.hpp"
30
31
namespace JITServer
32
{
33
/**
34
@class MessageBuffer
35
@brief A wrapper around a contiguous, persistent memory allocated buffer
36
for storing a JITServer message.
37
38
The buffer is extensible, i.e. when the current capacity is reached, a new,
39
larger buffer can be allocated and data copied there.
40
Since reallocation causes addresses of values inside the buffer to change, read/write operations
41
return an offset into the buffer to indicate the location of data, instead of pointers.
42
43
Method getValueAtOffset returns a pointer to data at a given offset, but be mindful that
44
the pointer might become invalid if more data is added to the buffer.
45
46
Variable _curPtr defines the boundary of the current data. Reading/writing to/from buffer
47
will always advance the pointer.
48
*/
49
class MessageBuffer
50
{
51
public:
52
MessageBuffer();
53
54
~MessageBuffer()
55
{
56
freeMemory(_storage);
57
}
58
59
60
/**
61
@brief Get the current active size of the buffer.
62
63
Note: this returns the number of bytes written to the buffer so far,
64
NOT the overall capacity of the buffer. Capacity is the number of
65
bytes allocated, but not necessarily used.
66
67
@return the size of the buffer
68
*/
69
uint32_t size() const { return _curPtr - _storage; }
70
71
char *getBufferStart() const { return _storage; }
72
73
/**
74
@brief Return a pointer to the value at given offset inside the buffer.
75
76
Given a type and offset, returns the pointer of that type.
77
Behavior is only defined if offset does not exceed populated buffer size.
78
79
@return ponter of the specified type at given offset
80
*/
81
template <typename T>
82
T *getValueAtOffset(uint32_t offset) const
83
{
84
TR_ASSERT_FATAL(offset < size(), "Offset is outside of buffer bounds");
85
return reinterpret_cast<T *>(_storage + offset);
86
}
87
88
/**
89
@brief Write value of type T to the buffer.
90
91
Copies the value into buffer, expanding it if needed,
92
and advances _curPtr by sizeof(T) bytes plus some padding
93
so that the data inside the buffer is always 32-bit aligned
94
Behavior is undefined if T is not trivially copyable (i.e. not contiguous in memory).
95
96
@param val value to be written
97
98
@return offset to the beginning of written value inside the buffer
99
*/
100
template <typename T>
101
uint32_t writeValue(const T &val)
102
{
103
static_assert(std::is_trivially_copyable<T>::value == true, "T must be trivially copyable.");
104
uint8_t paddingSize = static_cast<uint8_t>(OMR::alignNoCheck(sizeof(T), sizeof(uint32_t)) - sizeof(T));
105
return writeData(&val, sizeof(T), paddingSize);
106
}
107
108
/**
109
@brief Write a given number of bytes into the buffer.
110
111
Copies dataSize bytes from dataStart into the buffer, expanding it if needed,
112
and advances _curPtr by (dataSize + paddingSize) bytes.
113
114
@param dataStart pointer to the beginning of the data to be written
115
@param dataSize number of bytes of real data to be written
116
@param paddingSize number of bytes of padding
117
118
@return offset to the beginning of written data inside the buffer
119
*/
120
uint32_t writeData(const void *dataStart, uint32_t dataSize, uint8_t paddingSize);
121
122
/**
123
@brief Reserve memory for a value of type T.
124
125
Advances _curPtr by sizeof(T) bytes, expanding the
126
buffer if needed.
127
Behavior is undefined if T is not trivially copyable (i.e. not contiguous in memory).
128
129
@return offset to the beginning of the reserved memory block
130
*/
131
template <typename T>
132
uint32_t reserveValue()
133
{
134
expandIfNeeded(size() + sizeof(T));
135
char *valStart = _curPtr;
136
_curPtr += sizeof(T);
137
return offset(valStart);
138
}
139
140
/**
141
@brief Read next value of type T from the buffer.
142
143
Assumes that the next unread value in the buffer is of type T.
144
Advances _curPtr by sizeof(T) bytes.
145
146
@return offset to the beginning of value
147
*/
148
template <typename T>
149
uint32_t readValue()
150
{
151
return readData(sizeof(T));
152
}
153
154
/**
155
@brief "Read" next dataSize bytes from the buffer.
156
157
Assumes that the buffer contains at least dataSize unread bytes.
158
Advances _curPtr by dataSize bytes ( this is considered a "read")
159
160
@return offset to the beginning of data
161
*/
162
uint32_t readData(uint32_t dataSize)
163
{
164
char* data = _curPtr;
165
_curPtr += dataSize; // Advance cursor
166
return offset(data); // Return offset before the advance
167
}
168
169
void clear() { _curPtr = _storage; }
170
171
/**
172
@brief Check to see if the current pointer in the MessageBuffer is 64-bit aligned.
173
*/
174
bool is64BitAligned() { return ((uintptr_t)_curPtr & ((uintptr_t)0x7)) == 0; }
175
176
/**
177
@brief Moves the current pointer in the MessageBuffer to achieve 64-bit alignment
178
179
@return returns the number of padding bytes required for alignment (0-7)
180
*/
181
uint8_t alignCurrentPositionOn64Bit();
182
183
/**
184
@brief Expand the underlying buffer if more than allocated memory is needed.
185
186
@param requiredSize the number of bytes the buffer needs to fit.
187
*/
188
void expandIfNeeded(uint32_t requiredSize);
189
190
/**
191
@brief Expand the underlying buffer to fit requiredSize and copy numBytesToCopy
192
from the old buffer to the new buffer when requiredSize is greater than
193
the capacity, and free the old buffer.
194
195
If requiredSize is greater than _capacity, allocates a new buffer that can fit requiredSize
196
bytes rounded up to the nearest power of 2,
197
copies all existing data based on _curPtr location to the new buffer,
198
and frees the old buffer.
199
200
@param requiredSize the number of bytes the buffer needs to fit.
201
@param numBytesToCopy the number of bytes that need to be copied over from the old buffer
202
*/
203
void expand(uint32_t requiredSize, uint32_t numBytesToCopy);
204
205
uint32_t getCapacity() const { return _capacity; }
206
207
208
private:
209
static const size_t INITIAL_BUFFER_SIZE = 32768; // Initial buffer size is 32K
210
uint32_t offset(char *addr) const { return addr - _storage; }
211
char *allocateMemory(uint32_t capacity) { return static_cast<char *>(_allocator.allocate(capacity)); }
212
void freeMemory(char *storage) { _allocator.deallocate(storage); }
213
uint32_t computeRequiredCapacity(uint32_t requiredSize);
214
215
uint32_t _capacity;
216
char *_storage;
217
char *_curPtr;
218
TR::PersistentAllocator &_allocator;
219
};
220
};
221
#endif
222
223