Run JIT compilation in the background to make programs start faster.

[INTERPRETER]
* OPT: JIT compilation is run in two steps.

[GB.JIT]
* OPT: Run JIT compilation in the background.
* NEW: JIT.Debug is a new property that allows to enable JIT debugging messages at runtime.
This commit is contained in:
gambas 2019-03-11 16:34:50 +01:00
parent 209a8faacf
commit 3f7095bbd9
7 changed files with 232 additions and 119 deletions

View file

@ -125,6 +125,7 @@ static void main_exit(bool silent)
TRY
{
JIT_abort();
SIGNAL_exit();
EXTERN_release();
STREAM_exit();

View file

@ -1195,6 +1195,7 @@ END_PROPERTY
BEGIN_METHOD(Process_Wait, GB_FLOAT timeout)
// FIXME: Does not work if Ignore is set
CPROCESS_wait_for(THIS, (int)(VARGOPT(timeout, 0.0) * 1000));
END_METHOD

View file

@ -1256,14 +1256,8 @@ static void load_without_inits(CLASS *class)
ARCHIVE *arch = class->component ? class->component->archive : NULL;
if (JIT_can_compile(arch))
{
if (JIT_compile(arch))
{
for(i = 0; i < class->load->n_func; i++)
class->load->func[i].fast = FALSE;
}
}
JIT_compile(arch);
break;
}
}

View file

@ -43,6 +43,7 @@ bool JIT_disabled = FALSE;
static bool _component_loaded = FALSE;
static GB_FUNCTION _jit_compile_func;
static GB_FUNCTION _jit_wait_func;
static bool _jit_compiling = FALSE;
static void *_jit_library = NULL;
@ -56,32 +57,30 @@ void JIT_exit(void)
ARRAY_delete(&_jit_func);
}
void JIT_abort(void)
{
static GB_FUNCTION _func;
if (GB_GetFunction(&_func, CLASS_find_global("Jit"), "_Abort", NULL, NULL))
ERROR_panic("Unable to find JIT._Abort() method");
GB_Call(&_func, 0, FALSE);
}
bool JIT_can_compile(ARCHIVE *arch)
{
return arch ? !arch->jit_compiling : !_jit_compiling;
}
bool JIT_compile(ARCHIVE *arch)
void JIT_compile(ARCHIVE *arch)
{
GB_VALUE *ret;
char *path;
void *lib;
void **iface;
COMPONENT *current;
if (JIT_disabled)
return TRUE;
return;
if (arch)
{
if (arch->jit_library)
return FALSE;
}
else
{
if (_jit_library)
return FALSE;
}
if (arch ? arch->jit_library : _jit_library)
return;
if (!_component_loaded)
{
@ -93,7 +92,7 @@ bool JIT_compile(ARCHIVE *arch)
if (var && var[0] && !(var[0] == '0' && var[1] == 0))
{
JIT_disabled = TRUE;
return TRUE;
return;
}
var = getenv("GB_JIT_DEBUG");
@ -104,8 +103,10 @@ bool JIT_compile(ARCHIVE *arch)
fprintf(stderr, "gbx3: loading gb.jit component\n");
COMPONENT_load(COMPONENT_create("gb.jit"));
if (GB_GetFunction(&_jit_compile_func, CLASS_find_global("Jit"), "_Compile", "s", "s"))
ERROR_panic("Unable to find JIT compilation method");
if (GB_GetFunction(&_jit_compile_func, CLASS_find_global("Jit"), "_Compile", "s", "b"))
ERROR_panic("Unable to find JIT._Compile() method");
if (GB_GetFunction(&_jit_wait_func, CLASS_find_global("Jit"), "_Wait", "s", "s"))
ERROR_panic("Unable to find JIT._Wait() method");
}
arch ? (arch->jit_compiling = TRUE) : (_jit_compiling = TRUE);
@ -114,16 +115,39 @@ bool JIT_compile(ARCHIVE *arch)
COMPONENT_current = NULL;
GB_Push(1, T_STRING, arch ? arch->name : "", -1);
ret = GB_Call(&_jit_compile_func, 1, FALSE);
path = GB_ToZeroString((GB_STRING *)ret);
GB_Call(&_jit_compile_func, 1, FALSE);
COMPONENT_current = current;
}
bool wait_for_compilation(ARCHIVE *arch)
{
COMPONENT *current;
void *lib;
void **iface;
GB_VALUE *ret;
char *path;
if (JIT_disabled)
return TRUE;
if (arch ? arch->jit_library : _jit_library)
return FALSE;
current = COMPONENT_current;
COMPONENT_current = NULL;
GB_Push(1, T_STRING, arch ? arch->name : "", -1);
ret = GB_Call(&_jit_wait_func, 1, FALSE);
COMPONENT_current = current;
if (!*path)
ERROR_panic("Unable to compile JIT source file");
arch ? (arch->jit_compiling = FALSE) : (_jit_compiling = FALSE);
path = GB_ToZeroString((GB_STRING *)ret);
if (!*path)
ERROR_panic("Unable to compile JIT source file");
//fprintf(stderr, "gbx3: shared jit library is: %s\n", path);
lib = dlopen(path, RTLD_NOW);
@ -157,6 +181,13 @@ static bool create_function(CLASS *class, int index)
arch = class->component ? class->component->archive : NULL;
if (wait_for_compilation(arch))
{
for (i = 0; i < class->load->n_func; i++)
class->load->func[i].fast = FALSE;
return TRUE;
}
func = &class->load->func[index];
func->fast_linked = TRUE;
@ -203,6 +234,7 @@ void JIT_exec(bool ret_on_stack)
VALUE *sp = SP;
JIT_FUNCTION *jit;
CLASS *class = EXEC.class;
void *object = EXEC.object;
char nparam = EXEC.nparam;
VALUE ret;
FUNCTION *func = EXEC.func;
@ -221,7 +253,7 @@ void JIT_exec(bool ret_on_stack)
STACK_push_frame(&EXEC_current, func->stack_usage);
CP = class;
OP = (void *)EXEC.object;
OP = object;
FP = func;
EC = NULL;

View file

@ -38,7 +38,7 @@ typedef
extern bool JIT_disabled;
#endif
bool JIT_compile(ARCHIVE *arch);
void JIT_compile(ARCHIVE *arch);
void JIT_debug(const char *fmt, ...);
void JIT_exec(bool ret_on_stack);
PCODE *JIT_get_code(FUNCTION *func);
@ -46,6 +46,7 @@ CLASS_CONST *JIT_get_constant(int index);
void *JIT_get_class_ref(int index);
void JIT_call_unknown(PCODE *pc, VALUE **psp);
void JIT_abort(void);
void JIT_exit(void);
bool JIT_can_compile(ARCHIVE *arch);

View file

@ -0,0 +1,121 @@
' Gambas class file
Static Public All As New Collection
Static Private $sCompiler As String
Static Private $aFlags As String[]
Public Name As String
Public PathSO As String
Private $sResult As String
Private $fTime As Float
Private $hProcess As Process
Static Private Sub Init()
Dim sFlag As String
Dim sCompiler As String
sCompiler = Env["GB_JIT_CC"]
If Not sCompiler Then sCompiler = "gcc"
$sCompiler = System.Find(sCompiler)
If Not $sCompiler Then Error.Raise("Compiler not found")
sFlag = Env["GB_JIT_CFLAGS"]
If Not sFlag Then sFlag = "-O3"
$aFlags = Split(sFlag, " ")
End
Public Sub _new(sName As String, sPathSO As String, fTime As Float)
Name = sName
PathSO = sPathSO
$fTime = fTime
All[sName] = Me
End
Public Sub Run(sInput As String, Optional sOutput As String, sOption As String)
Dim aExec As String[]
'Dim I As Integer
If Not $sCompiler Then Init
aExec = [$sCompiler]
If sOption Then aExec.Insert(Split(sOption, " "))
aExec.Insert($aFlags)
aExec.Add(sInput)
If sOutput Then
aExec.Add("-o")
aExec.Add(sOutput)
Endif
' For I = 0 To aExec.Max
' aExec[I] = Shell$(aExec[I])
' Next
If Jit.Debug Then Error "gb.jit: run: "; aExec.Join(" ")
$hProcess = Exec aExec For Read As "Compiler"
'$hProcess.Ignore = True
'System._Breakpoint
End
Public Sub Compiler_Read()
Dim sData As String
sData = Read #$hProcess, -1024
$sResult &= sData
End
Public Sub Compiler_Error(({Error}) As String)
$sResult &= {Error}
End
Public Sub Compiler_Kill()
If $hProcess.Value = 0 Then
$fTime = Timer - $fTime
Jit._Time += $fTime
If Jit.Debug Then Error "gb.jit: compilation of '"; Name; "' done in "; Format($fTime, "0.000"); " s"
Else
If Jit.Debug Then Error "gb.jit: compilation of '"; Name; "' returns "; $hProcess.Value
Endif
' Shell "objdump -S " & Shell(sPathSO) To sResult
' Error sResult
End
Public Sub Wait() As String
If Jit.Debug Then Error "gb.jit: waiting for compilation of '"; Name; "'..."
$hProcess.Wait
If Not Exist(PathSO) Then
Error "gb.jit: error: unable to compile JIT code of '"; Name; "':"
Error $sResult
Return
Endif
Return PathSO
End
Public Sub Kill()
Try $hProcess.Kill
$hProcess = Null
End

View file

@ -4,87 +4,23 @@ Export
Class __Jit
Property Read Time As Float
Property Debug As Boolean
Public _Time As Float
Private $fTime As Float
Private $sCompiler As String
Private $aFlags As String[]
Private $hProcess As Process
Private $sResult As String
Private $bDebug As Integer
Private Sub Init()
Dim sFlag As String
Dim sCompiler As String
sCompiler = Env["GB_JIT_CC"]
If Not sCompiler Then sCompiler = "gcc"
$sCompiler = System.Find(sCompiler)
If Not $sCompiler Then Error.Raise("Compiler not found")
sFlag = Env["GB_JIT_CFLAGS"]
If Not sFlag Then sFlag = "-O3"
$aFlags = Split(sFlag, " ")
End
Private Sub RunCompiler(sInput As String, Optional sOutput As String, sOption As String) As String
Dim aExec As String[]
'Dim I As Integer
aExec = [$sCompiler]
If sOption Then aExec.Insert(Split(sOption, " "))
aExec.Insert($aFlags)
aExec.Add(sInput)
If sOutput Then
aExec.Add("-o")
aExec.Add(sOutput)
Endif
' For I = 0 To aExec.Max
' aExec[I] = Shell$(aExec[I])
' Next
If $bDebug Then Error "gb.jit: run: "; aExec.Join(" ")
$sResult = ""
$hProcess = Exec aExec For Read As "Compiler"
$hProcess.Wait
'Shell aExec.Join(" ") & " 2>&1" To sResult
Return $sResult
End
Public Sub Compiler_Read()
Dim sData As String
sData = Read #$hProcess, -1024
$sResult &= sData
End
Public Sub Compiler_Error(({Error}) As String)
$sResult &= {Error}
End
Public Sub _Compile(sArch As String) As String
Public Sub _Compile(sArch As String) As Boolean
Dim sFile As String
Dim sDir As String
Dim sName As String
Dim sPath As String
Dim hFile As File
Dim sResult As String
Dim sPathO As String
Dim sPathSO As String
Dim fTime As Float
Dim hComp As CCompilation
fTime = Timer
@ -92,9 +28,6 @@ Public Sub _Compile(sArch As String) As String
If $bDebug Then Error "gb.jit: translating "; If(sArch, sArch, "project")
If Not $sCompiler Then Init
sName = sArch
If Not sName Then sName = "gb"
@ -184,12 +117,10 @@ Public Sub _Compile(sArch As String) As String
'gcc -c -fPIC -o foo.o foo.c
'Exec [$sCompiler, "-c", "-fPIC", "-o", File.SetExt(sPath, "o"), sPath] To sResult
'Shell $sCompiler & " -c -fPIC " & sFlag & " -o " & Shell(sPathO) & " " & Shell(sPath) & " 2>&1" To sResult
sResult = RunCompiler(sPath, sPathSO, "-w -fPIC -shared -lm")
If Not Exist(sPathSO) Then
Error "gb.jit: error: unable to compile JIT code:"
Error sResult
Return
Endif
hComp = New CCompilation(sName, sPathSO, fTime)
hComp.Run(sPath, sPathSO, "-w -fPIC -shared -lm")
' If $bDebug Then Error "gb.jit: linking to "; sPathSO
'
@ -203,20 +134,52 @@ Public Sub _Compile(sArch As String) As String
' Return
' Endif
fTime = Timer - fTime
$fTime += fTime
End
Public Sub _Wait(sArch As String) As String
Dim hComp As CCompilation
Dim sResult As String
If $bDebug Then Error "gb.jit: done in "; Format(fTime, "0.000"); "s"
If Not sArch Then sArch = "gb"
hComp = CCompilation.All[sArch]
If Not hComp Then Return
' Shell "objdump -S " & Shell(sPathSO) To sResult
' Error sResult
sResult = hComp.Wait()
Return sResult
End
Public Sub _Abort()
Dim hComp As CCompilation
Return sPathSO
If $bDebug Then Error "gb.jit: abort compilation"
For Each hComp In CCompilation.All
hComp.Kill
Next
CCompilation.All.Clear
End
Private Function Time_Read() As Float
Return $fTime
Return _Time
End
Private Function Debug_Read() As Boolean
Return $bDebug
End
Private Sub Debug_Write(Value As Boolean)
$bDebug = Value
End