-
Notifications
You must be signed in to change notification settings - Fork 747
/
Copy pathEstimateCodeSize.hpp
146 lines (117 loc) · 4.81 KB
/
EstimateCodeSize.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*******************************************************************************
* Copyright IBM Corp. and others 2000
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#ifndef ESTIMATECS_INCL
#define ESTIMATECS_INCL
#include <stddef.h>
#include <stdint.h>
#include "env/TRMemory.hpp"
#include "infra/Flags.hpp"
#include "optimizer/Inliner.hpp"
class TR_CallStack;
namespace TR { class Compilation; }
struct TR_CallSite;
struct TR_CallTarget;
#define MAX_ECS_RECURSION_DEPTH 30
enum EcsCleanupErrorStates {
ECS_NORMAL = 0,
ECS_RECURSION_DEPTH_THRESHOLD_EXCEEDED,
ECS_OPTIMISTIC_SIZE_THRESHOLD_EXCEEDED,
ECS_VISITED_COUNT_THRESHOLD_EXCEEDED,
ECS_REAL_SIZE_THRESHOLD_EXCEEDED,
ECS_ARGUMENTS_INCOMPATIBLE,
ECS_CALLSITES_CREATION_FAILED
};
class TR_EstimateCodeSize
{
public:
void * operator new (size_t size, TR::Allocator allocator) { return allocator.allocate(size); }
void operator delete (void *, TR::Allocator allocator) {}
// {
// TR_EstimateCodeSize::raiiWrapper lexicalScopeObject(....);
// TR_EstimateCodeSize *ecs = lexicalScopeObject->getCodeEstimator();
// ... do whatever you gotta do
// } // estimator will be automatically freed by lexicalScopeObject regardless of how scope is exited
class raiiWrapper
{
public:
raiiWrapper(TR_InlinerBase *inliner, TR_InlinerTracer *tracer, int32_t sizeThreshold)
{
_estimator = TR_EstimateCodeSize::get(inliner, tracer, sizeThreshold);
}
~raiiWrapper()
{
TR_EstimateCodeSize::release(_estimator);
}
TR_EstimateCodeSize *getCodeEstimator()
{
return _estimator;
}
private:
TR_EstimateCodeSize *_estimator;
};
TR_EstimateCodeSize() { }
static TR_EstimateCodeSize *get(TR_InlinerBase *inliner, TR_InlinerTracer *tracer, int32_t sizeThreshold);
static void release(TR_EstimateCodeSize *estimator);
bool calculateCodeSize(TR_CallTarget *, TR_CallStack *, bool recurseDown = true);
int32_t getSize() { return _realSize; }
virtual int32_t getOptimisticSize() { return 0; } // override in subclasses that support partial inlining
const char *getError();
int32_t getSizeThreshold() { return _sizeThreshold; }
bool aggressivelyInlineThrows() { return _aggressivelyInlineThrows; }
bool recursedTooDeep() { return _recursedTooDeep; }
bool isLeaf() { return _isLeaf; }
int32_t getNumOfEstimatedCalls() { return _numOfEstimatedCalls; }
/*
* \brief
* tell whether this callsite has inlineable target
*/
bool isInlineable(TR_CallStack *, TR_CallSite *callsite);
TR::Compilation *comp() { return _inliner->comp(); }
TR_InlinerTracer *tracer() { return _tracer; }
TR_InlinerBase* getInliner() { return _inliner; }
protected:
virtual bool estimateCodeSize(TR_CallTarget *, TR_CallStack * , bool recurseDown = true) = 0;
/*
* \brief common tasks requiring completion before returning from estimation
*
* \param errorState
* an unique state used to identify where estimate code size bailed out
*/
bool returnCleanup(EcsCleanupErrorStates errorState);
/* Fields */
bool _isLeaf;
bool _foundThrow;
bool _hasExceptionHandlers;
bool _mayHaveVirtualCallProfileInfo;
bool _aggressivelyInlineThrows;
int32_t _recursionDepth;
bool _recursedTooDeep;
int32_t _sizeThreshold;
int32_t _realSize; // size once we know if we're doing a partial inline or not
EcsCleanupErrorStates _error;
int32_t _totalBCSize; // Pure accumulation of the bytecode size. Used by HW-based inlining.
TR_InlinerBase * _inliner;
TR_InlinerTracer *_tracer;
int32_t _numOfEstimatedCalls;
bool _hasNonColdCalls;
};
#endif