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:
parent
209a8faacf
commit
3f7095bbd9
7 changed files with 232 additions and 119 deletions
|
@ -125,6 +125,7 @@ static void main_exit(bool silent)
|
|||
|
||||
TRY
|
||||
{
|
||||
JIT_abort();
|
||||
SIGNAL_exit();
|
||||
EXTERN_release();
|
||||
STREAM_exit();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
121
main/lib/jit/gb.jit/.src/CCompilation.class
Normal file
121
main/lib/jit/gb.jit/.src/CCompilation.class
Normal 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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue