2008-06-30 15:33:41 -07:00
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
2008-06-19 10:47:58 -07:00
/* ***** BEGIN LICENSE BLOCK *****
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is [ Open Source Virtual Machine ] .
*
* The Initial Developer of the Original Code is
* Adobe System Incorporated .
* Portions created by the Initial Developer are Copyright ( C ) 2004 - 2007
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
* Adobe AS3 Team
2008-09-02 10:15:26 -07:00
* Mozilla TraceMonkey Team
* Asko Tontti < atontti @ cc . hut . fi >
2008-06-19 10:47:58 -07:00
*
* Alternatively , the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later ( the " GPL " ) , or
* the GNU Lesser General Public License Version 2.1 or later ( the " LGPL " ) ,
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above . If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL , and not to allow others to
* use your version of this file under the terms of the MPL , indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL . If you do not delete
* the provisions above , a recipient may use your version of this file under
* the terms of any one of the MPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * */
# include "nanojit.h"
2008-10-13 13:29:18 -07:00
# undef MEMORY_INFO
2008-06-19 10:47:58 -07:00
namespace nanojit
{
# ifdef FEATURE_NANOJIT
using namespace avmplus ;
2008-07-15 13:06:05 -07:00
static uint32_t calcSaneCacheSize ( uint32_t in )
{
if ( in < uint32_t ( NJ_LOG2_PAGE_SIZE ) ) return NJ_LOG2_PAGE_SIZE ; // at least 1 page
if ( in > 30 ) return 30 ; // 1GB should be enough for anyone
return in ;
}
2008-06-19 10:47:58 -07:00
/**
* This is the main control center for creating and managing fragments .
*/
2008-07-15 13:06:05 -07:00
Fragmento : : Fragmento ( AvmCore * core , uint32_t cacheSizeLog2 )
2008-12-08 15:23:41 -08:00
: _frags ( core - > GetGC ( ) ) ,
2008-11-14 12:46:35 -08:00
_freePages ( core - > GetGC ( ) , 1024 ) ,
2008-12-08 15:23:41 -08:00
_allocList ( core - > GetGC ( ) ) ,
2008-10-13 13:29:18 -07:00
_max_pages ( 1 < < ( calcSaneCacheSize ( cacheSizeLog2 ) - NJ_LOG2_PAGE_SIZE ) ) ,
_pagesGrowth ( 1 )
2008-06-19 10:47:58 -07:00
{
2008-11-08 01:45:50 -08:00
# ifdef _DEBUG
{
// XXX These belong somewhere else, but I can't find the
// right location right now.
NanoStaticAssert ( ( LIR_lt ^ 3 ) = = LIR_ge ) ;
NanoStaticAssert ( ( LIR_le ^ 3 ) = = LIR_gt ) ;
NanoStaticAssert ( ( LIR_ult ^ 3 ) = = LIR_uge ) ;
NanoStaticAssert ( ( LIR_ule ^ 3 ) = = LIR_ugt ) ;
2008-12-08 21:11:56 -08:00
NanoStaticAssert ( ( LIR_flt ^ 3 ) = = LIR_fge ) ;
NanoStaticAssert ( ( LIR_fle ^ 3 ) = = LIR_fgt ) ;
2008-11-08 01:45:50 -08:00
/* Opcodes must be strictly increasing without holes. */
uint32_t count = 0 ;
# define OPDEF(op, number, operands) \
NanoAssertMsg ( LIR_ # # op = = count + + , " misnumbered opcode " ) ;
# define OPDEF64(op, number, operands) OPDEF(op, number, operands)
# include "LIRopcode.tbl"
# undef OPDEF
# undef OPDEF64
}
# endif
2008-07-01 14:46:10 -07:00
# ifdef MEMORY_INFO
_allocList . set_meminfo_name ( " Fragmento._allocList " ) ;
# endif
2008-10-13 13:29:18 -07:00
NanoAssert ( _max_pages > _pagesGrowth ) ; // shrink growth if needed
2008-06-19 10:47:58 -07:00
_core = core ;
GC * gc = core - > GetGC ( ) ;
2008-10-20 15:51:13 -07:00
_assm = NJ_NEW ( gc , nanojit : : Assembler ) ( this ) ;
verbose_only ( enterCounts = NJ_NEW ( gc , BlockHist ) ( gc ) ; )
verbose_only ( mergeCounts = NJ_NEW ( gc , BlockHist ) ( gc ) ; )
2008-06-19 10:47:58 -07:00
}
Fragmento : : ~ Fragmento ( )
{
2008-09-02 10:15:26 -07:00
AllocEntry * entry ;
2008-08-11 16:01:21 -07:00
clearFrags ( ) ;
2008-12-08 15:23:41 -08:00
_frags . clear ( ) ;
2008-11-14 12:46:35 -08:00
_freePages . clear ( ) ;
2008-06-19 10:47:58 -07:00
while ( _allocList . size ( ) > 0 )
{
//fprintf(stderr,"dealloc %x\n", (intptr_t)_allocList.get(_allocList.size()-1));
2008-07-01 14:46:10 -07:00
# ifdef MEMORY_INFO
ChangeSizeExplicit ( " NanoJitMem " , - 1 , _gcHeap - > Size ( _allocList . last ( ) ) ) ;
# endif
2008-09-02 10:15:26 -07:00
entry = _allocList . removeLast ( ) ;
_gcHeap - > Free ( entry - > page , entry - > allocSize ) ;
2008-10-20 15:51:13 -07:00
NJ_DELETE ( entry ) ;
2008-06-19 10:47:58 -07:00
}
2008-10-20 15:51:13 -07:00
NJ_DELETE ( _assm ) ;
2008-08-11 16:01:21 -07:00
# if defined(NJ_VERBOSE)
2008-10-20 15:51:13 -07:00
NJ_DELETE ( enterCounts ) ;
NJ_DELETE ( mergeCounts ) ;
2008-08-11 16:01:21 -07:00
# endif
2008-06-19 10:47:58 -07:00
}
2008-11-14 12:46:35 -08:00
void Fragmento : : trackPages ( )
2008-07-15 13:06:05 -07:00
{
2008-11-14 12:46:35 -08:00
const uint32_t pageUse = _stats . pages - _freePages . size ( ) ;
2008-07-15 13:06:05 -07:00
if ( _stats . maxPageUse < pageUse )
_stats . maxPageUse = pageUse ;
}
2008-06-19 10:47:58 -07:00
Page * Fragmento : : pageAlloc ( )
{
NanoAssert ( sizeof ( Page ) = = NJ_PAGE_SIZE ) ;
2008-11-14 12:46:35 -08:00
if ( ! _freePages . size ( ) )
2008-10-13 13:29:18 -07:00
pagesGrow ( _pagesGrowth ) ; // try to get more mem
if ( ( _pagesGrowth < < 1 ) < _max_pages )
_pagesGrowth < < = 1 ;
2008-11-14 12:46:35 -08:00
trackPages ( ) ;
Page * page = 0 ;
if ( _freePages . size ( ) )
page = _freePages . removeLast ( ) ;
return page ;
2008-10-13 13:29:18 -07:00
}
2008-11-14 12:46:35 -08:00
void Fragmento : : pagesRelease ( PageList & l )
2008-06-19 10:47:58 -07:00
{
2008-11-14 12:46:35 -08:00
_freePages . add ( l ) ;
l . clear ( ) ;
NanoAssert ( _freePages . size ( ) < = _stats . pages ) ;
2008-06-19 10:47:58 -07:00
}
void Fragmento : : pageFree ( Page * page )
{
2008-11-14 12:46:35 -08:00
_freePages . add ( page ) ;
NanoAssert ( _freePages . size ( ) < = _stats . pages ) ;
2008-06-19 10:47:58 -07:00
}
void Fragmento : : pagesGrow ( int32_t count )
{
2008-11-14 12:46:35 -08:00
NanoAssert ( ! _freePages . size ( ) ) ;
2008-06-19 10:47:58 -07:00
MMGC_MEM_TYPE ( " NanojitFragmentoMem " ) ;
Page * memory = 0 ;
2008-11-14 12:46:35 -08:00
GC * gc = _core - > GetGC ( ) ;
2008-07-15 13:06:05 -07:00
if ( _stats . pages < _max_pages )
2008-06-19 10:47:58 -07:00
{
2008-09-02 10:15:26 -07:00
AllocEntry * entry ;
2008-08-22 16:37:37 -07:00
// make sure we don't grow beyond _max_pages
if ( _stats . pages + count > _max_pages )
count = _max_pages - _stats . pages ;
if ( count < 0 )
count = 0 ;
2008-06-19 10:47:58 -07:00
// @todo nastiness that needs a fix'n
2008-11-14 12:46:35 -08:00
_gcHeap = gc - > GetGCHeap ( ) ;
2008-07-15 13:06:05 -07:00
NanoAssert ( int32_t ( NJ_PAGE_SIZE ) < = _gcHeap - > kNativePageSize ) ;
2008-06-19 10:47:58 -07:00
2008-07-15 13:06:05 -07:00
// convert _max_pages to gc page count
2008-06-19 10:47:58 -07:00
int32_t gcpages = ( count * NJ_PAGE_SIZE ) / _gcHeap - > kNativePageSize ;
2008-07-15 13:06:05 -07:00
MMGC_MEM_TYPE ( " NanoJitMem " ) ;
2008-06-19 10:47:58 -07:00
memory = ( Page * ) _gcHeap - > Alloc ( gcpages ) ;
2008-07-01 14:46:10 -07:00
# ifdef MEMORY_INFO
ChangeSizeExplicit ( " NanoJitMem " , 1 , _gcHeap - > Size ( memory ) ) ;
# endif
2008-06-19 10:47:58 -07:00
NanoAssert ( ( int * ) memory = = pageTop ( memory ) ) ;
//fprintf(stderr,"head alloc of %d at %x of %d pages using nj page size of %d\n", gcpages, (intptr_t)memory, (intptr_t)_gcHeap->kNativePageSize, NJ_PAGE_SIZE);
2008-07-16 14:21:31 -07:00
2008-11-14 12:46:35 -08:00
entry = NJ_NEW ( gc , AllocEntry ) ;
2008-09-02 10:15:26 -07:00
entry - > page = memory ;
entry - > allocSize = gcpages ;
_allocList . add ( entry ) ;
2008-06-19 10:47:58 -07:00
_stats . pages + = count ;
2008-11-14 12:46:35 -08:00
Page * page = memory ;
while ( - - count > = 0 )
2008-06-19 10:47:58 -07:00
{
2008-11-14 12:46:35 -08:00
//fprintf(stderr,"Fragmento::pageGrow adding page %x ; %d\n", (unsigned)page, _freePages.size()+1);
_freePages . add ( page + + ) ;
2008-06-19 10:47:58 -07:00
}
2008-11-14 12:46:35 -08:00
trackPages ( ) ;
2008-06-19 10:47:58 -07:00
}
}
2008-11-03 16:14:44 -08:00
// Clear the fragment. This *does not* remove the fragment from the
// map--the caller must take care of this.
void Fragmento : : clearFragment ( Fragment * f )
{
Fragment * peer = f - > peer ;
while ( peer ) {
Fragment * next = peer - > peer ;
peer - > releaseTreeMem ( this ) ;
2008-10-20 15:51:13 -07:00
NJ_DELETE ( peer ) ;
2008-11-03 16:14:44 -08:00
peer = next ;
}
f - > releaseTreeMem ( this ) ;
2008-10-20 15:51:13 -07:00
NJ_DELETE ( f ) ;
2008-11-03 16:14:44 -08:00
}
void Fragmento : : clearFrag ( const void * ip )
{
2008-12-08 15:23:41 -08:00
if ( _frags . containsKey ( ip ) ) {
clearFragment ( _frags . remove ( ip ) ) ;
2008-11-04 14:51:51 -08:00
}
2008-11-03 16:14:44 -08:00
}
2008-06-19 10:47:58 -07:00
void Fragmento : : clearFrags ( )
{
2008-06-24 15:57:33 -07:00
// reclaim any dangling native pages
_assm - > pageReset ( ) ;
2008-06-19 10:47:58 -07:00
2008-12-08 15:23:41 -08:00
while ( ! _frags . isEmpty ( ) ) {
clearFragment ( _frags . removeLast ( ) ) ;
2008-10-27 20:42:49 -07:00
}
2008-06-19 10:47:58 -07:00
verbose_only ( enterCounts - > clear ( ) ; )
verbose_only ( mergeCounts - > clear ( ) ; )
2008-06-24 15:57:33 -07:00
verbose_only ( _stats . flushes + + ) ;
verbose_only ( _stats . compiles = 0 ) ;
//fprintf(stderr, "Fragmento.clearFrags %d free pages of %d\n", _stats.freePages, _stats.pages);
2008-06-19 10:47:58 -07:00
}
Assembler * Fragmento : : assm ( )
{
return _assm ;
}
AvmCore * Fragmento : : core ( )
{
return _core ;
}
2008-10-13 13:29:18 -07:00
Fragment * Fragmento : : getAnchor ( const void * ip )
2008-08-15 20:15:47 -07:00
{
Fragment * f = newFrag ( ip ) ;
2008-12-08 15:23:41 -08:00
Fragment * p = _frags . get ( ip ) ;
2008-08-16 11:42:38 -07:00
if ( p ) {
2008-08-16 15:41:21 -07:00
f - > first = p ;
2008-08-16 11:42:38 -07:00
/* append at the end of the peer list */
Fragment * next ;
while ( ( next = p - > peer ) ! = NULL )
p = next ;
p - > peer = f ;
2008-08-16 15:41:21 -07:00
} else {
f - > first = f ;
2008-12-08 15:23:41 -08:00
_frags . put ( ip , f ) ; /* this is the first fragment */
2008-08-16 15:41:21 -07:00
}
2008-08-15 20:15:47 -07:00
f - > anchor = f ;
f - > root = f ;
f - > kind = LoopTrace ;
2008-12-08 15:23:41 -08:00
verbose_only ( addLabel ( f , " T " , _frags . size ( ) ) ; )
2008-08-15 20:15:47 -07:00
return f ;
}
2008-07-07 02:47:40 -07:00
Fragment * Fragmento : : getLoop ( const void * ip )
2008-06-19 10:47:58 -07:00
{
2008-12-08 15:23:41 -08:00
return _frags . get ( ip ) ;
2008-06-19 10:47:58 -07:00
}
# ifdef NJ_VERBOSE
void Fragmento : : addLabel ( Fragment * f , const char * prefix , int id )
{
char fragname [ 20 ] ;
sprintf ( fragname , " %s%d " , prefix , id ) ;
labels - > add ( f , sizeof ( Fragment ) , 0 , fragname ) ;
}
# endif
2008-07-07 02:47:40 -07:00
Fragment * Fragmento : : getMerge ( GuardRecord * lr , const void * ip )
2008-06-19 10:47:58 -07:00
{
2008-10-21 17:50:32 -07:00
Fragment * anchor = lr - > exit - > from - > anchor ;
2008-06-19 10:47:58 -07:00
for ( Fragment * f = anchor - > branches ; f ! = 0 ; f = f - > nextbranch ) {
2008-07-15 13:06:05 -07:00
if ( f - > kind = = MergeTrace & & f - > ip = = ip /*&& f->calldepth == lr->calldepth*/ ) {
2008-06-19 10:47:58 -07:00
// found existing shared branch on anchor
return f ;
}
}
2008-07-07 02:47:40 -07:00
Fragment * f = newBranch ( anchor , ip ) ;
2008-06-24 15:57:33 -07:00
f - > root = f ;
2008-06-19 10:47:58 -07:00
f - > kind = MergeTrace ;
2008-07-15 13:06:05 -07:00
verbose_only (
int mergeid = 1 ;
for ( Fragment * g = anchor - > branches ; g ! = 0 ; g = g - > nextbranch )
if ( g - > kind = = MergeTrace )
mergeid + + ;
addLabel ( f , " M " , mergeid ) ;
)
2008-06-19 10:47:58 -07:00
return f ;
}
2008-10-21 17:50:32 -07:00
Fragment * Fragmento : : createBranch ( SideExit * exit , const void * ip )
2008-06-19 10:47:58 -07:00
{
2008-10-21 17:50:32 -07:00
Fragment * f = newBranch ( exit - > from , ip ) ;
2008-06-19 10:47:58 -07:00
f - > kind = BranchTrace ;
2008-06-24 15:57:33 -07:00
f - > treeBranches = f - > root - > treeBranches ;
f - > root - > treeBranches = f ;
2008-06-19 10:47:58 -07:00
return f ;
}
# ifdef NJ_VERBOSE
2008-07-15 13:06:05 -07:00
struct fragstats {
int size ;
uint64_t traceDur ;
uint64_t interpDur ;
int lir , lirbytes ;
} ;
void Fragmento : : dumpFragStats ( Fragment * f , int level , fragstats & stat )
2008-06-19 10:47:58 -07:00
{
2008-07-08 17:09:53 -07:00
char buf [ 50 ] ;
sprintf ( buf , " %*c%s " , 1 + level , ' ' , labels - > format ( f ) ) ;
2008-06-19 10:47:58 -07:00
int called = f - > hits ( ) ;
if ( called > = 0 )
called + = f - > _called ;
else
called = - ( 1 < < f - > blacklistLevel ) - called - 1 ;
uint32_t main = f - > _native - f - > _exitNative ;
char cause [ 200 ] ;
if ( f - > _token & & strcmp ( f - > _token , " loop " ) = = 0 )
sprintf ( cause , " %s %d " , f - > _token , f - > xjumpCount ) ;
else if ( f - > _token ) {
if ( f - > eot_target ) {
sprintf ( cause , " %s %s " , f - > _token , labels - > format ( f - > eot_target ) ) ;
} else {
strcpy ( cause , f - > _token ) ;
}
}
else
cause [ 0 ] = 0 ;
2008-06-30 15:33:41 -07:00
2008-07-08 17:09:53 -07:00
_assm - > outputf ( " %-10s %7d %6d %6d %6d %4d %9llu %9llu %-12s %s " , buf ,
2008-06-19 10:47:58 -07:00
called , f - > guardCount , main , f - > _native , f - > compileNbr , f - > traceTicks / 1000 , f - > interpTicks / 1000 ,
2008-07-08 17:09:53 -07:00
cause , labels - > format ( f - > ip ) ) ;
2008-06-30 15:33:41 -07:00
2008-07-15 13:06:05 -07:00
stat . size + = main ;
stat . traceDur + = f - > traceTicks ;
stat . interpDur + = f - > interpTicks ;
stat . lir + = f - > _lir ;
stat . lirbytes + = f - > _lirbytes ;
2008-06-19 10:47:58 -07:00
for ( Fragment * x = f - > branches ; x ! = 0 ; x = x - > nextbranch )
if ( x - > kind ! = MergeTrace )
2008-07-15 13:06:05 -07:00
dumpFragStats ( x , level + 1 , stat ) ;
2008-06-19 10:47:58 -07:00
for ( Fragment * x = f - > branches ; x ! = 0 ; x = x - > nextbranch )
if ( x - > kind = = MergeTrace )
2008-07-15 13:06:05 -07:00
dumpFragStats ( x , level + 1 , stat ) ;
2008-06-19 10:47:58 -07:00
2008-06-24 15:57:33 -07:00
if ( f - > isAnchor ( ) & & f - > branches ! = 0 ) {
2008-06-19 10:47:58 -07:00
_assm - > output ( " " ) ;
}
}
class DurData { public :
DurData ( ) : frag ( 0 ) , traceDur ( 0 ) , interpDur ( 0 ) , size ( 0 ) { }
DurData ( int ) : frag ( 0 ) , traceDur ( 0 ) , interpDur ( 0 ) , size ( 0 ) { }
DurData ( Fragment * f , uint64_t td , uint64_t id , int32_t s )
: frag ( f ) , traceDur ( td ) , interpDur ( id ) , size ( s ) { }
Fragment * frag ;
uint64_t traceDur ;
uint64_t interpDur ;
int32_t size ;
} ;
void Fragmento : : dumpRatio ( const char * label , BlockHist * hist )
{
int total = 0 , unique = 0 ;
for ( int i = 0 , n = hist - > size ( ) ; i < n ; i + + ) {
const void * id = hist - > keyAt ( i ) ;
int c = hist - > get ( id ) ;
if ( c > 1 ) {
//_assm->outputf("%d %X", c, id);
unique + = 1 ;
}
else if ( c = = 1 ) {
unique + = 1 ;
}
total + = c ;
}
_assm - > outputf ( " %s total %d unique %d ratio %.1f% " , label , total , unique , double ( total ) / unique ) ;
}
void Fragmento : : dumpStats ( )
{
bool vsave = _assm - > _verbose ;
_assm - > _verbose = true ;
_assm - > output ( " " ) ;
dumpRatio ( " inline " , enterCounts ) ;
dumpRatio ( " merges " , mergeCounts ) ;
_assm - > outputf ( " abc %d il %d (%.1fx) abc+il %d (%.1fx) " ,
_stats . abcsize , _stats . ilsize , ( double ) _stats . ilsize / _stats . abcsize ,
_stats . abcsize + _stats . ilsize ,
double ( _stats . abcsize + _stats . ilsize ) / _stats . abcsize ) ;
2008-12-08 15:23:41 -08:00
int32_t count = _frags . size ( ) ;
2008-06-19 10:47:58 -07:00
int32_t pages = _stats . pages ;
2008-07-15 13:06:05 -07:00
int32_t maxPageUse = _stats . maxPageUse ;
2008-11-14 12:46:35 -08:00
int32_t free = _freePages . size ( ) ;
2008-06-24 15:57:33 -07:00
int32_t flushes = _stats . flushes ;
2008-06-19 10:47:58 -07:00
if ( ! count )
{
2008-06-24 15:57:33 -07:00
_assm - > outputf ( " No fragments in cache, %d flushes " , flushes ) ;
2008-06-19 10:47:58 -07:00
_assm - > _verbose = vsave ;
return ;
}
2008-06-24 15:57:33 -07:00
_assm - > outputf ( " \n Fragment statistics " ) ;
_assm - > outputf ( " loop trees: %d " , count ) ;
_assm - > outputf ( " flushes: %d " , flushes ) ;
_assm - > outputf ( " compiles: %d / %d " , _stats . compiles , _stats . totalCompiles ) ;
_assm - > outputf ( " used: %dk / %dk " , ( pages - free ) < < ( NJ_LOG2_PAGE_SIZE - 10 ) , pages < < ( NJ_LOG2_PAGE_SIZE - 10 ) ) ;
2008-07-15 13:06:05 -07:00
_assm - > outputf ( " maxPageUse: %dk " , ( maxPageUse ) < < ( NJ_LOG2_PAGE_SIZE - 10 ) ) ;
2008-07-08 17:09:53 -07:00
_assm - > output ( " \n trace calls guards main native gen T-trace T-interp " ) ;
2008-06-19 10:47:58 -07:00
avmplus : : SortedMap < uint64_t , DurData , avmplus : : LIST_NonGCObjects > durs ( _core - > gc ) ;
uint64_t totaldur = 0 ;
2008-07-15 13:06:05 -07:00
fragstats totalstat = { 0 , 0 , 0 , 0 , 0 } ;
2008-06-19 10:47:58 -07:00
for ( int32_t i = 0 ; i < count ; i + + )
{
2008-12-08 15:23:41 -08:00
Fragment * f = _frags . at ( i ) ;
2008-08-15 20:15:47 -07:00
while ( true ) {
fragstats stat = { 0 , 0 , 0 , 0 , 0 } ;
dumpFragStats ( f , 0 , stat ) ;
if ( stat . lir ) {
totalstat . lir + = stat . lir ;
totalstat . lirbytes + = stat . lirbytes ;
}
uint64_t bothDur = stat . traceDur + stat . interpDur ;
if ( bothDur ) {
totalstat . interpDur + = stat . interpDur ;
totalstat . traceDur + = stat . traceDur ;
totalstat . size + = stat . size ;
totaldur + = bothDur ;
while ( durs . containsKey ( bothDur ) ) bothDur + + ;
DurData d ( f , stat . traceDur , stat . interpDur , stat . size ) ;
durs . put ( bothDur , d ) ;
}
if ( ! f - > peer )
break ;
f = f - > peer ;
2008-07-16 14:21:31 -07:00
}
2008-06-19 10:47:58 -07:00
}
2008-07-15 13:06:05 -07:00
uint64_t totaltrace = totalstat . traceDur ;
int totalsize = totalstat . size ;
2008-06-19 10:47:58 -07:00
_assm - > outputf ( " " ) ;
2008-07-16 14:21:31 -07:00
_assm - > outputf ( " lirbytes %d / lir %d = %.1f bytes/lir " , totalstat . lirbytes ,
totalstat . lir , double ( totalstat . lirbytes ) / totalstat . lir ) ;
2008-06-19 10:47:58 -07:00
_assm - > outputf ( " trace interp " ) ;
_assm - > outputf ( " %9lld (%2d%%) %9lld (%2d%%) " ,
totaltrace / 1000 , int ( 100.0 * totaltrace / totaldur ) ,
( totaldur - totaltrace ) / 1000 , int ( 100.0 * ( totaldur - totaltrace ) / totaldur ) ) ;
_assm - > outputf ( " " ) ;
_assm - > outputf ( " trace ticks trace interp size " ) ;
for ( int32_t i = durs . size ( ) - 1 ; i > = 0 ; i - - ) {
uint64_t bothDur = durs . keyAt ( i ) ;
DurData d = durs . get ( bothDur ) ;
int size = d . size ;
2008-07-08 17:09:53 -07:00
_assm - > outputf ( " %-4s %9lld (%2d%%) %9lld (%2d%%) %9lld (%2d%%) %6d (%2d%%) %s " ,
2008-06-19 10:47:58 -07:00
labels - > format ( d . frag ) ,
bothDur / 1000 , int ( 100.0 * bothDur / totaldur ) ,
d . traceDur / 1000 , int ( 100.0 * d . traceDur / totaldur ) ,
d . interpDur / 1000 , int ( 100.0 * d . interpDur / totaldur ) ,
2008-07-08 17:09:53 -07:00
size , int ( 100.0 * size / totalsize ) ,
labels - > format ( d . frag - > ip ) ) ;
2008-06-19 10:47:58 -07:00
}
_assm - > _verbose = vsave ;
}
2008-07-07 02:47:40 -07:00
void Fragmento : : countBlock ( BlockHist * hist , const void * ip )
2008-06-19 10:47:58 -07:00
{
int c = hist - > count ( ip ) ;
if ( _assm - > _verbose )
2008-10-13 13:29:18 -07:00
_assm - > outputf ( " ++ %s %d " , labels - > format ( ip ) , c ) ;
2008-06-19 10:47:58 -07:00
}
void Fragmento : : countIL ( uint32_t il , uint32_t abc )
{
_stats . ilsize + = il ;
_stats . abcsize + = abc ;
}
2008-06-30 15:33:41 -07:00
# ifdef AVMPLUS_VERBOSE
2008-07-31 13:28:12 -07:00
void Fragmento : : drawTrees ( char * fileName ) {
2008-06-30 15:33:41 -07:00
drawTraceTrees ( this , this - > _frags , this - > _core , fileName ) ;
}
# endif
2008-06-19 10:47:58 -07:00
# endif // NJ_VERBOSE
//
// Fragment
//
2008-07-07 02:47:40 -07:00
Fragment : : Fragment ( const void * _ip ) : ip ( _ip )
2008-06-19 10:47:58 -07:00
{
// Fragment is a gc object which is zero'd by the GC, no need to clear fields
}
2008-06-24 15:57:33 -07:00
Fragment : : ~ Fragment ( )
{
2008-08-11 16:01:21 -07:00
onDestroy ( ) ;
2008-06-24 15:57:33 -07:00
NanoAssert ( _pages = = 0 ) ;
}
2008-06-19 10:47:58 -07:00
2008-10-27 20:42:49 -07:00
void Fragment : : resetHits ( )
{
blacklistLevel > > = 1 ;
_hits = 0 ;
}
2008-06-19 10:47:58 -07:00
void Fragment : : blacklist ( )
{
blacklistLevel + + ;
_hits = - ( 1 < < blacklistLevel ) ;
}
2008-07-07 02:47:40 -07:00
Fragment * Fragmento : : newFrag ( const void * ip )
2008-06-19 10:47:58 -07:00
{
GC * gc = _core - > gc ;
2008-10-20 15:51:13 -07:00
Fragment * f = NJ_NEW ( gc , Fragment ) ( ip ) ;
2008-06-19 10:47:58 -07:00
f - > blacklistLevel = 5 ;
2008-10-27 20:42:49 -07:00
f - > recordAttempts = 0 ;
2008-06-19 10:47:58 -07:00
return f ;
}
2008-07-07 02:47:40 -07:00
Fragment * Fragmento : : newBranch ( Fragment * from , const void * ip )
2008-06-19 10:47:58 -07:00
{
2008-07-07 02:47:40 -07:00
Fragment * f = newFrag ( ip ) ;
2008-06-19 10:47:58 -07:00
f - > anchor = from - > anchor ;
2008-06-24 15:57:33 -07:00
f - > root = from - > root ;
2008-06-19 10:47:58 -07:00
f - > xjumpCount = from - > xjumpCount ;
/*// prepend
f - > nextbranch = from - > branches ;
from - > branches = f ; */
// append
if ( ! from - > branches ) {
from - > branches = f ;
} else {
Fragment * p = from - > branches ;
while ( p - > nextbranch ! = 0 )
p = p - > nextbranch ;
p - > nextbranch = f ;
}
return f ;
}
2008-06-24 15:57:33 -07:00
void Fragment : : releaseLirBuffer ( )
{
lastIns = 0 ;
}
2008-06-19 10:47:58 -07:00
2008-06-24 15:57:33 -07:00
void Fragment : : releaseCode ( Fragmento * frago )
{
_code = 0 ;
while ( _pages )
{
Page * next = _pages - > next ;
frago - > pageFree ( _pages ) ;
_pages = next ;
}
}
void Fragment : : releaseTreeMem ( Fragmento * frago )
{
releaseLirBuffer ( ) ;
releaseCode ( frago ) ;
2008-08-18 12:32:14 -07:00
2008-06-24 15:57:33 -07:00
// now do it for all branches
Fragment * branch = branches ;
while ( branch )
{
Fragment * next = branch - > nextbranch ;
branch - > releaseTreeMem ( frago ) ; // @todo safer here to recurse in case we support nested trees
2008-10-20 15:51:13 -07:00
NJ_DELETE ( branch ) ;
2008-06-24 15:57:33 -07:00
branch = next ;
}
}
2008-06-19 10:47:58 -07:00
# endif /* FEATURE_NANOJIT */
}
2008-06-30 15:33:41 -07:00