@@ -27,15 +27,11 @@ import {
2727
2828import {
2929 BinFmt ,
30- CellDebugInfo ,
3130 ValueType ,
32- DebugInfo ,
33- FunctionDebugInfo ,
3431 Host ,
3532 OpCall ,
3633 NumFmt ,
3734 Op ,
38- RoleDebugInfo ,
3935 SMap ,
4036 ValueKind ,
4137 JacsDiagnostic ,
@@ -66,6 +62,13 @@ import {
6662import { buildAST , formatDiagnostics , getProgramDiagnostics } from "./tsiface"
6763import { preludeFiles } from "./specgen"
6864import { jacdacDefaultSpecifications } from "./embedspecs"
65+ import {
66+ CellDebugInfo ,
67+ RoleDebugInfo ,
68+ FunctionDebugInfo ,
69+ DebugInfo ,
70+ SrcLocation ,
71+ } from "./info"
6972
7073export const JD_SERIAL_HEADER_SIZE = 16
7174export const JD_SERIAL_MAX_PAYLOAD_SIZE = 236
@@ -80,6 +83,7 @@ export const DEVS_BYTECODE_FILE = `${DEVS_FILE_PREFIX}.devs`
8083export const DEVS_LIB_FILE = `${ DEVS_FILE_PREFIX } -lib.json`
8184export const DEVS_BODY_FILE = `${ DEVS_FILE_PREFIX } -body.json`
8285export const DEVS_DBG_FILE = `${ DEVS_FILE_PREFIX } -dbg.json`
86+ export const DEVS_SIZES_FILE = `${ DEVS_FILE_PREFIX } -sizes.txts`
8387
8488class Cell {
8589 _index : number
@@ -271,6 +275,18 @@ function cellKind(v: Value): ValueType {
271275 return v . valueType
272276}
273277
278+ function toSrcLocation ( n : ts . Node ) : SrcLocation {
279+ const f = n . getSourceFile ( )
280+ const pp = f . getLineAndCharacterOfPosition ( n . pos )
281+ return {
282+ file : f . fileName ,
283+ line : pp . line + 1 ,
284+ col : pp . character + 1 ,
285+ len : n . end - n . pos ,
286+ pos : n . pos ,
287+ }
288+ }
289+
274290function idName ( pat : ts . Expression | ts . DeclarationName ) {
275291 if ( ts . isIdentifier ( pat ) ) return pat . text
276292 else return null
@@ -303,6 +319,8 @@ class Procedure {
303319 params : VariableScope
304320 locals : VariableScope
305321 methodSeqNo : Variable
322+ users : ts . Node [ ] = [ ]
323+ skipAccounting = false
306324 constructor ( public parent : Program , public name : string ) {
307325 this . index = this . parent . procs . length
308326 this . writer = new OpWriter ( parent , `${ this . name } _F${ this . index } ` )
@@ -322,6 +340,10 @@ class Procedure {
322340 args ( ) {
323341 return this . params . list . slice ( ) as Variable [ ]
324342 }
343+ useFrom ( node : ts . Node ) {
344+ if ( this . users . indexOf ( node ) >= 0 ) return
345+ this . users . push ( node )
346+ }
325347 mkTempLocal ( name : string , tp : ValueType ) {
326348 const l = new Variable ( null , this . locals , tp )
327349 l . _name = name
@@ -333,6 +355,8 @@ class Procedure {
333355 return {
334356 name : this . name ,
335357 srcmap : this . writer . srcmap ,
358+ size : this . writer . size ,
359+ users : this . users . map ( toSrcLocation ) ,
336360 locals : this . params . list
337361 . concat ( this . locals . list )
338362 . map ( v => v . debugInfo ( ) ) ,
@@ -439,6 +463,7 @@ class Program implements TopOpWriter {
439463 stringLiterals : ( string | Uint8Array ) [ ] = [ ]
440464 writer : OpWriter
441465 proc : Procedure
466+ accountingProc : Procedure
442467 sysSpec : jdspec . ServiceSpec
443468 serviceSpecs : Record < string , jdspec . ServiceSpec >
444469 enums : Record < string , jdspec . EnumInfo > = { }
@@ -565,6 +590,7 @@ class Program implements TopOpWriter {
565590 private roleDispatcher ( role : Role ) {
566591 if ( ! role . dispatcher ) {
567592 const proc = new Procedure ( this , role . getName ( ) + "_disp" )
593+ proc . skipAccounting = true
568594 role . dispatcher = {
569595 proc,
570596 top : proc . writer . mkLabel ( "disp_top" ) ,
@@ -702,13 +728,16 @@ class Program implements TopOpWriter {
702728 private withProcedure < T > ( proc : Procedure , f : ( wr : OpWriter ) => T ) {
703729 assert ( ! ! proc )
704730 const prevProc = this . proc
731+ const prevAcc = this . accountingProc
705732 try {
706733 this . proc = proc
734+ if ( ! proc . skipAccounting ) this . accountingProc = proc
707735 this . writer = proc . writer
708736 return f ( proc . writer )
709737 } finally {
710738 this . proc = prevProc
711739 if ( prevProc ) this . writer = prevProc . writer
740+ this . accountingProc = prevAcc
712741 }
713742 }
714743
@@ -1082,6 +1111,12 @@ class Program implements TopOpWriter {
10821111 this . writer . assertNoTemps ( )
10831112 }
10841113
1114+ private uniqueProcName ( base : string ) {
1115+ let suff = 0
1116+ while ( this . procs . some ( p => p . name == base + "_" + suff ) ) suff ++
1117+ return base + "_" + suff
1118+ }
1119+
10851120 private emitHandler (
10861121 name : string ,
10871122 func : Expr ,
@@ -1092,7 +1127,8 @@ class Program implements TopOpWriter {
10921127 ) : Procedure {
10931128 if ( ! ts . isArrowFunction ( func ) )
10941129 throwError ( func , "arrow function expected here" )
1095- const proc = new Procedure ( this , name )
1130+ const proc = new Procedure ( this , this . uniqueProcName ( name ) )
1131+ proc . useFrom ( func )
10961132 proc . writer . ret = proc . writer . mkLabel ( "ret" )
10971133 if ( func . parameters . length && ! options . methodHandler )
10981134 throwError ( func , "parameters not supported here" )
@@ -1872,6 +1908,7 @@ class Program implements TopOpWriter {
18721908 ) {
18731909 const wr = this . writer
18741910 const args = expr . arguments . slice ( )
1911+ proc . useFrom ( expr )
18751912 if ( isMember ) {
18761913 this . requireArgs ( expr , proc . numargs - 1 )
18771914 if ( ts . isPropertyAccessExpression ( expr . expression ) )
@@ -2833,6 +2870,7 @@ class Program implements TopOpWriter {
28332870 }
28342871 this . host . write ( DEVS_BODY_FILE , JSON . stringify ( progJson , null , 4 ) )
28352872 this . host . write ( DEVS_DBG_FILE , JSON . stringify ( dbg , null , 4 ) )
2873+ this . host . write ( DEVS_SIZES_FILE , computeSizes ( dbg ) )
28362874
28372875 // write assembly again
28382876 if ( this . numErrors == 0 )
@@ -2988,3 +3026,23 @@ export function testCompiler(host: Host, code: string) {
29883026 }
29893027 }
29903028}
3029+
3030+ export function computeSizes ( dbg : DebugInfo ) {
3031+ const funs = dbg . functions . slice ( )
3032+ funs . sort ( ( a , b ) => a . size - b . size || strcmp ( a . name , b . name ) )
3033+ return (
3034+ "\n## Functions\n" +
3035+ funs . map ( f => `${ f . size } \t${ f . name } \t${ locs2str ( f . users ) } \n` ) . join ( "" )
3036+ )
3037+
3038+ function loc2str ( l : SrcLocation ) {
3039+ return `${ l . file } (${ l . line } ,${ l . col } )`
3040+ }
3041+
3042+ function locs2str ( ls : SrcLocation [ ] ) {
3043+ const maxlen = 10
3044+ let r = ls . slice ( 0 , maxlen ) . map ( loc2str ) . join ( ", " )
3045+ if ( ls . length > maxlen ) r += "..."
3046+ return r
3047+ }
3048+ }
0 commit comments