1 |
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ |
2 |
/* ***** BEGIN LICENSE BLOCK ***** |
3 |
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
4 |
* |
5 |
* The contents of this file are subject to the Mozilla Public License Version |
6 |
* 1.1 (the "License"); you may not use this file except in compliance with |
7 |
* the License. You may obtain a copy of the License at |
8 |
* http://www.mozilla.org/MPL/ |
9 |
* |
10 |
* Software distributed under the License is distributed on an "AS IS" basis, |
11 |
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
12 |
* for the specific language governing rights and limitations under the |
13 |
* License. |
14 |
* |
15 |
* The Original Code is [Open Source Virtual Machine]. |
16 |
* |
17 |
* The Initial Developer of the Original Code is |
18 |
* Adobe System Incorporated. |
19 |
* Portions created by the Initial Developer are Copyright (C) 2004-2007 |
20 |
* the Initial Developer. All Rights Reserved. |
21 |
* |
22 |
* Contributor(s): |
23 |
* Adobe AS3 Team |
24 |
* Mozilla TraceMonkey Team |
25 |
* Asko Tontti <atontti@cc.hut.fi> |
26 |
* |
27 |
* Alternatively, the contents of this file may be used under the terms of |
28 |
* either the GNU General Public License Version 2 or later (the "GPL"), or |
29 |
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
30 |
* in which case the provisions of the GPL or the LGPL are applicable instead |
31 |
* of those above. If you wish to allow use of your version of this file only |
32 |
* under the terms of either the GPL or the LGPL, and not to allow others to |
33 |
* use your version of this file under the terms of the MPL, indicate your |
34 |
* decision by deleting the provisions above and replace them with the notice |
35 |
* and other provisions required by the GPL or the LGPL. If you do not delete |
36 |
* the provisions above, a recipient may use your version of this file under |
37 |
* the terms of any one of the MPL, the GPL or the LGPL. |
38 |
* |
39 |
* ***** END LICENSE BLOCK ***** */ |
40 |
|
41 |
|
42 |
#ifndef __nanojit_Fragmento__ |
43 |
#define __nanojit_Fragmento__ |
44 |
|
45 |
#ifdef AVMPLUS_VERBOSE |
46 |
extern void drawTraceTrees(Fragmento *frago, FragmentMap * _frags, avmplus::AvmCore *core, char *fileName); |
47 |
#endif |
48 |
|
49 |
namespace nanojit |
50 |
{ |
51 |
struct GuardRecord; |
52 |
class Assembler; |
53 |
|
54 |
struct PageHeader |
55 |
{ |
56 |
struct Page *next; |
57 |
}; |
58 |
struct Page: public PageHeader |
59 |
{ |
60 |
union { |
61 |
LIns lir[(NJ_PAGE_SIZE-sizeof(PageHeader))/sizeof(LIns)]; |
62 |
NIns code[(NJ_PAGE_SIZE-sizeof(PageHeader))/sizeof(NIns)]; |
63 |
}; |
64 |
}; |
65 |
struct AllocEntry : public avmplus::GCObject |
66 |
{ |
67 |
Page *page; |
68 |
uint32_t allocSize; |
69 |
}; |
70 |
typedef avmplus::List<AllocEntry*,avmplus::LIST_NonGCObjects> AllocList; |
71 |
|
72 |
typedef avmplus::GCSortedMap<const void*, uint32_t, avmplus::LIST_NonGCObjects> BlockSortedMap; |
73 |
class BlockHist: public BlockSortedMap |
74 |
{ |
75 |
public: |
76 |
BlockHist(avmplus::GC*gc) : BlockSortedMap(gc) |
77 |
{ |
78 |
} |
79 |
uint32_t count(const void *p) { |
80 |
uint32_t c = 1+get(p); |
81 |
put(p, c); |
82 |
return c; |
83 |
} |
84 |
}; |
85 |
|
86 |
struct fragstats; |
87 |
/* |
88 |
* |
89 |
* This is the main control center for creating and managing fragments. |
90 |
*/ |
91 |
class Fragmento : public avmplus::GCFinalizedObject |
92 |
{ |
93 |
public: |
94 |
Fragmento(AvmCore* core, uint32_t cacheSizeLog2); |
95 |
~Fragmento(); |
96 |
|
97 |
void addMemory(void* firstPage, uint32_t pageCount); // gives memory to the Assembler |
98 |
Assembler* assm(); |
99 |
AvmCore* core(); |
100 |
Page* pageAlloc(); |
101 |
void pageFree(Page* page); |
102 |
|
103 |
Fragment* getLoop(const void* ip); |
104 |
Fragment* getAnchor(const void* ip); |
105 |
// Remove one fragment. The caller is responsible for making sure |
106 |
// that this does not destroy any resources shared with other |
107 |
// fragments (such as a LirBuffer or this fragment itself as a |
108 |
// jump target). |
109 |
void clearFrag(const void* ip); |
110 |
void clearFrags(); // clear all fragments from the cache |
111 |
Fragment* getMerge(GuardRecord *lr, const void* ip); |
112 |
Fragment* createBranch(SideExit *exit, const void* ip); |
113 |
Fragment* newFrag(const void* ip); |
114 |
Fragment* newBranch(Fragment *from, const void* ip); |
115 |
void disconnectLoops(); |
116 |
void reconnectLoops(); |
117 |
|
118 |
verbose_only ( uint32_t pageCount(); ) |
119 |
verbose_only ( void dumpStats(); ) |
120 |
verbose_only ( void dumpRatio(const char*, BlockHist*);) |
121 |
verbose_only ( void dumpFragStats(Fragment*, int level, fragstats&); ) |
122 |
verbose_only ( void countBlock(BlockHist*, const void* pc); ) |
123 |
verbose_only ( void countIL(uint32_t il, uint32_t abc); ) |
124 |
verbose_only( void addLabel(Fragment* f, const char *prefix, int id); ) |
125 |
|
126 |
// stats |
127 |
struct |
128 |
{ |
129 |
uint32_t pages; // pages consumed |
130 |
uint32_t freePages; // how many pages not in use (<= pages) |
131 |
uint32_t maxPageUse; // highwater mark of (poges-freePages) |
132 |
uint32_t flushes, ilsize, abcsize, compiles, totalCompiles; |
133 |
} |
134 |
_stats; |
135 |
|
136 |
verbose_only( DWB(BlockHist*) enterCounts; ) |
137 |
verbose_only( DWB(BlockHist*) mergeCounts; ) |
138 |
verbose_only( DWB(LabelMap*) labels; ) |
139 |
|
140 |
#ifdef AVMPLUS_VERBOSE |
141 |
void drawTrees(char *fileName); |
142 |
#endif |
143 |
|
144 |
uint32_t cacheUsed() const { return (_stats.pages-_stats.freePages)<<NJ_LOG2_PAGE_SIZE; } |
145 |
uint32_t cacheUsedMax() const { return (_stats.maxPageUse)<<NJ_LOG2_PAGE_SIZE; } |
146 |
private: |
147 |
void clearFragment(Fragment *f); |
148 |
void pagesGrow(int32_t count); |
149 |
void trackFree(int32_t delta); |
150 |
|
151 |
AvmCore* _core; |
152 |
DWB(Assembler*) _assm; |
153 |
DWB(FragmentMap*) _frags; /* map from ip -> Fragment ptr */ |
154 |
Page* _pageList; |
155 |
|
156 |
/* unmanaged mem */ |
157 |
AllocList _allocList; |
158 |
avmplus::GCHeap* _gcHeap; |
159 |
|
160 |
const uint32_t _max_pages; |
161 |
uint32_t _pagesGrowth; |
162 |
}; |
163 |
|
164 |
enum TraceKind { |
165 |
LoopTrace, |
166 |
BranchTrace, |
167 |
MergeTrace |
168 |
}; |
169 |
|
170 |
/** |
171 |
* Fragments are linear sequences of native code that have a single entry |
172 |
* point at the start of the fragment and may have one or more exit points |
173 |
* |
174 |
* It may turn out that that this arrangement causes too much traffic |
175 |
* between d and i-caches and that we need to carve up the structure differently. |
176 |
*/ |
177 |
class Fragment : public avmplus::GCFinalizedObject |
178 |
{ |
179 |
public: |
180 |
Fragment(const void*); |
181 |
~Fragment(); |
182 |
|
183 |
NIns* code() { return _code; } |
184 |
void setCode(NIns* codee, Page* pages) { _code = codee; _pages = pages; } |
185 |
GuardRecord* links() { return _links; } |
186 |
int32_t& hits() { return _hits; } |
187 |
void resetHits(); |
188 |
void blacklist(); |
189 |
bool isBlacklisted() { return _hits < 0; } |
190 |
debug_only( bool hasOnlyTreeLinks(); ) |
191 |
void releaseLirBuffer(); |
192 |
void releaseCode(Fragmento* frago); |
193 |
void releaseTreeMem(Fragmento* frago); |
194 |
bool isAnchor() { return anchor == this; } |
195 |
bool isRoot() { return root == this; } |
196 |
void onDestroy(); |
197 |
|
198 |
verbose_only( uint32_t _called; ) |
199 |
verbose_only( uint32_t _native; ) |
200 |
verbose_only( uint32_t _exitNative; ) |
201 |
verbose_only( uint32_t _lir; ) |
202 |
verbose_only( uint32_t _lirbytes; ) |
203 |
verbose_only( const char* _token; ) |
204 |
verbose_only( uint64_t traceTicks; ) |
205 |
verbose_only( uint64_t interpTicks; ) |
206 |
verbose_only( DWB(Fragment*) eot_target; ) |
207 |
verbose_only( uint32_t sid;) |
208 |
verbose_only( uint32_t compileNbr;) |
209 |
|
210 |
DWB(Fragment*) treeBranches; |
211 |
DWB(Fragment*) branches; |
212 |
DWB(Fragment*) nextbranch; |
213 |
DWB(Fragment*) anchor; |
214 |
DWB(Fragment*) root; |
215 |
DWB(Fragment*) parent; |
216 |
DWB(Fragment*) first; |
217 |
DWB(Fragment*) peer; |
218 |
DWB(BlockHist*) mergeCounts; |
219 |
DWB(LirBuffer*) lirbuf; |
220 |
LIns* lastIns; |
221 |
SideExit* spawnedFrom; |
222 |
|
223 |
TraceKind kind; |
224 |
const void* ip; |
225 |
uint32_t guardCount; |
226 |
uint32_t xjumpCount; |
227 |
uint32_t recordAttempts; |
228 |
int32_t blacklistLevel; |
229 |
NIns* fragEntry; |
230 |
NIns* loopEntry; |
231 |
void* vmprivate; |
232 |
|
233 |
private: |
234 |
NIns* _code; // ptr to start of code |
235 |
GuardRecord* _links; // code which is linked (or pending to be) to this fragment |
236 |
int32_t _hits; |
237 |
Page* _pages; // native code pages |
238 |
}; |
239 |
} |
240 |
#endif // __nanojit_Fragmento__ |