March 05, 2021, 06:24:08 AM

Author Topic: [bmx] BriskVM invoker as function pointers by GW [ 1+ years ago ]  (Read 602 times)

Offline BlitzBot

Title : BriskVM invoker as function pointers
Author : GW
Posted : 1+ years ago

Description : This program will read an already generated invoker file and convert it to one that uses function pointers, giving a large speed boost.  
It does not overwrite the original invoker file.ead in an existing invoker file and will spit out a copy that internally uses function pointer.


Code :
Code: BlitzMax
  1. Rem
  2.         BVM invoker converter by AWoodard 2014 (admin at kerneltrick.com)
  3. EndRem
  4.  
  5. SuperStrict
  6. Framework brl.retro
  7.  
  8. Local aa$[] = AppArgs[..]       '// for debugging
  9.  
  10. Global outStream:TStream
  11.  
  12. If AppArgs.Length <> 2 Then
  13.         Print "Usage: BVM_Converter <invoker.bmx>"     
  14.         End
  15. EndIf
  16.  
  17. outstream =  WriteFile(StripExt(AppArgs[1]) + "_" + ".bmx" )
  18.  
  19. reprocess(AppArgs[1])
  20. '------------------------------------------------------------------------------------------------------------
  21. Function _Print(s$)
  22.         WriteString(outStream,s+"~n")  
  23. End Function
  24. '------------------------------------------------------------------------------------------------------------
  25. Function reprocess( file$)
  26.         Local invokertext$      'raw text
  27.         Local aLines$[]         'invoker text split by line
  28.         Local startline%        'start of invoke function
  29.         Local endline%          'end of select/case
  30.         Local startSelect%      'line of 'Select ret%"
  31.         Global firstLine$ = "Function BVM_Invoke%(withTimeOut% = False)"
  32.         Local maxIndex% = 0
  33.         Local Locals$[]
  34.         Local cases:TList = CreateList()
  35.                
  36.         If Not FileType(file)=1 Then RuntimeError("Not a valid invoker file! " + file)
  37.         invokertext = LoadText(file)
  38.         aLines = invokertext.split("~n")
  39.        
  40.         startline = find_string(aLines, firstline)
  41.         If Not startline Then RuntimeError("Cant Find function def!")
  42.        
  43.         endline = find_string(aLines, "End Function", startline+1 )
  44.         If Not endline Then RuntimeError("Cant Find end block!")
  45.        
  46.         startselect = find_string(aLines, "Select ret%")
  47.        
  48.         maxIndex = FindMaxIndex(aLines, startline, endline)     '// find the largest case value
  49.  
  50.         Locals = GatherLocals(Locals, aLines, startline, endline)       'wtf!? 'Locals' array is not passes by ref?!
  51.        
  52.  
  53.         '// write pre
  54.         For Local i% = 0 Until startline        '// write out the file before our mods
  55.                 _Print(aLines[i])
  56.         Next
  57.        
  58.         _Print "Function Err2%()"
  59.         _Print "        BVM_SetLastError(BVM_ERR_ERROR%, ~qFatal error : unknown command of id ~q + BVM_IntToStr(tBVMf.ret))" '+ ", the invoker seems To be out of sync with the 'Test' command set")"
  60.         _Print "        BVM_ReportDebugError(BVM_GetLastErrorMsg())"
  61.         _Print "        Return 0"
  62.         _Print "End function~n"
  63.  
  64.  
  65.         _Print "Function BVM_FP_run%(index%)"
  66.         _Print "        Local tmpfunc%() = tBVMf.FP[index]"
  67.         _Print "        return tmpfunc()"
  68.         _Print "End Function~n"
  69.  
  70.                
  71.         _Print "Type tBVMf"
  72.                 _Print "~tGlobal hasInit%=0"
  73.                 _Print "~tGlobal withTimeOut%"
  74.                 _Print "~tGlobal FP:byte ptr["+(maxindex+1)+"]"
  75.         '// Get locals from func
  76.                 For Local s$ = EachIn locals
  77.                         _Print "~tGlobal " + s
  78.                 Next
  79.                
  80.         ''Print "~t'GLOBALS"
  81.        
  82.        
  83.         Local block$[]
  84.         For Local i% = 0 Until MaxIndex
  85. '               Print i
  86.                 block = GetBLockContents(aLInes, i, startline, endline )
  87.                 If block.length Then
  88.                         WriteFuncBlock(i,block)
  89.                         cases.AddLast(String(i))
  90.                 End If
  91.         Next
  92.        
  93.         '// set all the pointers to the ERR function at start
  94.         _Print "        Function Init()"
  95.                 _Print "~t~tFor Local i% = 0 Until "+maxindex
  96.                 _Print "~t~t~tFP[i]=Err2"
  97.                 _Print "~t~tNext"
  98.                
  99.                 '// now just replace the ones we use
  100.                 For Local s$ = EachIn cases
  101.                         _Print "~t~tFP["+Int(s)+"] = tBVMf._bvmf_" + Int(s)
  102.                 Next
  103.         _Print "        hasInit=1"
  104.         _Print "        End Function~n"
  105.        
  106.  
  107.        
  108.         _Print "End Type"
  109.        
  110.         _Print firstline
  111.         _Print "local ret%"
  112.         _print "tBVMf.withTimeOut%=withTimeOut"
  113.         _print " if not tBVMf.hasInit then tBVMf.init()"
  114.         _Print " Repeat"
  115.         _Print "        If withTimeOut% Then"
  116.         _Print "                ret% = BVM_RunWithTimeOut()"
  117.         _Print "        Else"
  118.         _Print "                ret% = BVM_Run()"
  119.         _Print "        End If"
  120.         _Print "        tBVMf.ret = ret"
  121.         _Print "        Select ret"
  122.         _Print "                Case 0"
  123.         _print "                        BVM_FlushDebugLog(); Return 1"
  124.         _Print "                Case 1"
  125.         _Print "                        If withTimeOut% Then"
  126.         _Print "                                Return -1"
  127.         _Print "                        Else"
  128.         _Print "                                BVM_ReportDebugError(BVM_GetLastErrorMsg())"
  129.         _Print "                                Return 0"
  130.         _Print "                        End If"
  131.         _Print "                Case -1"
  132.         _Print "                        BVM_ReportDebugError(BVM_GetLastErrorMsg())"
  133.         _Print "                        Return 0"
  134.         _Print "                Default"
  135.         _Print "        '               If Int(tBVMf.FP[ret]) <> 0 Then"
  136.         _Print "                                BVM_FP_run(ret)"
  137.         _Print "        '               Else"
  138.         _Print "        '                       BVM_SetLastError(BVM_ERR_ERROR%, ~qFatal error : unknown command of id ~q + BVM_IntToStr(ret%))" '+ ", the invoker seems To be out of sync with the 'Test' command set")"
  139.         _Print "        '                       BVM_ReportDebugError(BVM_GetLastErrorMsg())"
  140.         _Print "        '                       Return 0"
  141.         _Print "        '               endif"
  142.         _Print "        End Select      "
  143.        
  144.         '_print "       if ret = 0 then"
  145.         '_print "               BVM_FlushDebugLog(); Return 1"
  146.         '_print "       EndIf" 
  147.        
  148.         '_Print "       if ret = -1 then"
  149.  
  150.         '_Print "       EndIf"
  151.        
  152.         _Print " Forever"
  153.         _Print "End Function~n"
  154.        
  155.         For Local I% = endline +1 Until aLines.Length
  156.                 _Print aLines[i]
  157.         Next
  158.        
  159. End Function
  160. '------------------------------------------------------------------------------------------------------------
  161. Function GatherLocals$[](Locals$[], aLInes$[], _start%, _end%)
  162.         For Local i% = _start To _end
  163.                 If Left(Trim(aLines[i]),5) = "Local" Then
  164.                         Locals :+ [ aLines[i].Split("Local ")[1] ]
  165.                 EndIf
  166.         Next
  167.         Return locals
  168. End Function
  169. '------------------------------------------------------------------------------------------------------------
  170. Function Find_string%(aLines$[], needle$, start%=0)
  171.         For Local i% = start Until aLines.Length
  172.                 If Lower(Trim(alines[i])) = Lower(Trim(needle)) Then
  173.                         Return i
  174.                 EndIf
  175.         Next
  176.         Return False
  177. End Function
  178. '------------------------------------------------------------------------------------------------------------
  179. Function WriteFuncBlock$(num%, contents$[])
  180.         _Print "        Function _bvmf_" + num + "%()"
  181.         For Local s$ = EachIn contents
  182.                 _Print s.Replace("~t~t","~t")
  183.         Next
  184.         _Print "        End Function~n"
  185. End Function
  186. '------------------------------------------------------------------------------------------------------------
  187. '------------------------------------------------------------------------------------------------------------
  188. Function FindMaxIndex%( aLines$[], _start%, _end%)
  189.         '// Find the largest case value //
  190.         Local res%=-9999
  191.         Local num%
  192.         Local aTmp$[]
  193.        
  194.         Assert(_end < aLines.length)
  195.                 For Local i% = _start Until _end
  196.                         If alines[i].Contains("Case 0") Then Continue
  197.                         If Left(Trim(aLines[i]),4) = "Case" Then
  198.                                 aTmp =  Trim(aLines[i]).Split(" ")
  199.                                 num = Int(aTmp[1])
  200.                                 If Not num Then
  201.                                         RuntimeError("wrong number at line " + i)
  202.                                 End If 
  203.                                 If num > res Then res = num
  204.                         EndIf
  205.                 Next
  206.                
  207.                 Return res
  208. End Function
  209. '------------------------------------------------------------------------------------------------------------
  210. Function GetBLockContents$[](aLInes$[], num%, _start%, _end%)
  211.         '// get the contents of the case block and return as a string array or empty //
  212.         Local state% = False
  213.         Local block$[]
  214.        
  215.         For Local i% = _start Until _end       
  216.                 If Lower(Trim(aLines[i])) = "case " + num Then
  217.                         'If state Then Return block            
  218.                         state = True
  219.                         Continue
  220.                 EndIf
  221.                 If state Then
  222.                         If Left(Lower(Trim(aLines[i])),4) = "case" Then Return block
  223.                         block :+ [aLInes[i]]
  224.                 EndIf
  225. '               Print i
  226.         Next
  227.         Return block
  228. End Function
  229.  
  230. '------------------------------------------------------------------------------------------------------------


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal