Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/optimizer/J9Inliner.hpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 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 INLINERTEMPFORJ9_INCL
24
#define INLINERTEMPFORJ9_INCL
25
26
#include "j9cfg.h"
27
#include "ras/LogTracer.hpp"
28
#include "runtime/J9ValueProfiler.hpp"
29
30
class OMR_InlinerPolicy;
31
class OMR_InlinerUtil;
32
class TR_InlinerBase;
33
class TR_J9InnerPreexistenceInfo;
34
35
36
/**
37
* Class TR_MultipleCallTargetInliner
38
* ==================================
39
*
40
* Exception Directed Optimization (EDO) enables more aggressive
41
* inlining that the JIT does in cases when the call graph of the
42
* callee being inlined has some throw statements that would get
43
* caught in a catch block of the caller.
44
*
45
* The end goal is to give the JIT optimizer (value propagation in
46
* particular) the opportunity to convert a throw statement into a goto
47
* statement in cases when it can be proven at compile time that the throw
48
* would be caught by a specific catch block in the same compiled method.
49
*
50
* The advantage of this optimization is being able to avoid the throw/catch
51
* flow of control that typically is implemented by some form of stack
52
* walking in the JVM; stack walking can be quite an expensive operation
53
* especially when compared with other simpler ways of transferring
54
* flow of control, like a goto for example.
55
*
56
* Value propagation propagates type information as part of the analysis
57
* and this means that it can determine if the exception thrown can in fact
58
* be caught by a particular catch block or not based on the type of the
59
* exception and the types that the catch block handles according to the
60
* exception table information in the bytecodes.
61
*
62
* EDO depends on profiling throw statements and catch blocks, and
63
* determining those operations that are frequently executed and then
64
* attempting to bring the frequently executed throw and catch together
65
* into the same compilation unit (method) by inlining aggressively.
66
*/
67
68
class TR_MultipleCallTargetInliner : public TR_InlinerBase
69
{
70
public:
71
72
template <typename FunctObj>
73
void recursivelyWalkCallTargetAndPerformAction(TR_CallTarget *ct, FunctObj &action);
74
75
//void generateNodeEstimate(TR_CallTarget *ct, TR::Compilation *comp);
76
77
class generateNodeEstimate
78
{
79
public:
80
generateNodeEstimate() : _nodeEstimate(0){ }
81
void operator()(TR_CallTarget *ct, TR::Compilation *comp);
82
int32_t getNodeEstimate() { return _nodeEstimate; }
83
private:
84
int32_t _nodeEstimate;
85
};
86
87
TR_MultipleCallTargetInliner(TR::Optimizer *, TR::Optimization *);
88
89
virtual bool inlineCallTargets(TR::ResolvedMethodSymbol *, TR_CallStack *, TR_InnerPreexistenceInfo *);
90
virtual bool exceedsSizeThreshold(TR_CallSite *callSite, int bytecodeSize, TR::Block * callNodeBlock, TR_ByteCodeInfo & bcInfo, int32_t numLocals=0, TR_ResolvedMethod * caller = 0, TR_ResolvedMethod * calleeResolvedMethod = 0, TR::Node * callNode = 0, bool allConsts = false);
91
92
TR_LinkHead<TR_CallTarget> _callTargets; // This list only contains the call targets from top most level
93
94
protected:
95
virtual int32_t scaleSizeBasedOnBlockFrequency(int32_t bytecodeSize, int32_t frequency, int32_t borderFrequency, TR_ResolvedMethod * calleeResolvedMethod, TR::Node *callNode, int32_t coldBorderFrequency = 0);
96
float getScalingFactor(float factor);
97
virtual bool supportsMultipleTargetInlining () { return true ; }
98
99
void walkCallSites(TR::ResolvedMethodSymbol *, TR_CallStack *, TR_InnerPreexistenceInfo *, int32_t walkDepth);
100
void walkCallSite( TR::ResolvedMethodSymbol * calleeSymbol, TR_CallStack * callStack,
101
TR::TreeTop * callNodeTreeTop, TR::Node * parent, TR::Node * callNode, TR_VirtualGuardSelection *guard,
102
TR_OpaqueClassBlock * thisClass, bool inlineNonRecursively, int32_t walkDepth);
103
private:
104
bool analyzeCallSite(TR::ResolvedMethodSymbol *, TR_CallStack *, TR::TreeTop *, TR::Node *, TR::Node *);
105
void weighCallSite( TR_CallStack * callStack , TR_CallSite *callsite, bool currentBlockHasExceptionSuccessors,bool dontAddCalls=false);
106
107
int32_t applyArgumentHeuristics(TR_LinkHead<TR_ParameterMapping> &map, int32_t originalWeight, TR_CallTarget *target);
108
bool eliminateTailRecursion(TR::ResolvedMethodSymbol *, TR_CallStack *, TR::TreeTop *, TR::Node *, TR::Node *, TR_VirtualGuardSelection *);
109
void assignArgumentsToParameters(TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *);
110
bool isLargeCompiledMethod(TR_ResolvedMethod *calleeResolvedMethod, int32_t bytecodeSize, int32_t freq);
111
/* \brief
112
* This API processes the call targets got chopped off from \ref _calltargets
113
*
114
* \parm firstChoppedOffcalltarget
115
* the start of the targets that should be chopped off from \ref _callTargets
116
*
117
* \parm lastTargetToInline
118
* the tail of _callTargets
119
*
120
* \notes
121
* Call targets are chopped off from \ref _callTargets list because of global budget limit like node counts and total weight.
122
* This function chooses to keep some chopped of targets if they meet certain conditions.
123
*/
124
void processChoppedOffCallTargets(TR_CallTarget* lastTargetToInline, TR_CallTarget *firstChoppedOffcalltarget, int estimateAndRefineBytecodeSize);
125
126
/*
127
* \brief
128
* Recursively walk through the sub call graph of a given calltarget and clean up all targets
129
* from their respective callsites if chopped of from _callTargets
130
*
131
* \return
132
* True if the given calltarget should be inlined
133
*/
134
bool inlineSubCallGraph(TR_CallTarget* calltarget);
135
};
136
137
class TR_J9InlinerUtil: public OMR_InlinerUtil
138
{
139
friend class TR_InlinerBase;
140
friend class TR_MultipleCallTargetInliner;
141
public:
142
TR_J9InlinerUtil(TR::Compilation *comp);
143
virtual void adjustByteCodeSize(TR_ResolvedMethod *calleeResolvedMethod, bool isInLoop, TR::Block *block, int &bytecodeSize);
144
virtual void adjustCallerWeightLimit(TR::ResolvedMethodSymbol *callSymbol, int &callerWeightLimit);
145
virtual void adjustMethodByteCodeSizeThreshold(TR::ResolvedMethodSymbol *callSymbol, int &methodByteCodeSizeThreshold);
146
virtual bool addTargetIfMethodIsNotOverridenInReceiversHierarchy(TR_IndirectCallSite *callsite);
147
virtual bool addTargetIfThereIsSingleImplementer (TR_IndirectCallSite *callsite);
148
virtual TR_ResolvedMethod *findSingleJittedImplementer(TR_IndirectCallSite *callsite);
149
virtual TR_PrexArgInfo* createPrexArgInfoForCallTarget(TR_VirtualGuardSelection *guard, TR_ResolvedMethod *implementer);
150
virtual TR_InlinerTracer * getInlinerTracer(TR::Optimization *optimization);
151
virtual TR_PrexArgInfo *computePrexInfo(TR_CallTarget *target);
152
virtual TR_PrexArgInfo *computePrexInfo(TR_CallTarget *target, TR_PrexArgInfo *callerArgInfo);
153
static TR_PrexArgInfo *computePrexInfo(TR_InlinerBase *inliner, TR_CallSite *site, TR_PrexArgInfo *callerArgInfo = NULL);
154
virtual void refineInlineGuard(TR::Node *callNode, TR::Block *&block1, TR::Block *&block2,
155
bool &appendTestToBlock1, TR::ResolvedMethodSymbol * callerSymbol, TR::TreeTop *cursorTree,
156
TR::TreeTop *&virtualGuard, TR::Block *block4);
157
virtual void refineInliningThresholds(TR::Compilation *comp, int32_t &callerWeightLimit, int32_t &maxRecursiveCallByteCodeSizeEstimate, int32_t &methodByteCodeSizeThreshold, int32_t &methodInWarmBlockByteCodeSizeThreshold, int32_t &methodInColdBlockByteCodeSizeThreshold, int32_t &nodeCountThreshold, int32_t size);
158
static void checkForConstClass(TR_CallTarget *target, TR_LogTracer *tracer);
159
virtual bool needTargetedInlining(TR::ResolvedMethodSymbol *callee);
160
virtual void requestAdditionalOptimizations(TR_CallTarget *calltarget);
161
protected:
162
virtual void refineColdness (TR::Node* node, bool& isCold);
163
virtual void computeMethodBranchProfileInfo (TR::Block * cfgBlock, TR_CallTarget* calltarget, TR::ResolvedMethodSymbol* callerSymbol);
164
virtual int32_t getCallCount(TR::Node *callNode);
165
virtual TR_InnerPreexistenceInfo *createInnerPrexInfo(TR::Compilation * c, TR::ResolvedMethodSymbol *methodSymbol, TR_CallStack *callStack, TR::TreeTop *callTree, TR::Node *callNode, TR_VirtualGuardKind guardKind);
166
virtual void estimateAndRefineBytecodeSize(TR_CallSite* callsite, TR_CallTarget* target, TR_CallStack *callStack, int32_t &bytecodeSize);
167
virtual TR_TransformInlinedFunction *getTransformInlinedFunction(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::Block *, TR::TreeTop *,
168
TR::Node *, TR_ParameterToArgumentMapper &, TR_VirtualGuardSelection *, List<TR::SymbolReference> &,
169
List<TR::SymbolReference> &, List<TR::SymbolReference> &);
170
};
171
172
class TR_J9InlinerPolicy : public OMR_InlinerPolicy
173
{
174
friend class TR_J9InlinerUtil;
175
friend class TR_InlinerBase;
176
friend class TR_MultipleCallTargetInliner;
177
public:
178
TR_J9InlinerPolicy(TR::Compilation *comp);
179
virtual bool inlineRecognizedMethod(TR::RecognizedMethod method);
180
virtual bool tryToInlineTrivialMethod (TR_CallStack* callStack, TR_CallTarget* calltarget);
181
bool isInlineableJNI(TR_ResolvedMethod *method,TR::Node *callNode);
182
virtual bool alwaysWorthInlining(TR_ResolvedMethod * calleeMethod, TR::Node *callNode);
183
bool adjustFanInSizeInExceedsSizeThreshold(int bytecodeSize,
184
uint32_t& calculatedSize,
185
TR_ResolvedMethod* callee,
186
TR_ResolvedMethod* caller,
187
int32_t bcIndex);
188
void adjustFanInSizeInWeighCallSite(int32_t& weight,
189
int32_t size,
190
TR_ResolvedMethod* callee,
191
TR_ResolvedMethod* caller,
192
int32_t bcIndex);
193
virtual bool aggressivelyInlineInLoops();
194
virtual void determineInliningHeuristic(TR::ResolvedMethodSymbol *callerSymbol);
195
virtual void determineAggressionInLoops(TR::ResolvedMethodSymbol *callerSymbol);
196
virtual int32_t getInitialBytecodeSize(TR_ResolvedMethod *feMethod, TR::ResolvedMethodSymbol * methodSymbol, TR::Compilation *comp);
197
virtual bool tryToInline(TR_CallTarget *, TR_CallStack *, bool);
198
virtual bool inlineMethodEvenForColdBlocks(TR_ResolvedMethod *method);
199
virtual bool willBeInlinedInCodeGen(TR::RecognizedMethod method);
200
virtual bool canInlineMethodWhileInstrumenting(TR_ResolvedMethod *method);
201
virtual bool shouldRemoveDifferingTargets(TR::Node *callNode);
202
virtual bool skipHCRGuardForCallee(TR_ResolvedMethod* callee);
203
virtual bool dontPrivatizeArgumentsForRecognizedMethod(TR::RecognizedMethod recognizedMethod);
204
virtual bool replaceSoftwareCheckWithHardwareCheck(TR_ResolvedMethod *calleeMethod);
205
virtual bool suitableForRemat(TR::Compilation *comp, TR::Node *callNode, TR_VirtualGuardSelection *guard);
206
207
#ifdef J9VM_OPT_JAVA_CRYPTO_ACCELERATION
208
virtual bool willInlineCryptoMethodInCodeGen(TR::RecognizedMethod method);
209
#endif
210
211
protected:
212
bool _aggressivelyInlineInLoops;
213
void createTempsForUnsafeCall( TR::TreeTop *callNodeTreeTop, TR::Node * unsafeCallNode );
214
TR::Node * inlineGetClassAccessFlags(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *);
215
bool inlineUnsafeCall(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *);
216
TR::Block * addNullCheckForUnsafeGetPut(TR::Node* unsafeAddress, TR::SymbolReference* newSymbolReferenceForAddress, TR::TreeTop* callNodeTreeTop, TR::TreeTop* directAccessTreeTop, TR::TreeTop* arrayDirectAccessTreeTop, TR::TreeTop* indirectAccessTreeTop);
217
bool createUnsafePutWithOffset(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool, bool needNullCheck = false, bool isOrdered = false);
218
TR::TreeTop* genDirectAccessCodeForUnsafeGetPut(TR::Node* callNode, bool conversionNeeded, bool isUnsafeGet);
219
void createTempsForUnsafePutGet(TR::Node*& unsafeAddress, TR::Node* unsafeCall, TR::TreeTop* callNodeTreeTop, TR::Node*& offset, TR::SymbolReference*& newSymbolReferenceForAddress, bool isUnsafeGet);
220
bool createUnsafeGet(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool compress = true);
221
bool createUnsafePut(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool compress = true);
222
TR::Node * createUnsafeAddress(TR::Node *);
223
bool createUnsafeGetWithOffset(TR::ResolvedMethodSymbol *, TR::ResolvedMethodSymbol *, TR::TreeTop *, TR::Node *, TR::DataType, bool, bool needNullCheck = false);
224
TR::Node * createUnsafeAddressWithOffset(TR::Node *);
225
bool createUnsafeFence(TR::TreeTop *, TR::Node *, TR::ILOpCodes);
226
227
TR::Node * createUnsafeMonitorOp(TR::ResolvedMethodSymbol *calleeSymbol, TR::ResolvedMethodSymbol *callerSymbol, TR::TreeTop * callNodeTreeTop, TR::Node * unsafeCall, bool isEnter);
228
bool createUnsafeCASCallDiamond(TR::TreeTop *, TR::Node *);
229
TR::TreeTop* genClassCheckForUnsafeGetPut(TR::Node* offset);
230
TR::TreeTop* genClassCheckForUnsafeGetPut(TR::Node* offset, bool isNotLowTagged);
231
232
/** \brief
233
* Generates the indirect access for an unsafe get/put operation given a direct access. This function will
234
* replicate the entire direct access tree passed in (see \p directAccessOrTempStoreNode) and update the
235
* symbol reference of the unsafe get/put operation to represent an indirect access.
236
*
237
* \param directAccessOrTempStoreNode
238
* The direct access of the unsafe operation or a temp store of the direct access.
239
*
240
* \param unsafeAddress
241
* The unsafe address to access.
242
*
243
* \return
244
* The tree top representing the indirect access along with the potential temp store in case of a get
245
* operation.
246
*/
247
TR::TreeTop* genIndirectAccessCodeForUnsafeGetPut(TR::Node* directAccessOrTempStoreNode, TR::Node* unsafeAddress);
248
249
void createAnchorNodesForUnsafeGetPut(TR::TreeTop* treeTop, TR::DataType type, bool isUnsafeGet);
250
TR::Node * genCompressedRefs(TR::Node *, bool genTT = true, int32_t isLoad = 1);
251
void genCodeForUnsafeGetPut(TR::Node* unsafeAddress, TR::TreeTop* callNodeTreeTop, TR::TreeTop* prevTreeTop, TR::SymbolReference* newSymbolReferenceForAddress, TR::TreeTop* directAccessTreeTop, TR::TreeTop* lowTagCmpTree, bool needNullCheck, bool isUnsafeGet, bool conversionNeeded, TR::Block * joinBlock, TR_OpaqueClassBlock *javaLangClass, TR::Node* orderedCallNode);
252
virtual bool callMustBeInlined(TR_CallTarget *calltarget);
253
bool mustBeInlinedEvenInDebug(TR_ResolvedMethod * calleeMethod, TR::TreeTop *callNodeTreeTop);
254
bool _tryToGenerateILForMethod (TR::ResolvedMethodSymbol* calleeSymbol, TR::ResolvedMethodSymbol* callerSymbol, TR_CallTarget* calltarget);
255
bool doCorrectnessAndSizeChecksForInlineCallTarget(TR_CallStack *callStack, TR_CallTarget *calltarget, bool inlinefromgraph, TR_PrexArgInfo *argInfo);
256
bool validateArguments(TR_CallTarget *calltarget, TR_LinkHead<TR_ParameterMapping> &map);
257
virtual bool supressInliningRecognizedInitialCallee(TR_CallSite* callsite, TR::Compilation* comp);
258
virtual TR_InlinerFailureReason checkIfTargetInlineable(TR_CallTarget* target, TR_CallSite* callsite, TR::Compilation* comp);
259
/** \brief
260
* This query decides whether the given method is JSR292 related
261
*/
262
static bool isJSR292Method(TR_ResolvedMethod *resolvedMethod);
263
/** \brief
264
* This query decides whether the given JSR292 callee is worthing inlining
265
*
266
* \notes
267
* The methods are in 3 kinds: 1. VarHandle operation methods 2. small getters 3. method handle thunk
268
*/
269
static bool isJSR292AlwaysWorthInlining(TR_ResolvedMethod *resolvedMethod);
270
/** \brief
271
* This query defines a group of methods that are small getters in the java/lang/invoke package
272
*/
273
static bool isJSR292SmallGetterMethod(TR_ResolvedMethod *resolvedMethod);
274
/** \brief
275
* This query defines a group of methods that are small helpers in the java/lang/invoke package
276
*/
277
static bool isJSR292SmallHelperMethod(TR_ResolvedMethod *resolvedMethod);
278
};
279
280
class TR_J9JSR292InlinerPolicy : public TR_J9InlinerPolicy
281
{
282
friend class TR_J9InlinerUtil;
283
friend class TR_InlinerBase;
284
friend class TR_MultipleCallTargetInliner;
285
public:
286
TR_J9JSR292InlinerPolicy(TR::Compilation *comp);
287
protected:
288
virtual TR_InlinerFailureReason checkIfTargetInlineable(TR_CallTarget* target, TR_CallSite* callsite, TR::Compilation* comp);
289
};
290
291
class TR_J9TransformInlinedFunction : public TR_TransformInlinedFunction
292
{
293
public:
294
TR_J9TransformInlinedFunction(
295
TR::Compilation *c, TR_InlinerTracer *tracer,TR::ResolvedMethodSymbol * callerSymbol, TR::ResolvedMethodSymbol * calleeSymbol,
296
TR::Block * callNodeBlock, TR::TreeTop * callNodeTreeTop, TR::Node * callNode,
297
TR_ParameterToArgumentMapper & mapper, TR_VirtualGuardSelection *guard,
298
List<TR::SymbolReference> & temps, List<TR::SymbolReference> & availableTemps,
299
List<TR::SymbolReference> & availableTemps2);
300
virtual void transform();
301
private:
302
void transformSynchronizedMethod(TR_ResolvedMethod *);
303
TR::Block * appendCatchBlockForInlinedSyncMethod(TR_ResolvedMethod *, TR::TreeTop * , int32_t, int32_t, bool addBlocks = true);
304
bool isSyncReturnBlock(TR::Compilation *comp, TR::Block * b);
305
// { RTSJ Support begins
306
void wrapCalleeInTryRegion(bool, bool, TR_ResolvedMethod *);
307
TR::TreeTop * createThrowCatchBlock(bool, bool, TR::CFG *, TR::Block *, TR::TreeTop *, TR::SymbolReference *, int32_t, TR_ScratchList<TR::Block> & newCatchBlocks);
308
TR::Block * appendCatchBlockToRethrowException(TR_ResolvedMethod *, TR::TreeTop *, bool, int32_t, int32_t, bool addBlocks = true);
309
// } RTSJ Support ends
310
};
311
312
class TR_J9InnerPreexistenceInfo : public TR_InnerPreexistenceInfo
313
{
314
public:
315
TR_J9InnerPreexistenceInfo(TR::Compilation * c, TR::ResolvedMethodSymbol *methodSymbol, TR_CallStack *callStack,
316
TR::TreeTop *callTree, TR::Node *callNode,
317
TR_VirtualGuardKind _guardKind);
318
virtual bool perform(TR::Compilation *comp, TR::Node *guardNode, bool & disableTailRecursion);
319
class ParmInfo
320
{
321
public:
322
TR_ALLOC(TR_Memory::Inliner);
323
ParmInfo(TR::ParameterSymbol *innerParm, TR::ParameterSymbol *outerParm = 0);
324
325
void setOuterSymbol(TR::ParameterSymbol *outerParm) { _outerParm = outerParm; }
326
void setNotInvariant() { _isInvariant = false; }
327
bool isInvariant() { return _isInvariant; }
328
329
TR::ParameterSymbol *_outerParm; // may be null
330
TR::ParameterSymbol *_innerParm; // never null
331
bool _isInvariant;
332
};
333
334
struct PreexistencePoint
335
{
336
TR_ALLOC(TR_Memory::Inliner);
337
PreexistencePoint(TR_CallStack *callStack, int32_t ordinal) :
338
_callStack(callStack), _ordinal(ordinal) {}
339
340
TR_CallStack *_callStack;
341
int32_t _ordinal;
342
};
343
344
ParmInfo *getParmInfo(int32_t ordinal) { return _parameters[ordinal]; }
345
PreexistencePoint *getPreexistencePoint(int32_t ordinal);
346
void addInnerAssumption(TR_InnerAssumption *a) { _assumptions.add(a); }
347
List<TR_InnerAssumption> &getInnerAssumptions() { return _assumptions; }
348
private:
349
PreexistencePoint *getPreexistencePointImpl(int32_t ordinal, TR_CallStack *prevCallStack);
350
ParmInfo **_parameters; // information about the address type parameters
351
};
352
353
class TR_J9InlinerTracer : public TR_InlinerTracer
354
{
355
public:
356
TR_J9InlinerTracer(TR::Compilation *comp, TR_FrontEnd *fe, TR::Optimization *opt);
357
void dumpProfiledClasses (ListIterator<TR_ExtraAddressInfo>& sortedValuesIt, uint32_t totalFrequency = 1);
358
};
359
#endif
360
361