From b40e76d8370de38ce660cff90178d8f21a6c7d29 Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Mon, 12 Aug 2024 05:13:14 +0300 Subject: [PATCH 1/6] update builtin types for change vm to unsafe --- runtime/ishtar.vm/__builtin/B_App.cs | 12 +-- runtime/ishtar.vm/__builtin/B_Field.cs | 10 +-- runtime/ishtar.vm/__builtin/B_Function.cs | 14 ++-- runtime/ishtar.vm/__builtin/B_GC.cs | 4 +- runtime/ishtar.vm/__builtin/B_IEEEConsts.cs | 2 +- runtime/ishtar.vm/__builtin/B_NAPI.cs | 6 +- runtime/ishtar.vm/__builtin/B_Out.cs | 6 +- runtime/ishtar.vm/__builtin/B_String.cs | 10 +-- .../ishtar.vm/__builtin/B_StringBuilder.cs | 28 +++---- runtime/ishtar.vm/__builtin/B_Sys.cs | 12 +-- runtime/ishtar.vm/__builtin/B_Threading.cs | 19 +++-- runtime/ishtar.vm/__builtin/B_Type.cs | 82 +++++++++---------- runtime/ishtar.vm/__builtin/X_Utils.cs | 6 +- 13 files changed, 107 insertions(+), 104 deletions(-) diff --git a/runtime/ishtar.vm/__builtin/B_App.cs b/runtime/ishtar.vm/__builtin/B_App.cs index 45911ac1..071db428 100644 --- a/runtime/ishtar.vm/__builtin/B_App.cs +++ b/runtime/ishtar.vm/__builtin/B_App.cs @@ -12,12 +12,12 @@ public static unsafe class B_App var gc = current->GetGC(); // TODO remove using RuntimeInformation if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - return gc.ToIshtarObject(0, current); + return gc->ToIshtarObject(0, current); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - return gc.ToIshtarObject(1, current); + return gc->ToIshtarObject(1, current); if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - return gc.ToIshtarObject(2, current); - return gc.ToIshtarObject(-1, current); + return gc->ToIshtarObject(2, current); + return gc->ToIshtarObject(-1, current); } @@ -31,7 +31,7 @@ public static unsafe class B_App ForeignFunctionInterface.StaticTypeOf(current, &exitCode, TYPE_I4); ForeignFunctionInterface.StaticValidateField(current, &exitCode, "!!value"); - current->vm.halt(IshtarMarshal.ToDotnetInt32(exitCode, current)); + current->vm->halt(IshtarMarshal.ToDotnetInt32(exitCode, current)); return null; } @@ -54,7 +54,7 @@ public static unsafe class B_App var clr_key = IshtarMarshal.ToDotnetString(key, current); var clr_value = IshtarMarshal.ToDotnetBoolean(value, current); - //current->vm.Config.Set(clr_key, clr_value); + //current->vm->Config.Set(clr_key, clr_value); return null; } diff --git a/runtime/ishtar.vm/__builtin/B_Field.cs b/runtime/ishtar.vm/__builtin/B_Field.cs index e80f911f..7f5f9224 100644 --- a/runtime/ishtar.vm/__builtin/B_Field.cs +++ b/runtime/ishtar.vm/__builtin/B_Field.cs @@ -33,14 +33,14 @@ public static unsafe class B_Field public static void InitTable(ForeignFunctionInterface ffi) { //var table = ffi.method_table; - //ffi.vm.CreateInternalMethod("i_call_Field_setValue", Public | Static | Extern, - // new VeinArgumentRef("targetObject", ffi.vm.Types.ObjectClass), + //ffi.vm->CreateInternalMethod("i_call_Field_setValue", Public | Static | Extern, + // new VeinArgumentRef("targetObject", ffi.vm->Types.ObjectClass), // new VeinArgumentRef("f", ThisClass), - // new VeinArgumentRef("value", ffi.vm.Types.ObjectClass)) + // new VeinArgumentRef("value", ffi.vm->Types.ObjectClass)) // .AsNative((delegate*)&FieldSetValue) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_Field_getValue", Public | Static | Extern, - // new VeinArgumentRef("targetObject", ffi.vm.Types.ObjectClass), + //ffi.vm->CreateInternalMethod("i_call_Field_getValue", Public | Static | Extern, + // new VeinArgumentRef("targetObject", ffi.vm->Types.ObjectClass), // new VeinArgumentRef("f", ThisClass)) // .AsNative((delegate*)&FieldGetValue) // .AddInto(table, x => x.Name); diff --git a/runtime/ishtar.vm/__builtin/B_Function.cs b/runtime/ishtar.vm/__builtin/B_Function.cs index af5c5f04..30581e39 100644 --- a/runtime/ishtar.vm/__builtin/B_Function.cs +++ b/runtime/ishtar.vm/__builtin/B_Function.cs @@ -26,16 +26,16 @@ public static unsafe class B_Function public static void InitTable(ForeignFunctionInterface ffi) { //var table = ffi.method_table; - //ffi.vm.CreateInternalMethod("i_call_Function_call", Public | Static | Extern, + //ffi.vm->CreateInternalMethod("i_call_Function_call", Public | Static | Extern, // new VeinArgumentRef("f", ThisClass), - // new VeinArgumentRef("args", ffi.vm.Types.ArrayClass)) + // new VeinArgumentRef("args", ffi.vm->Types.ArrayClass)) // .AsNative((delegate*)&Call) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_Function_create", Public | Static | Extern, - // new VeinArgumentRef("target", ffi.vm.Types.ObjectClass), - // new VeinArgumentRef("name", ffi.vm.Types.StringClass), - // new VeinArgumentRef("ignoreCase", ffi.vm.Types.BoolClass), - // new VeinArgumentRef("throwWhenFailBind", ffi.vm.Types.BoolClass) + //ffi.vm->CreateInternalMethod("i_call_Function_create", Public | Static | Extern, + // new VeinArgumentRef("target", ffi.vm->Types.ObjectClass), + // new VeinArgumentRef("name", ffi.vm->Types.StringClass), + // new VeinArgumentRef("ignoreCase", ffi.vm->Types.BoolClass), + // new VeinArgumentRef("throwWhenFailBind", ffi.vm->Types.BoolClass) // ) // .AsNative((delegate*)&Create) // .AddInto(table, x => x.Name); diff --git a/runtime/ishtar.vm/__builtin/B_GC.cs b/runtime/ishtar.vm/__builtin/B_GC.cs index e1c05f75..2c253f7a 100644 --- a/runtime/ishtar.vm/__builtin/B_GC.cs +++ b/runtime/ishtar.vm/__builtin/B_GC.cs @@ -8,12 +8,12 @@ public static unsafe class B_GC [IshtarExport(0, "i_call_GC_get_allocated")] [IshtarExportFlags(Public | Static)] public static IshtarObject* GetAllocatedBytes(CallFrame* current, IshtarObject** _) - => current->GetGC().ToIshtarObject(current->vm.GC.Stats.total_allocations, current); + => current->GetGC()->ToIshtarObject(current->vm->gc->total_allocations, current); [IshtarExport(0, "i_call_GC_get_alive_objects")] [IshtarExportFlags(Public | Static)] public static IshtarObject* GetAliveObjects(CallFrame* current, IshtarObject** _) - => current->GetGC().ToIshtarObjectT(current->vm.GC.Stats.alive_objects, current); + => current->GetGC()->ToIshtarObjectT(current->vm->gc->alive_objects, current); public static void InitTable(ForeignFunctionInterface ffi) { diff --git a/runtime/ishtar.vm/__builtin/B_IEEEConsts.cs b/runtime/ishtar.vm/__builtin/B_IEEEConsts.cs index 97d5bbd9..dcfd9218 100644 --- a/runtime/ishtar.vm/__builtin/B_IEEEConsts.cs +++ b/runtime/ishtar.vm/__builtin/B_IEEEConsts.cs @@ -9,7 +9,7 @@ public static unsafe class B_IEEEConsts [IshtarExportFlags(Public | Static)] public static IshtarObject* getHalfNaN(CallFrame* current, IshtarObject** args) { - current->vm.FastFail(WNE.MISSING_METHOD, "[B_IEEEConsts::getHalfNaN]", current); + current->vm->FastFail(WNE.MISSING_METHOD, "[B_IEEEConsts::getHalfNaN]", current); return null; } diff --git a/runtime/ishtar.vm/__builtin/B_NAPI.cs b/runtime/ishtar.vm/__builtin/B_NAPI.cs index d65a800b..3812c857 100644 --- a/runtime/ishtar.vm/__builtin/B_NAPI.cs +++ b/runtime/ishtar.vm/__builtin/B_NAPI.cs @@ -32,7 +32,7 @@ public static unsafe class B_NAPI // return IshtarObject.NullPointer; //} - //var result = current.vm.NativeStorage.TryLoad(libFile, out var h); + //var result = current.vm->NativeStorage.TryLoad(libFile, out var h); //if (!result) //{ @@ -42,7 +42,7 @@ public static unsafe class B_NAPI //var handleClass = KnowTypes.VeinLang.Native.NativeHandle(current); - //var handleObj = current.vm.GC.AllocObject(handleClass, current); + //var handleObj = current.vm->gc.AllocObject(handleClass, current); //var wrapper = new KnowTypes.WrappedTypes.S_NativeHandle(handleObj, current); @@ -55,7 +55,7 @@ public static unsafe class B_NAPI public static void InitTable(ForeignFunctionInterface ffi) { //var table = ffi.method_table; - //ffi.vm.CreateInternalMethod("i_call_NAPI_LoadNative", Public | Static | Extern) + //ffi.vm->CreateInternalMethod("i_call_NAPI_LoadNative", Public | Static | Extern) // .AsNative((delegate*)&LoadNativeLibrary) // .AddInto(table, x => x.Name); } diff --git a/runtime/ishtar.vm/__builtin/B_Out.cs b/runtime/ishtar.vm/__builtin/B_Out.cs index df17a8fd..67794831 100644 --- a/runtime/ishtar.vm/__builtin/B_Out.cs +++ b/runtime/ishtar.vm/__builtin/B_Out.cs @@ -25,21 +25,21 @@ public static unsafe class B_Out IshtarMarshal.ToDotnetString(arg1, current) : IshtarMarshal.ToDotnetString(IshtarMarshal.ToIshtarString(arg1, current), current); - current->vm.trace.console_std_write(str); + current->vm->trace.console_std_write(str); return null; } [IshtarExport(0, "@_readline")] [IshtarExportFlags(Public | Static)] public static IshtarObject* FReadLine(CallFrame* current, IshtarObject** args) - => current->GetGC().ToIshtarObject(In.ReadLine(), current); + => current->GetGC()->ToIshtarObject(In.ReadLine(), current); public static void InitTable(ForeignFunctionInterface ffi) { ffi.Add("@_println", Public | Static | Extern, TYPE_VOID, ("val", TYPE_OBJECT)) ->AsNative((delegate*)&FPrintLn_Object); - ffi.Add("@_readline", Public | Static | Extern, TYPE_STRING.AsRuntimeClass(ffi.vm.Types)) + ffi.Add("@_readline", Public | Static | Extern, TYPE_STRING.AsRuntimeClass(ffi.vm->Types)) ->AsNative((delegate*)&FReadLine); } } diff --git a/runtime/ishtar.vm/__builtin/B_String.cs b/runtime/ishtar.vm/__builtin/B_String.cs index 82611317..403f4788 100644 --- a/runtime/ishtar.vm/__builtin/B_String.cs +++ b/runtime/ishtar.vm/__builtin/B_String.cs @@ -77,7 +77,7 @@ public static void InitTable(ForeignFunctionInterface ffi) var result = string.Format(template, dotnet_arr); - return gc.ToIshtarObject(result, frame); + return gc->ToIshtarObject(result, frame); } @@ -100,7 +100,7 @@ public static void InitTable(ForeignFunctionInterface ffi) var result = string.Concat(str1, str2); - return gc.ToIshtarObject(result, frame); + return gc->ToIshtarObject(result, frame); } @@ -123,7 +123,7 @@ public static void InitTable(ForeignFunctionInterface ffi) var result = str1.Contains(str2); - return gc.ToIshtarObject(result, frame); + return gc->ToIshtarObject(result, frame); } [IshtarExportFlags(Private | Static)] @@ -144,7 +144,7 @@ public static void InitTable(ForeignFunctionInterface ffi) var result = str1.Equals(str2); - return gc.ToIshtarObject(result, frame); + return gc->ToIshtarObject(result, frame); } public static IshtarObject* TemplateFunctionApply(CallFrame* frame, IshtarObject** args, Func apply) @@ -158,7 +158,7 @@ public static void InitTable(ForeignFunctionInterface ffi) var result = apply(clr_str); - return gc.ToIshtarObject(result, frame); + return gc->ToIshtarObject(result, frame); } diff --git a/runtime/ishtar.vm/__builtin/B_StringBuilder.cs b/runtime/ishtar.vm/__builtin/B_StringBuilder.cs index e1bf49b6..0a1c4497 100644 --- a/runtime/ishtar.vm/__builtin/B_StringBuilder.cs +++ b/runtime/ishtar.vm/__builtin/B_StringBuilder.cs @@ -54,7 +54,7 @@ public unsafe static class B_StringBuilder //var gc = current.GetGC(); //ForeignFunctionInterface.StaticValidate(current, &arg1); //arg1->vtable[@class_1.Field["!!buffer"].vtable_offset] = - // gc.AllocStatic(); + // gc->AllocStatic(); return null; } @@ -68,7 +68,7 @@ public unsafe static class B_StringBuilder //var buffer = (ImmortalObject*)arg1->vtable[@class_1.Field["!!buffer"].vtable_offset]; //buffer->Value.Clear(); //var gc = current.GetGC(); - //gc.FreeStatic(buffer); + //gc->FreeStatic(buffer); return null; } @@ -82,40 +82,40 @@ public unsafe static class B_StringBuilder //var gc = current.GetGC(); //ForeignFunctionInterface.StaticValidate(current, &arg1); //var buffer = (ImmortalObject*)arg1->vtable[@class_1.Field["!!buffer"].vtable_offset]; - //return gc.ToIshtarObject(buffer->Value.ToString(), current); + //return gc->ToIshtarObject(buffer->Value.ToString(), current); } public static void InitTable(ForeignFunctionInterface ffi) { - //ffi.vm.CreateInternalMethod("i_call_StringBuilder_append", Public | Static | Extern, - // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm.Types->ObjectClass)) + //ffi.vm->CreateInternalMethod("i_call_StringBuilder_append", Public | Static | Extern, + // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm->Types->ObjectClass)) // .AsNative((delegate*)&Append) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_StringBuilder_append", Public | Static | Extern, - // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm.Types.ValueTypeClass)) + //ffi.vm->CreateInternalMethod("i_call_StringBuilder_append", Public | Static | Extern, + // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm->Types.ValueTypeClass)) // .AsNative((delegate*)&Append) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_StringBuilder_appendLine", Public | Static | Extern, - // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm.Types.ObjectClass)) + //ffi.vm->CreateInternalMethod("i_call_StringBuilder_appendLine", Public | Static | Extern, + // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm->Types.ObjectClass)) // .AsNative((delegate*)&AppendLine) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_StringBuilder_appendLine", Public | Static | Extern, - // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm.Types.ValueTypeClass)) + //ffi.vm->CreateInternalMethod("i_call_StringBuilder_appendLine", Public | Static | Extern, + // new VeinArgumentRef("_this_", ThisClass), new VeinArgumentRef("value", ffi.vm->Types.ValueTypeClass)) // .AsNative((delegate*)&AppendLine) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_StringBuilder_init_buffer", Public | Static | Extern, + //ffi.vm->CreateInternalMethod("i_call_StringBuilder_init_buffer", Public | Static | Extern, // new VeinArgumentRef("_this_", ThisClass)) // .AsNative((delegate*)&InitBuffer) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_StringBuilder_clear_buffer", Public | Static | Extern, + //ffi.vm->CreateInternalMethod("i_call_StringBuilder_clear_buffer", Public | Static | Extern, // new VeinArgumentRef("_this_", ThisClass)) // .AsNative((delegate*)&ClearBuffer) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("i_call_StringBuilder_toString", Public | Static | Extern, + //ffi.vm->CreateInternalMethod("i_call_StringBuilder_toString", Public | Static | Extern, // new VeinArgumentRef("_this_", ThisClass)) // .AsNative((delegate*)&ToString) // .AddInto(table, x => x.Name); diff --git a/runtime/ishtar.vm/__builtin/B_Sys.cs b/runtime/ishtar.vm/__builtin/B_Sys.cs index b1c5e6a7..a1d4412c 100644 --- a/runtime/ishtar.vm/__builtin/B_Sys.cs +++ b/runtime/ishtar.vm/__builtin/B_Sys.cs @@ -31,18 +31,18 @@ public static unsafe class B_Sys [IshtarExport(0, "@queryPerformanceCounter")] [IshtarExportFlags(Public | Static)] public static IshtarObject* QueryPerformanceCounter(CallFrame* current, IshtarObject** _) - => current->GetGC().ToIshtarObject(Stopwatch.GetTimestamp(), current); + => current->GetGC()->ToIshtarObject(Stopwatch.GetTimestamp(), current); public static void InitTable(ForeignFunctionInterface ffi) { - //ffi.Add(ffi.vm.CreateInternalMethod("@value2string", Public | Static | Extern, - // new VeinArgumentRef("value", ffi.vm.Types->ValueTypeClass)) + //ffi.Add(ffi.vm->CreateInternalMethod("@value2string", Public | Static | Extern, + // new VeinArgumentRef("value", ffi.vm->Types->ValueTypeClass)) // ->AsNative((delegate*)&ValueToString)); - //ffi.vm.CreateInternalMethod("@object2string", Public | Static | Extern, - // new VeinArgumentRef("value", ffi.vm.Types.ObjectClass)) + //ffi.vm->CreateInternalMethod("@object2string", Public | Static | Extern, + // new VeinArgumentRef("value", ffi.vm->Types.ObjectClass)) // .AsNative((delegate*)&ObjectToString) // .AddInto(table, x => x.Name); - //ffi.vm.CreateInternalMethod("@queryPerformanceCounter", Public | Static | Extern) + //ffi.vm->CreateInternalMethod("@queryPerformanceCounter", Public | Static | Extern) // .AsNative((delegate*)&QueryPerformanceCounter) // .AddInto(table, x => x.Name); } diff --git a/runtime/ishtar.vm/__builtin/B_Threading.cs b/runtime/ishtar.vm/__builtin/B_Threading.cs index 8439cfbe..875dcfcb 100644 --- a/runtime/ishtar.vm/__builtin/B_Threading.cs +++ b/runtime/ishtar.vm/__builtin/B_Threading.cs @@ -4,12 +4,15 @@ namespace ishtar; using libuv; using static IshtarMath; + public static unsafe class B_Threading { private static RuntimeIshtarClass* getThreadClass(CallFrame* current) { - var threadTypeName = current->vm.Vault.GlobalFindTypeName("[std]::std::Thread"); - var result = current->vm.Vault.GlobalFindType(threadTypeName, true, true); + var vault = AppVault.GetVault(current->vm); + + var threadTypeName = vault.GlobalFindTypeName("[std]::std::Thread"); + var result = vault.GlobalFindType(threadTypeName, true, true); return result; } @@ -19,11 +22,11 @@ public static unsafe class B_Threading var fnBox = args[0]; var clazz = fnBox->clazz; - var scopePointer = fnBox->vtable[clazz->Field["_scope"]->vtable_offset]; - var fnPointer = fnBox->vtable[clazz->Field["_fn"]->vtable_offset]; + var proxy = new Vein_ClosureDelegate(fnBox); + - var isVolatile = scopePointer == null; - var metadataRef = (rawval*)fnPointer; + var isVolatile = proxy.IsVolatile; + var metadataRef = proxy.Function; current->assert(metadataRef->type == VeinRawCode.ISHTAR_METHOD, WNE.TYPE_MISMATCH); @@ -35,10 +38,10 @@ public static unsafe class B_Threading throw null; var type = getThreadClass(current); - var threadObj = current->vm.GC.AllocObject(type, current); + var threadObj = current->vm->gc->AllocObject(type, current); threadObj->vtable[type->Field["_fn"]->vtable_offset] = fnBox; - threadObj->vtable[type->Field["_threadRef"]->vtable_offset] = current->vm.threading.CreateThread(childFrame); + threadObj->vtable[type->Field["_threadRef"]->vtable_offset] = current->vm->threading.CreateThread(childFrame); return threadObj; } diff --git a/runtime/ishtar.vm/__builtin/B_Type.cs b/runtime/ishtar.vm/__builtin/B_Type.cs index 33500e41..d21e357a 100644 --- a/runtime/ishtar.vm/__builtin/B_Type.cs +++ b/runtime/ishtar.vm/__builtin/B_Type.cs @@ -4,64 +4,64 @@ namespace ishtar; using static vein.runtime.MethodFlags; public static unsafe class B_Type { - [IshtarExport(1, "i_call_Type_findByName")] - [IshtarExportFlags(Public | Static)] - public static IshtarObject* FindByName(CallFrame* current, IshtarObject** args) - { - var arg1 = args[0]; - var vault = current->vm.Vault; - var gc = current->GetGC(); + //[IshtarExport(1, "i_call_Type_findByName")] + //[IshtarExportFlags(Public | Static)] + //public static IshtarObject* FindByName(CallFrame* current, IshtarObject** args) + //{ + // var arg1 = args[0]; + // var vault = current->vm->Vault; + // var gc = current->GetGC(); - ForeignFunctionInterface.StaticValidate(current, &arg1); - ForeignFunctionInterface.StaticTypeOf(current, &arg1, VeinTypeCode.TYPE_STRING); + // ForeignFunctionInterface.StaticValidate(current, &arg1); + // ForeignFunctionInterface.StaticTypeOf(current, &arg1, VeinTypeCode.TYPE_STRING); - var name = IshtarMarshal.ToDotnetString(arg1, current); + // var name = IshtarMarshal.ToDotnetString(arg1, current); - var results = vault.GlobalFindType(name); - if (results.Length == 0) - { - current->ThrowException(KnowTypes.TypeNotFoundFault(current), $"'{name}' not found."); - return null; - } + // var results = vault.GlobalFindType(name); + // if (results.Length == 0) + // { + // current->ThrowException(KnowTypes.TypeNotFoundFault(current), $"'{name}' not found."); + // return null; + // } - if (results.Length > 1) - { - // todo, add info about all types - current->ThrowException(KnowTypes.MultipleTypeFoundFault(current), $"Multiple detected '{name}' types."); - return null; - } + // if (results.Length > 1) + // { + // // todo, add info about all types + // current->ThrowException(KnowTypes.MultipleTypeFoundFault(current), $"Multiple detected '{name}' types."); + // return null; + // } - var result = results[0]; + // var result = results[0]; - return gc.AllocTypeInfoObject(result, current); - } + // return gc->AllocTypeInfoObject(result, current); + //} - [IshtarExport(1, "i_call_Type_findField")] - [IshtarExportFlags(Public | Static)] - public static IshtarObject* FindField(CallFrame* current, IshtarObject** args) - { - var arg1 = args[0]; - var arg2 = args[1]; + //[IshtarExport(1, "i_call_Type_findField")] + //[IshtarExportFlags(Public | Static)] + //public static IshtarObject* FindField(CallFrame* current, IshtarObject** args) + //{ + // var arg1 = args[0]; + // var arg2 = args[1]; - ForeignFunctionInterface.StaticValidate(current, &arg1); - ForeignFunctionInterface.StaticValidate(current, &arg2); - ForeignFunctionInterface.StaticTypeOf(current, &arg2, VeinTypeCode.TYPE_STRING); + // ForeignFunctionInterface.StaticValidate(current, &arg1); + // ForeignFunctionInterface.StaticValidate(current, &arg2); + // ForeignFunctionInterface.StaticTypeOf(current, &arg2, VeinTypeCode.TYPE_STRING); - current->ThrowException(KnowTypes.PlatformIsNotSupportFault(current)); + // current->ThrowException(KnowTypes.PlatformIsNotSupportFault(current)); - return null; - } + // return null; + //} public static void InitTable(ForeignFunctionInterface ffi) { - //ffi.Add(ffi.vm.CreateInternalMethod("i_call_Type_findByName", Public | Static | Extern, + //ffi.Add(ffi.vm->CreateInternalMethod("i_call_Type_findByName", Public | Static | Extern, // ("name", VeinTypeCode.TYPE_STRING)) // ->AsNative((delegate*)&FindByName)); - //ffi.Add(ffi.vm.CreateInternalMethod("i_call_Type_findField", Public | Static | Extern, + //ffi.Add(ffi.vm->CreateInternalMethod("i_call_Type_findField", Public | Static | Extern, // new VeinArgumentRef("type", ThisClass), ("name", VeinTypeCode.TYPE_STRING)) // .AsNative((delegate*)&FindField)); - //ffi.vm.CreateInternalMethod("i_call_Type_findMethod", Public | Static | Extern, - // new VeinArgumentRef("type", ThisClass), new VeinArgumentRef("name", ffi.vm.Types.StringClass)) + //ffi.vm->CreateInternalMethod("i_call_Type_findMethod", Public | Static | Extern, + // new VeinArgumentRef("type", ThisClass), new VeinArgumentRef("name", ffi.vm->Types.StringClass)) // .AsNative((delegate*)&FindField) // .AddInto(table, x => x.Name); } diff --git a/runtime/ishtar.vm/__builtin/X_Utils.cs b/runtime/ishtar.vm/__builtin/X_Utils.cs index c49fc6c9..5f7db3c6 100644 --- a/runtime/ishtar.vm/__builtin/X_Utils.cs +++ b/runtime/ishtar.vm/__builtin/X_Utils.cs @@ -7,7 +7,7 @@ public static unsafe class X_Utils //[IshtarExportFlags(Public | Static)] //public static IshtarObject* BumpModulesTypes(CallFrame current, IshtarObject** args) //{ - // foreach (var module in current.vm.Vault.Modules) + // foreach (var module in current.vm->Vault.Modules) // { // Console.ForegroundColor = ConsoleColor.Green; // Console.WriteLine($"#module '{module->Name}'\n"); @@ -34,10 +34,10 @@ public static unsafe class X_Utils //public static void InitTable(ForeignFunctionInterface ffi) //{ // var table = ffi.method_table; - // ffi.vm.CreateInternalMethod("vein::ishtar::graph::bump", Public | Static | Extern) + // ffi.vm->CreateInternalMethod("vein::ishtar::graph::bump", Public | Static | Extern) // .AsNative((delegate*)&BumpModulesTypes) // .AddInto(table, x => x.Name); - // ffi.vm.CreateInternalMethod("vein::ishtar::debugger::break", Public | Static | Extern) + // ffi.vm->CreateInternalMethod("vein::ishtar::debugger::break", Public | Static | Extern) // .AsNative((delegate*)&DebuggerBreak) // .AddInto(table, x => x.Name); //} From c3f018df3abd73b6bdda1fb2e0ac6b9b492138ef Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Mon, 12 Aug 2024 05:13:27 +0300 Subject: [PATCH 2/6] update vm part to unsafe --- runtime/ishtar.vm/vm.cfg.cs | 6 +- runtime/ishtar.vm/vm.entry.cs | 26 +-- runtime/ishtar.vm/vm.exec.cs | 2 +- runtime/ishtar.vm/vm.fields.cs | 39 ++-- runtime/ishtar.vm/vm.loop.cs | 334 ++++++++++++++++----------------- runtime/ishtar.vm/vm.math.cs | 4 +- runtime/ishtar.vm/vm.new.cs | 57 +++--- runtime/ishtar.vm/vm.utils.cs | 18 +- 8 files changed, 237 insertions(+), 249 deletions(-) diff --git a/runtime/ishtar.vm/vm.cfg.cs b/runtime/ishtar.vm/vm.cfg.cs index 9125e0ec..700e06bf 100644 --- a/runtime/ishtar.vm/vm.cfg.cs +++ b/runtime/ishtar.vm/vm.cfg.cs @@ -4,9 +4,9 @@ namespace ishtar; using ishtar.runtime.io.ini; using runtime.gc; -public unsafe partial class VirtualMachine +public unsafe partial struct VirtualMachine { - public static IniRoot* readBootCfg(VirtualMachineRef* @ref) + public static IniRoot* readBootCfg() { var path = ""; @@ -19,7 +19,7 @@ public unsafe partial class VirtualMachine var source = IshtarFile.readAllFile(path); - var parser = new IniParser(source, IshtarGC.CreateAllocatorWithParent(@ref)); + var parser = new IniParser(source, IshtarGC.CreateAllocatorWithParent(null)); return parser.Parse(); } diff --git a/runtime/ishtar.vm/vm.entry.cs b/runtime/ishtar.vm/vm.entry.cs index b6b0e3e9..441240e0 100644 --- a/runtime/ishtar.vm/vm.entry.cs +++ b/runtime/ishtar.vm/vm.entry.cs @@ -9,8 +9,10 @@ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) Console.OutputEncoding = Encoding.Unicode; + VirtualMachine.static_init(); + var vm = VirtualMachine.Create("app"); - var vault = vm.Vault; + var vault = vm->Vault; #if DEBUG Thread.CurrentThread.Name = $"ishtar::entry"; @@ -29,13 +31,13 @@ { if (args.Length < 1) { - vm.FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, "0x1 [module path is not passed]", vm.Frames->EntryPoint); + vm->FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, "0x1 [module path is not passed]", vm->Frames->EntryPoint); return -1; } var entry = new FileInfo(args.First()); if (!entry.Exists) { - vm.FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, $"0x2 [{entry.FullName} is not found]", vm.Frames->EntryPoint); + vm->FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, $"0x2 [{entry.FullName} is not found]", vm->Frames->EntryPoint); return -2; } vault.WorkDirectory = entry.Directory; @@ -53,7 +55,7 @@ if (entry_point is null) { - vm.FastFail(WNE.MISSING_METHOD, $"Entry point in '{module->Name}' module is not defined.", vm.Frames->EntryPoint); + vm->FastFail(WNE.MISSING_METHOD, $"Entry point in '{module->Name}' module is not defined.", vm->Frames->EntryPoint); return -280; } @@ -76,8 +78,8 @@ // IshtarSharedDebugData.DumpToFile(new FileInfo($"./modules/{x->Name}.module"), IshtarTrace.Dump(x)); //}); - vm.task_scheduler->start_threading(module); - vm.task_scheduler->execute_method(frame); + vm->task_scheduler->start_threading(module); + vm->task_scheduler->execute_method(frame); if (!frame->exception.IsDefault()) { @@ -86,7 +88,7 @@ if (exceptionClass->FindField("message") is null) { - vm.trace.error($"unhandled exception '{frame->exception.value->clazz->Name}' was thrown. \n" + + vm->trace.error($"unhandled exception '{frame->exception.value->clazz->Name}' was thrown. \n" + $"{frame->exception.GetStackTrace()}"); } else @@ -94,13 +96,13 @@ var msg = exceptionValue->vtable[exceptionClass->Field["message"]->vtable_offset]; if (msg is null) { - vm.trace.error($"unhandled exception '{frame->exception.value->clazz->Name}' was thrown. \n" + + vm->trace.error($"unhandled exception '{frame->exception.value->clazz->Name}' was thrown. \n" + $"{frame->exception.GetStackTrace()}"); } else { var message = IshtarMarshal.ToDotnetString((IshtarObject*)msg, frame); - vm.trace.error( + vm->trace.error( $""" unhandled exception '{frame->exception.value->clazz->Name}' was thrown. '{message}' @@ -111,11 +113,11 @@ unhandled exception '{frame->exception.value->clazz->Name}' was thrown. } watcher.Stop(); - vm.trace.log($"Elapsed: {watcher.Elapsed}"); + vm->trace.log($"Elapsed: {watcher.Elapsed}"); frame->Dispose(); - vm.Dispose(); + vm->Dispose(); - vm.trace.log($"Press ENTER to exit..."); + vm->trace.log($"Press ENTER to exit..."); Console.ReadKey(); return 0; diff --git a/runtime/ishtar.vm/vm.exec.cs b/runtime/ishtar.vm/vm.exec.cs index 474f8a59..f104588f 100644 --- a/runtime/ishtar.vm/vm.exec.cs +++ b/runtime/ishtar.vm/vm.exec.cs @@ -4,7 +4,7 @@ namespace ishtar; using static vein.runtime.VeinTypeCode; using static WNE; -public unsafe partial class VirtualMachine +public unsafe partial struct VirtualMachine { private void exec_method_external_native(CallFrame* frame) { diff --git a/runtime/ishtar.vm/vm.fields.cs b/runtime/ishtar.vm/vm.fields.cs index e21ceb45..66aff221 100644 --- a/runtime/ishtar.vm/vm.fields.cs +++ b/runtime/ishtar.vm/vm.fields.cs @@ -4,12 +4,19 @@ namespace ishtar; using runtime.gc; using runtime.vin; using runtime; -using vm.runtime; using llmv; +using ishtar.runtime.io.ini; [CTypeExport("vm_t")] -public unsafe struct VirtualMachineRef +public unsafe partial struct VirtualMachine : IDisposable { + public readonly RuntimeInfo runtimeInfo = new(); + public readonly VirtualMachine* @ref = self; + + public AppVault Vault => AppVault.GetVault(@ref); + public ForeignFunctionInterface FFI => Vault.FFI; + public NativeStorage NativeStorage => Vault.NativeStorage; + public InternedString* Name; public IshtarFrames* Frames; @@ -20,29 +27,9 @@ public unsafe struct VirtualMachineRef public TaskScheduler* task_scheduler; internal RuntimeIshtarModule* InternalModule; internal RuntimeIshtarClass* InternalClass; -} - -public unsafe partial class VirtualMachine : IDisposable -{ - public readonly RuntimeInfo runtimeInfo = new(); - - public VirtualMachineRef* @ref; - - public volatile NativeException CurrentException; - public volatile IWatchDog watcher; - public volatile AppVault Vault; - public volatile IshtarGC GC; - public volatile ForeignFunctionInterface FFI; - public volatile IshtarJIT Jit; - public volatile NativeStorage NativeStorage; + public IniRoot* boot_cfg; public AppConfig Config; - - public IshtarFrames* Frames => @ref->Frames; - internal IshtarTrace trace => @ref->trace; - internal LLVMContext Jitter => @ref->Jitter; - public IshtarTypes* Types => @ref->Types; - public IshtarThreading threading => @ref->threading; - public TaskScheduler* task_scheduler => @ref->task_scheduler; - internal RuntimeIshtarModule* InternalModule => @ref->InternalModule; - internal RuntimeIshtarClass* InternalClass => @ref->InternalClass; + public IshtarMasterFault* currentFault; + public IshtarWatchDog watcher; + public IshtarGC* gc; } diff --git a/runtime/ishtar.vm/vm.loop.cs b/runtime/ishtar.vm/vm.loop.cs index 882dcaf1..6a9d5466 100644 --- a/runtime/ishtar.vm/vm.loop.cs +++ b/runtime/ishtar.vm/vm.loop.cs @@ -7,11 +7,49 @@ namespace ishtar; using static OpCodeValue; using static vein.runtime.VeinTypeCode; using static WNE; -public unsafe partial class VirtualMachine : IDisposable +public unsafe partial struct VirtualMachine : IDisposable { + void ForceThrow(RuntimeIshtarClass* clazz, stackval* sp, CallFrame* invocation, string? msg = null) + { + CallFrame.FillStackTrace(invocation); + var exception = gc->AllocObject(clazz, invocation); + sp->data.p = (nint)exception; + sp->type = TYPE_CLASS; + + if (msg is null) return; + + if (clazz->FindField("message") is null) + throw new InvalidOperationException($"Class '{clazz->FullName->NameWithNS}' is not contained 'message' field."); + + exception->vtable[clazz->Field["message"]->vtable_offset] + = gc->ToIshtarObject(msg, invocation); + } + + void jump_now(uint* start, ref uint* ip, MetaMethodHeader* mh, CallFrame* invocation) + { + var labelKey = mh->labels->Get((int)*ip); + if (mh->labels_map->TryGetValue(labelKey, out var label)) + ip = start + label.pos - 1; + else + FastFail(PROTECTED_ZONE_LABEL_CORRUPT, "[jump_now] cannot find protected zone label", invocation); + } + void jump_to(int index, uint* start, ref uint* ip, MetaMethodHeader* mh, CallFrame* invocation) + { + if (mh->labels_map->TryGetValue(mh->labels->Get(index), out var label)) + ip = start + label.pos - 1; + else FastFail(WNE.PROTECTED_ZONE_LABEL_CORRUPT, "[jump_to] cannot find protected zone label", invocation); + } + uint* get_jumper(int index, uint* start, MetaMethodHeader* mh, CallFrame* invocation) + { + if (mh->labels_map->TryGetValue(mh->labels->Get(index), out var label)) + return start + label.pos - 1; + FastFail(WNE.PROTECTED_ZONE_LABEL_CORRUPT, "[get_jumper] cannot find protected zone label", invocation); + return null; + } + public void exec_method(CallFrame* invocation) { - if (!Config.DisableValidationInvocationArgs) + if (!@ref->Config.DisableValidationInvocationArgs) { var argsLen = invocation->method->ArgLength; @@ -51,45 +89,6 @@ public void exec_method(CallFrame* invocation) var end_stack = sp + mh->max_stack; uint* endfinally_ip = null; var zone = default(ProtectedZone*); - void jump_now() - { - var labelKey = mh->labels->Get((int)*ip); - if (mh->labels_map->TryGetValue(labelKey, out var label)) - ip = start + label.pos - 1; - else - FastFail(PROTECTED_ZONE_LABEL_CORRUPT, "[jump_now] cannot find protected zone label", invocation); - } - - - void jump_to(int index) - { - if (mh->labels_map->TryGetValue(mh->labels->Get(index), out var label)) - ip = start + label.pos - 1; - else FastFail(WNE.PROTECTED_ZONE_LABEL_CORRUPT, "[jump_to] cannot find protected zone label", invocation); - } - uint* get_jumper(int index) - { - if (mh->labels_map->TryGetValue(mh->labels->Get(index), out var label)) - return start + label.pos - 1; - FastFail(WNE.PROTECTED_ZONE_LABEL_CORRUPT, "[get_jumper] cannot find protected zone label", invocation); - return null; - } - - void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) - { - CallFrame.FillStackTrace(invocation); - var exception = GC.AllocObject(clazz, invocation); - sp->data.p = (nint)exception; - sp->type = TYPE_CLASS; - - if (msg is null) return; - - if (clazz->FindField("message") is null) - throw new InvalidOperationException($"Class '{clazz->FullName->NameWithNS}' is not contained 'message' field."); - - exception->vtable[clazz->Field["message"]->vtable_offset] - = GC.ToIshtarObject(msg, invocation); - } var stopwatch = new Stopwatch(); @@ -212,6 +211,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) case LDC_F4: ++ip; sp->type = TYPE_R4; + // TODO remove using Int32BitsToSingle sp->data.f_r4 = BitConverter.Int32BitsToSingle((int)(*ip)); ++ip; ++sp; @@ -223,6 +223,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) var t1 = (long)*ip; ++ip; var t2 = (long)*ip; + // TODO remove using Int64BitsToDouble sp->data.f = BitConverter.Int64BitsToDouble(t2 << 32 | t1 & 0xffffffffL); ++ip; ++sp; @@ -286,7 +287,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) var typeID = GetClass(sp->data.ui, _module, invocation); sp->type = TYPE_ARRAY; if (invocation->method->IsStatic) - sp->data.p = (nint)GC.AllocArray(typeID, size, 1, invocation); + sp->data.p = (nint)gc->AllocArray(typeID, size, 1, invocation); //else fixed (IshtarObject** node = &invocation._this_) // sp->data.p = (nint)IshtarGC.AllocArray(typeID, size, 1, node, invocation); ++sp; @@ -362,20 +363,20 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) --sp; if (@this->type == TYPE_NONE) { - ForceThrow(KnowTypes.NullPointerException(invocation)); + ForceThrow(KnowTypes.NullPointerException(invocation), sp, invocation); goto exception_handle; } //FFI.StaticValidate(invocation, @this, field.Owner); var value = sp; var this_obj = (IshtarObject*)@this->data.p; - var target_class = this_obj->clazz; - if (!field->FieldType.IsGeneric) + if (!@ref->Config.SkipValidateStfType || !field->FieldType.IsGeneric) { if (value->type != TYPE_NULL && field->FieldType.Class->TypeCode != value->type) { CallFrame.FillStackTrace(invocation); - ForceThrow(KnowTypes.IncorrectCastFault(invocation), $"Cannot cast '{value->type}' to '{field->FieldType.Class->TypeCode}', maybe invalid IL"); + ForceThrow(KnowTypes.IncorrectCastFault(invocation), sp, invocation, + $"Cannot cast '{value->type}' to '{field->FieldType.Class->TypeCode}', maybe invalid IL"); goto exception_handle; } } @@ -412,7 +413,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) if (@this->type == TYPE_NULL) { CallFrame.FillStackTrace(invocation); - ForceThrow(KnowTypes.NullPointerException(invocation)); + ForceThrow(KnowTypes.NullPointerException(invocation), sp, invocation); goto exception_handle; } //FFI.StaticValidate(invocation, @this, field.Owner); @@ -454,13 +455,13 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) var t1 = (IshtarObject*)sp->data.p; if (t1 == null) { - ForceThrow(KnowTypes.NullPointerException(invocation)); + ForceThrow(KnowTypes.NullPointerException(invocation), sp, invocation); goto exception_handle; } var r = IshtarObject.IsInstanceOf(invocation, t1, t2); if (r == null) { - ForceThrow(KnowTypes.IncorrectCastFault(invocation)); + ForceThrow(KnowTypes.IncorrectCastFault(invocation), sp, invocation); goto exception_handle; } ++sp; @@ -475,7 +476,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) if (type1IsGeneric | type2IsGeneric) { - ForceThrow(KnowTypes.IncorrectCastFault(invocation)); + ForceThrow(KnowTypes.IncorrectCastFault(invocation), sp, invocation); goto exception_handle; } @@ -484,7 +485,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) if (!fromClass->TypeCode.IsCompatibleNumber(toClass->TypeCode)) { - ForceThrow(KnowTypes.IncorrectCastFault(invocation)); + ForceThrow(KnowTypes.IncorrectCastFault(invocation), sp, invocation); goto exception_handle; } (sp - 1)->type = toClass->TypeCode; @@ -501,7 +502,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) if (*ip == (uint)SEH_LEAVE_S) { ++ip; - jump_now(); + jump_now(start, ref ip, mh, invocation); } else ip++; @@ -517,17 +518,12 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) case POP: ++ip; --sp; - if (sp->type == TYPE_CLASS) - { - var obj = ((IshtarObject*)sp->data.p); - GC.FreeObject(&obj, invocation); - } break; case THROW: --sp; if (sp->data.p == IntPtr.Zero) { - sp->data.p = (nint)GC.AllocObject(KnowTypes.NullPointerException(invocation), invocation); + sp->data.p = (nint)gc->AllocObject(KnowTypes.NullPointerException(invocation), invocation); sp->type = TYPE_CLASS; } goto exception_handle; @@ -536,7 +532,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) ++ip; sp->type = TYPE_CLASS; sp->data.p = (nint) - GC.AllocObject( + gc->AllocObject( _module->FindType(_module->GetTypeNameByIndex((int)*ip, invocation), true), invocation); ++ip; ++sp; @@ -550,7 +546,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) var method = GetMethod(tokenIdx, owner, _module, invocation); ++ip; - var raw = GC.AllocRawValue(invocation); // TODO destroy + var raw = gc->AllocRawValue(invocation); // TODO destroy raw->type = VeinRawCode.ISHTAR_METHOD; raw->data.m = method; @@ -580,7 +576,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) if (sp->type == TYPE_NULL) { - ForceThrow(KnowTypes.NullPointerException(invocation)); + ForceThrow(KnowTypes.NullPointerException(invocation), sp, invocation); goto exception_handle; } @@ -588,7 +584,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) if (raw->type == VeinRawCode.ISHTAR_ERROR) { - ForceThrow(KnowTypes.IncorrectCastFault(invocation)); + ForceThrow(KnowTypes.IncorrectCastFault(invocation), sp, invocation); goto exception_handle; } Assert(raw->type == VeinRawCode.ISHTAR_METHOD, MISSING_TYPE, "", invocation); @@ -598,48 +594,46 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) var child_frame = invocation->CreateChild(method); println($".call {method->Owner->Name}::{method->Name}"); - var method_args = GC.AllocateStack(child_frame, method->ArgLength); + var method_args = gc->AllocateStack(child_frame, method->ArgLength); for (int i = 0, y = method->ArgLength - 1; i != method->ArgLength; i++, y--) { var _a = method->Arguments->Get(i); // TODO, type eq validate --sp; -//#if DEBUG -// if (_a->Type.IsGeneric) -// println($"@@@<< {StringStorage.GetString(_a->Name, invocation)}: {StringStorage.GetString(_a->Type.TypeArg->Name, invocation)}"); -// else -// println($"@@@<< {StringStorage.GetString(_a->Name, invocation)}: {_a->Type.Class->FullName->NameWithNS}"); - -// if (Config.CallOpCodeSkipValidateArgs) -// { -// method_args[y] = *sp; -// continue; -// } -// var arg_class = _a->Type; -// if (arg_class->Name is not "Object" and not "ValueType") -// { -// var sp_obj = IshtarMarshal.Boxing(invocation, sp); - -// if (sp_obj == null) -// continue; - -// var sp_class = sp_obj->clazz; - -// if (sp_class == null) -// continue; - -// if (sp_class->ID != arg_class->ID) -// { -// if (!sp_class->IsInner(arg_class)) -// { -// FastFail(TYPE_MISMATCH, -// $"Argument '{StringStorage.GetString(_a->Name, invocation)}: {_a->Type->Name}'" + -// $" is not matched for '{method->Name}' function.", -// invocation); -// break; -// } -// } -// } -//#endif + if (!@ref->Config.CallOpCodeSkipValidateArgs) + { + println(_a->Type.IsGeneric + ? $"@@@<< {StringStorage.GetString(_a->Name, invocation)}: {StringStorage.GetString(_a->Type.TypeArg->Name, invocation)}" + : $"@@@<< {StringStorage.GetString(_a->Name, invocation)}: {_a->Type.Class->FullName->NameWithNS}"); + + if (_a->Type.IsGeneric) + continue; + var arg_class = _a->Type.Class; + + if (arg_class->Name is not "Object" and not "ValueType") + { + var sp_obj = IshtarMarshal.Boxing(invocation, sp); + + if (sp_obj == null) + continue; + + var sp_class = sp_obj->clazz; + + if (sp_class == null) + continue; + + if (sp_class->ID != arg_class->ID) + { + if (!sp_class->IsInner(arg_class)) + { + FastFail(TYPE_MISMATCH, + $"Argument '{StringStorage.GetString(_a->Name, invocation)}: {(_a->Type.IsGeneric ? StringStorage.GetString(_a->Type.TypeArg->Name, invocation) : _a->Type.Class->Name)}'" + + $" is not matched for '{method->Name}' function.", + invocation); + break; + } + } + } + } println($".arg {method->Owner->Name}::{method->Name} (argument {y} is {sp->type} type) sp: {getStackLen()}"); @@ -663,7 +657,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) sp->data.p = (nint)child_frame->exception.value; invocation->exception = child_frame->exception; - GC.FreeStack(child_frame, method_args, method->ArgLength); + gc->FreeStack(child_frame, method_args, method->ArgLength); child_frame->Dispose(); goto exception_handle; } @@ -680,9 +674,9 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) } println($".call after {method->Owner->Name}::{method->Name}, sp: {getStackLen()}"); - GC.FreeStack(child_frame, method_args, method->ArgLength); + gc->FreeStack(child_frame, method_args, method->ArgLength); child_frame->Dispose(); - GC.Collect(); + gc->Collect(); } break; case LOC_INIT: { @@ -749,51 +743,51 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) { case TYPE_I1: if (first.data.b < second.data.b) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U1: if (first.data.ub < second.data.ub) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I2: if (first.data.s < second.data.s) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U2: if (first.data.us < second.data.us) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I4: if (first.data.i < second.data.i) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U4: if (first.data.ui < second.data.ui) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I8: if (first.data.l < second.data.l) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U8: if (first.data.ul < second.data.ul) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R2: if (first.data.hf < second.data.hf) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R4: if (first.data.f_r4 < second.data.f_r4) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R8: if (first.data.f < second.data.f) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R16: if (first.data.d < second.data.d) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; default: throw new NotImplementedException(); @@ -813,52 +807,52 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) { case TYPE_I1: if (first.data.b != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U1: if (first.data.ub != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I2: if (first.data.s != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U2: if (first.data.us != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I4: case TYPE_BOOLEAN: if (first.data.i != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U4: if (first.data.ui != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I8: if (first.data.l != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U8: if (first.data.ul != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R2: if ((float)first.data.hf != 0.0f) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R4: if (first.data.f_r4 != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R8: if (first.data.f != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R16: if (first.data.d != 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; default: throw new NotImplementedException(); @@ -879,51 +873,51 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) { case TYPE_I1: if (first.data.b <= second.data.b) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U1: if (first.data.ub <= second.data.ub) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I2: if (first.data.s <= second.data.s) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U2: if (first.data.us <= second.data.us) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I4: if (first.data.i <= second.data.i) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U4: if (first.data.ui <= second.data.ui) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I8: if (first.data.l <= second.data.l) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U8: if (first.data.ul <= second.data.ul) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R2: if (first.data.hf <= second.data.hf) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R4: if (first.data.f_r4 <= second.data.f_r4) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R8: if (first.data.f <= second.data.f) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R16: if (first.data.d <= second.data.d) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; default: throw new NotImplementedException(); @@ -947,51 +941,51 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) { case TYPE_I1: if (first.data.b != second.data.b) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U1: if (first.data.ub != second.data.ub) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I2: if (first.data.s != second.data.s) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U2: if (first.data.us != second.data.us) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I4: if (first.data.i != second.data.i) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U4: if (first.data.ui != second.data.ui) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I8: if (first.data.l != second.data.l) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U8: if (first.data.ul != second.data.ul) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R2: if (first.data.hf != second.data.hf) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R4: if (first.data.f_r4 != second.data.f_r4) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R8: if (first.data.f != second.data.f) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R16: if (first.data.d != second.data.d) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; default: throw new NotImplementedException(); @@ -1003,7 +997,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) break; case JMP: ++ip; - jump_now(); + jump_now(start, ref ip, mh, invocation); break; case JMP_F: { @@ -1014,52 +1008,52 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) { case TYPE_I1: if (first.data.b == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U1: if (first.data.ub == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I2: if (first.data.s == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U2: if (first.data.us == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I4: case TYPE_BOOLEAN: if (first.data.i == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U4: if (first.data.ui == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_I8: if (first.data.l == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_U8: if (first.data.ul == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R2: if (first.data.hf == (Half)0f) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R4: if (first.data.f_r4 == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R8: if (first.data.f == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; case TYPE_R16: if (first.data.d == 0) - jump_now(); + jump_now(start, ref ip, mh, invocation); else ++ip; break; default: throw new NotImplementedException(); @@ -1119,9 +1113,9 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) case RESERVED_2: ++ip; println($"*** GC DUMP ***"); - println($"\talive_objects: {GC.Stats.alive_objects}"); - println($"\ttotal_allocations: {GC.Stats.total_allocations}"); - println($"\ttotal_bytes_requested: {GC.Stats.total_bytes_requested}"); + println($"\talive_objects: {gc->alive_objects}"); + println($"\ttotal_allocations: {gc->total_allocations}"); + println($"\ttotal_bytes_requested: {gc->total_bytes_requested}"); println($"*** END GC DUMP ***"); break; case LDC_STR: @@ -1129,7 +1123,7 @@ void ForceThrow(RuntimeIshtarClass* clazz, string? msg = null) ++ip; sp->type = TYPE_STRING; var str = _module->GetConstStringByIndex((int) *ip); - sp->data.p = (nint)GC.ToIshtarObject(str, invocation); + sp->data.p = (nint)gc->ToIshtarObject(str, invocation); ++sp; ++ip; } @@ -1156,7 +1150,7 @@ void fill_frame_exception() ip++; } - var tryEndAddr = zone != default ? get_jumper(zone->TryEndLabel) : null; + var tryEndAddr = zone != default ? get_jumper(zone->TryEndLabel, start, mh, invocation) : null; if (zone != default && tryEndAddr > ip) { @@ -1209,7 +1203,7 @@ void fill_frame_exception() if (label_addr != -1) { - jump_to(label_addr); + jump_to(label_addr, start, ref ip, mh, invocation); ++sp; } else fill_frame_exception(); diff --git a/runtime/ishtar.vm/vm.math.cs b/runtime/ishtar.vm/vm.math.cs index 35e4f3cd..4bfd31b0 100644 --- a/runtime/ishtar.vm/vm.math.cs +++ b/runtime/ishtar.vm/vm.math.cs @@ -5,7 +5,7 @@ namespace ishtar; using static OpCodeValue; using static vein.runtime.VeinTypeCode; -public unsafe partial class VirtualMachine +public unsafe partial struct VirtualMachine { public delegate void A_OperationDelegate(ref T t1, ref T t2); @@ -218,7 +218,7 @@ private void A_OP(stackval* sp, int a_t, uint* ip, CallFrame* frame) if (i2 == 0) { // TODO - FastFail(WNE.ACCESS_VIOLATION, $"YOUR JUST OPEN A BLACKHOLE!!! [DivideByZeroError]", frame); + frame->vm->FastFail(WNE.ACCESS_VIOLATION, $"YOUR JUST OPEN A BLACKHOLE!!! [DivideByZeroError]", frame); } i1 /= i2; break; diff --git a/runtime/ishtar.vm/vm.new.cs b/runtime/ishtar.vm/vm.new.cs index 9722975b..30a824fc 100644 --- a/runtime/ishtar.vm/vm.new.cs +++ b/runtime/ishtar.vm/vm.new.cs @@ -3,54 +3,59 @@ namespace ishtar; using io; using runtime.gc; using runtime.vin; -using vm.runtime; using llmv; using runtime; using static runtime.gc.BoehmGCLayout.Native; -public unsafe partial class VirtualMachine +public unsafe partial struct VirtualMachine(VirtualMachine* self) { - public static VirtualMachine Create(string name) + public static bool hasInited; + public static void static_init() { - var vm = new VirtualMachine(); - - Load(vm.runtimeInfo); + if (hasInited) + throw new NotSupportedException(); GC_set_find_leak(true); GC_set_all_interior_pointers(true); GC_set_finalizer_notifier(on_gc_finalization); GC_init(); GC_allow_register_threads(); libuv_gc_allocator.install(); + hasInited = true; + } + + public static VirtualMachine* Create(string name) + { + var vm = IshtarGC.AllocateImmortal(null); + *vm = new VirtualMachine(vm); + vm->Name = StringStorage.Intern(name, vm); + var vault = AppVault.Create(vm, name); + - vm.@ref = IshtarGC.AllocateImmortal(null); + vm->boot_cfg = readBootCfg(); - vm.Jit = new IshtarJIT(vm); - vm.Config = new AppConfig(); - vm.Vault = new AppVault(vm, name); - vm.@ref->trace = new IshtarTrace(); + vm->Config = new AppConfig(vm->@ref->boot_cfg); + vm->trace = new IshtarTrace(); - vm.trace.Setup(); + vm->trace.Setup(); - vm.@ref->Types = IshtarTypes.Create(vm.Vault); - vm.GC = new IshtarGC(vm); + vm->Types = IshtarTypes.Create(vm->Vault); + vm->gc = IshtarGC.Create(vm); - vm.@ref->InternalModule = vm.Vault.DefineModule("$ishtar$"); + vm->InternalModule = vm->Vault.DefineModule("$ishtar$"); - vm.@ref->InternalClass = vm.InternalModule->DefineClass(RuntimeQualityTypeName.New("global", "sys", "ishtar", vm.@ref->InternalModule), - vm.Types->ObjectClass); + vm->@ref->InternalClass = vm->InternalModule->DefineClass(RuntimeQualityTypeName.New("global", "sys", "ishtar", vm->@ref->InternalModule), + vm->Types->ObjectClass); - vm.@ref->Frames = IshtarFrames.Create(vm); - vm.watcher = new DefaultWatchDog(vm); + vm->Frames = IshtarFrames.Create(vm); + vm->watcher = new IshtarWatchDog(vm); - vm.NativeStorage = new NativeStorage(vm); - vm.GC.init(); + vm->@ref->Jitter = new LLVMContext(); - vm.FFI = new ForeignFunctionInterface(vm); - vm.@ref->Jitter = new LLVMContext(); + vm->@ref->threading = new IshtarThreading(vm); - vm.@ref->threading = new IshtarThreading(vm); + vm->@ref->task_scheduler = vm->threading.CreateScheduler(vm); - vm.@ref->task_scheduler = vm.threading.CreateScheduler(vm); + vault.PostInit(); return vm; } @@ -68,7 +73,7 @@ public void Dispose() InternalModule->Dispose(); IshtarGC.FreeImmortalRoot(InternalModule); - GC.Dispose(); + gc->Dispose(); Vault.Dispose(); StringStorage.Dispose(); } diff --git a/runtime/ishtar.vm/vm.utils.cs b/runtime/ishtar.vm/vm.utils.cs index 404b3de9..5856c492 100644 --- a/runtime/ishtar.vm/vm.utils.cs +++ b/runtime/ishtar.vm/vm.utils.cs @@ -3,7 +3,7 @@ namespace ishtar; using vein.runtime; using static vein.runtime.VeinTypeCode; -public unsafe partial class VirtualMachine +public unsafe partial struct VirtualMachine { public RuntimeIshtarMethod* CreateInternalMethod(string name, MethodFlags flags, params (string name, VeinTypeCode code)[] args) { @@ -32,30 +32,30 @@ public unsafe partial class VirtualMachine => InternalClass->DefineMethod(name, TYPE_VOID.AsRuntimeClass(Types), flags); public RuntimeIshtarMethod* CreateInternalMethod(string name, MethodFlags flags, params VeinArgumentRef[] args) - => InternalClass->DefineMethod(name, TYPE_VOID.AsRuntimeClass(Types), flags, RuntimeMethodArgument.Create(this, args, @ref)); + => InternalClass->DefineMethod(name, TYPE_VOID.AsRuntimeClass(Types), flags, RuntimeMethodArgument.Create(@ref, args, @ref)); public RuntimeIshtarMethod* CreateInternalMethod(string name, MethodFlags flags, RuntimeIshtarClass* returnType, params VeinArgumentRef[] args) - => InternalClass->DefineMethod(name, returnType, flags, RuntimeMethodArgument.Create(this, args, @ref)); + => InternalClass->DefineMethod(name, returnType, flags, RuntimeMethodArgument.Create(@ref, args, @ref)); public RuntimeIshtarMethod* DefineEmptySystemMethod(string name) => CreateInternalMethod(name, MethodFlags.Extern, TYPE_VOID.AsRuntimeClass(Types), Array.Empty()); - public bool HasFaulted() => CurrentException is not null; + public bool HasFaulted() => @ref->currentFault is not null; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void FastFail(WNE type, string msg, CallFrame* frame) { - watcher?.FastFail(type, msg, frame); - watcher?.ValidateLastError(); + watcher.FastFail(type, msg, frame); + watcher.ValidateLastError(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void FastFail(bool assert, WNE type, string msg, CallFrame* frame) { if (!assert) return; - watcher?.FastFail(type, msg, frame); - watcher?.ValidateLastError(); + watcher.FastFail(type, msg, frame); + watcher.ValidateLastError(); } [Conditional("DEBUG")] @@ -77,7 +77,7 @@ public static void Assert(bool conditional, WNE type, string msg, CallFrame* fra return; if (frame is null) return; - frame->vm.FastFail(type, $"static assert failed: {msg}", frame); + frame->vm->FastFail(type, $"static assert failed: {msg}", frame); } public static void GlobalPrintln(string empty) { } From 5637bc8e8299c48b88b169028d02ba8408117130 Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Mon, 12 Aug 2024 05:13:40 +0300 Subject: [PATCH 3/6] remove unused code --- runtime/ishtar.vm/runtime/IWatchDog.cs | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 runtime/ishtar.vm/runtime/IWatchDog.cs diff --git a/runtime/ishtar.vm/runtime/IWatchDog.cs b/runtime/ishtar.vm/runtime/IWatchDog.cs deleted file mode 100644 index fa151bee..00000000 --- a/runtime/ishtar.vm/runtime/IWatchDog.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace ishtar -{ - public unsafe interface IWatchDog - { - void FastFail(WNE type, string msg, CallFrame* frame = null); - void ValidateLastError(); - } -} From 63f69ea86619f8e149712f4d97c1d637298aad06 Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Mon, 12 Aug 2024 05:13:56 +0300 Subject: [PATCH 4/6] update other parts to unsafe --- .../ishtar.vm/collections/AllocatorBlock.cs | 9 + runtime/ishtar.vm/collections/NativeList.cs | 1 + runtime/ishtar.vm/ishtar.vm.csproj | 8 +- runtime/ishtar.vm/runtime/AppConfig.cs | 17 +- runtime/ishtar.vm/runtime/AppVault.cs | 243 ++++---- runtime/ishtar.vm/runtime/DefaultWatchDog.cs | 37 -- .../ishtar.vm/runtime/IAssemblyResolver.cs | 6 +- runtime/ishtar.vm/runtime/IshtarArray.cs | 4 +- runtime/ishtar.vm/runtime/IshtarFrames.cs | 16 +- runtime/ishtar.vm/runtime/IshtarMarshal.cs | 72 +-- .../ishtar.vm/runtime/IshtarMasterFault.cs | 38 ++ runtime/ishtar.vm/runtime/IshtarObject.cs | 98 +++- runtime/ishtar.vm/runtime/IshtarWatchDog.cs | 40 ++ runtime/ishtar.vm/runtime/KnowTypes.cs | 10 +- runtime/ishtar.vm/runtime/NativeException.cs | 39 -- runtime/ishtar.vm/runtime/RuntimeInfo.cs | 2 +- runtime/ishtar.vm/runtime/StringStorage.cs | 2 +- runtime/ishtar.vm/runtime/Trace.cs | 7 +- .../runtime/allocators/IshtarAllocatorPool.cs | 2 +- runtime/ishtar.vm/runtime/gc/IshtarGC.cs | 533 ++++++++---------- .../ishtar.vm/runtime/io/IshtarThreading.cs | 20 +- runtime/ishtar.vm/runtime/io/TaskScheduler.cs | 23 +- runtime/ishtar.vm/runtime/jit/ABI.cs | 8 +- runtime/ishtar.vm/runtime/jit/IshtarJIT.cs | 32 +- .../ishtar.vm/runtime/libuv_gc_allocator.cs | 2 +- runtime/ishtar.vm/runtime/stackval.cs | 12 +- .../runtime/transit/RuntimeLayerObject.cs | 2 +- .../ishtar.vm/runtime/types/S_NativeHandle.cs | 2 +- .../ishtar.vm/runtime/vin/NativeStorage.cs | 2 +- runtime/ishtar.vm/runtime/vm/CallFrame.cs | 25 +- runtime/ishtar.vm/runtime/vm/IshtarTypes.cs | 4 +- .../runtime/vm/RuntimeIshtarClass.cs | 22 +- .../runtime/vm/RuntimeIshtarField.cs | 2 +- .../runtime/vm/RuntimeIshtarMethod.cs | 8 +- .../runtime/vm/RuntimeIshtarModule.cs | 46 +- vein_lang.sln.DotSettings | 11 + 36 files changed, 760 insertions(+), 645 deletions(-) delete mode 100644 runtime/ishtar.vm/runtime/DefaultWatchDog.cs create mode 100644 runtime/ishtar.vm/runtime/IshtarMasterFault.cs create mode 100644 runtime/ishtar.vm/runtime/IshtarWatchDog.cs delete mode 100644 runtime/ishtar.vm/runtime/NativeException.cs diff --git a/runtime/ishtar.vm/collections/AllocatorBlock.cs b/runtime/ishtar.vm/collections/AllocatorBlock.cs index 16986da4..26ab82d7 100644 --- a/runtime/ishtar.vm/collections/AllocatorBlock.cs +++ b/runtime/ishtar.vm/collections/AllocatorBlock.cs @@ -17,3 +17,12 @@ public readonly unsafe struct AllocatorBlock(void* parent, public void* alloc(uint size) => alloc_with_history(size, parent); public void* alloc_primitives(uint size) => alloc_primitives_with_history(size, parent); } + + +public static unsafe class AllocatorBlockEx +{ + public static T* malloc(this AllocatorBlock allocator, uint size) where T : unmanaged + => (T*)allocator.alloc(size); + public static T* realloc(this AllocatorBlock allocator, T* data, uint size) where T : unmanaged + => (T*)allocator.realloc(data, size); +} diff --git a/runtime/ishtar.vm/collections/NativeList.cs b/runtime/ishtar.vm/collections/NativeList.cs index 4f956dae..acadf389 100644 --- a/runtime/ishtar.vm/collections/NativeList.cs +++ b/runtime/ishtar.vm/collections/NativeList.cs @@ -43,6 +43,7 @@ public NativeList(int initialCapacity, AllocatorBlock allocator) public static void Free(NativeList* list) { + if (list is null) return; var allocator = list->_allocator; list->Dispose(); allocator.free(list); diff --git a/runtime/ishtar.vm/ishtar.vm.csproj b/runtime/ishtar.vm/ishtar.vm.csproj index fce720d3..103b9099 100644 --- a/runtime/ishtar.vm/ishtar.vm.csproj +++ b/runtime/ishtar.vm/ishtar.vm.csproj @@ -7,6 +7,7 @@ $(NETCoreSdkRuntimeIdentifier) win-x64;osx-x64;osx-arm64;linux-x64;linux-arm64 false + true @@ -52,7 +53,7 @@ runtime - + @@ -80,4 +81,9 @@ + + + + + diff --git a/runtime/ishtar.vm/runtime/AppConfig.cs b/runtime/ishtar.vm/runtime/AppConfig.cs index d52a63e6..86ed77f6 100644 --- a/runtime/ishtar.vm/runtime/AppConfig.cs +++ b/runtime/ishtar.vm/runtime/AppConfig.cs @@ -1,10 +1,13 @@ -namespace ishtar.vm.runtime; +namespace ishtar.runtime; -// TODO -public struct AppConfig +using io.ini; + +public readonly unsafe struct AppConfig(IniRoot* rootCfg) { - public bool UseDebugAllocator => Environment.GetEnvironmentVariable("+vm:has_debug_allocator") is not null; - public bool DisabledFinalization => Environment.GetEnvironmentVariable("+vm:has_disabled_finalization") is not null; - public bool CallOpCodeSkipValidateArgs => Environment.GetEnvironmentVariable("+vm:skip-validate-args") is not null; - public bool DisableValidationInvocationArgs => Environment.GetEnvironmentVariable("+vm:has_disabled_validation_inv_args") is not null; + public bool UseDebugAllocator => rootCfg->GetGroup("vm").GetFlag("has_debug_allocator"); + public bool DisabledFinalization => rootCfg->GetGroup("vm").GetFlag("has_disabled_finalization"); + public bool CallOpCodeSkipValidateArgs => rootCfg->GetGroup("vm").GetFlag("skip_validate_args"); + public bool SkipValidateStfType => rootCfg->GetGroup("vm").GetFlag("skip_validate_stf_type"); + public bool DisableValidationInvocationArgs => rootCfg->GetGroup("vm").GetFlag("has_disabled_validation_inv_args"); + public bool UseConsole => rootCfg->GetGroup("vm").GetFlag("use_console"); } diff --git a/runtime/ishtar.vm/runtime/AppVault.cs b/runtime/ishtar.vm/runtime/AppVault.cs index 306c8b23..a301f0cb 100644 --- a/runtime/ishtar.vm/runtime/AppVault.cs +++ b/runtime/ishtar.vm/runtime/AppVault.cs @@ -1,153 +1,166 @@ -namespace ishtar +namespace ishtar; + +using System.Linq; +using System.Threading; +using runtime; +using vein; +using vein.runtime; +using collections; +using ishtar; +using runtime.gc; +using runtime.vin; + +public sealed unsafe class AppVault : AppVaultSync, IDisposable { - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using runtime; - using vein; - using vein.reflection; - using vein.runtime; - using collections; - using ishtar; - using runtime.gc; - - public unsafe class AppVault : AppVaultSync, IDisposable - { - public DirectoryInfo WorkDirectory { get; set; } = new("./"); + public DirectoryInfo WorkDirectory { get; set; } = new("./"); - public VirtualMachine vm { get; } - public string Name { get; } - protected virtual AssemblyResolver Resolver { get; set; } - public TokenInterlocker TokenGranted { get; } - public int ThreadID { get; } + public VirtualMachine* vm { get; } + public string Name { get; } + private AssemblyResolver Resolver { get; set; } + public TokenInterlocker TokenGranted { get; } + public int ThreadID { get; } - internal readonly NativeList* Modules; + public ForeignFunctionInterface FFI; + public NativeStorage NativeStorage; - public AppVault(VirtualMachine vm, string name) - { - this.vm = vm; - Name = name; - TokenGranted = new TokenInterlocker(this, this); - ThreadID = Thread.CurrentThread.ManagedThreadId; - Modules = IshtarGC.AllocateList(vm.@ref); - } + internal readonly NativeList* Modules; - // TODO optimization for module search (TypeName already contain module name) - public RuntimeIshtarClass* GlobalFindType(RuntimeQualityTypeName* typeName, bool findExternally = false, bool dropUnresolved = false) - { - using var enumerator = Modules->GetEnumerator(); + private AppVault(VirtualMachine* vm, string name) + { + this.vm = vm; + Name = name; + + TokenGranted = new TokenInterlocker(this, this); + ThreadID = Thread.CurrentThread.ManagedThreadId; + Modules = IshtarGC.AllocateList(vm); + virtual_machines.Add(vm->Name->ID, this); + } - while (enumerator.MoveNext()) - { - var module = (RuntimeIshtarModule*)enumerator.Current; - var r = module->FindType(typeName, findExternally, dropUnresolved); - if (r->IsUnresolved) - continue; - return r; - } - - return null; - } + public void PostInit() + { + FFI = new ForeignFunctionInterface(vm); + NativeStorage = new NativeStorage(vm); + } + public static AppVault Create(VirtualMachine* vm, string name) => new(vm, name); - public RuntimeQualityTypeName* GlobalFindTypeName(string name) - { - using var enumerator = Modules->GetEnumerator(); + private static readonly Dictionary virtual_machines = new(); - RuntimeQualityTypeName* target = null; + public static AppVault GetVault(VirtualMachine* vm) => virtual_machines[vm->Name->ID]; - while (enumerator.MoveNext()) - { - var module = (RuntimeIshtarModule*)enumerator.Current; + // TODO optimization for module search (TypeName already contain module name) + public RuntimeIshtarClass* GlobalFindType(RuntimeQualityTypeName* typeName, bool findExternally = false, bool dropUnresolved = false) + { + using var enumerator = Modules->GetEnumerator(); - module->types_table->ForEach((x, y) => - { - if (target is not null) - return; + while (enumerator.MoveNext()) + { + var module = (RuntimeIshtarModule*)enumerator.Current; + var r = module->FindType(typeName, findExternally, dropUnresolved); + if (r->IsUnresolved) + continue; + return r; + } - if (y->ToString().Equals(name)) target = y; - }); + return null; + } - if (target is not null) - return target; - } - return null; - } + public RuntimeQualityTypeName* GlobalFindTypeName(string name) + { + using var enumerator = Modules->GetEnumerator(); - public RuntimeIshtarClass*[] GlobalFindType(string name) - => throw new NotImplementedException(); + RuntimeQualityTypeName* target = null; - public RuntimeIshtarClass* GlobalFindType(RuntimeToken token) + while (enumerator.MoveNext()) { - using var enumerator = Modules->GetEnumerator(); + var module = (RuntimeIshtarModule*)enumerator.Current; - while (enumerator.MoveNext()) + module->types_table->ForEach((x, y) => { - var module = (RuntimeIshtarModule*)enumerator.Current; - var r = module->FindType(token); - if (r->IsUnresolved) - continue; - return r; - } - - return null; - } + if (target is not null) + return; - public AssemblyResolver GetResolver() - { - if (Resolver is not null) - return Resolver; - Resolver = new AssemblyResolver(this); - Resolver.Resolved += ResolverOnResolved; - ReadDependencyMetadata(); - return Resolver; + if (y->ToString().Equals(name)) target = y; + }); + + if (target is not null) + return target; } - private void ReadDependencyMetadata() - { - if (!WorkDirectory.File("dependency.links").Exists) - return; + return null; + } - foreach (var line in File.ReadAllLines(WorkDirectory.File("dependency.links").FullName) - .Select(x => new DirectoryInfo(x)) - .Where(x => x.Exists)) - Resolver.AddSearchPath(line); - } + public RuntimeIshtarClass*[] GlobalFindType(string name) + => throw new NotImplementedException(); + + public RuntimeIshtarClass* GlobalFindType(RuntimeToken token) + { + using var enumerator = Modules->GetEnumerator(); - private void ResolverOnResolved(in RuntimeIshtarModule* module) + while (enumerator.MoveNext()) { - module->ID = TokenGranted.GrantModuleID(); - Modules->Add(module); + var module = (RuntimeIshtarModule*)enumerator.Current; + var r = module->FindType(token); + if (r->IsUnresolved) + continue; + return r; } - object AppVaultSync.TokenInterlockerGuard { get; } = new(); - internal uint LastModuleID; - internal uint LastClassID; - - public void Dispose() - { - VirtualMachine.GlobalPrintln($"Disposed vault '{Name}'"); + return null; + } - Modules->ForEach(x => x->Dispose()); - Modules->Clear(); - IshtarGC.FreeList(Modules); - } + public AssemblyResolver GetResolver() + { + if (Resolver is not null) + return Resolver; + Resolver = new AssemblyResolver(this); + Resolver.Resolved += ResolverOnResolved; + ReadDependencyMetadata(); + return Resolver; + } - public RuntimeIshtarModule* DefineModule(string @internal) - { - var module = IshtarGC.AllocateImmortalRoot(); + private void ReadDependencyMetadata() + { + if (!WorkDirectory.File("dependency.links").Exists) + return; - *module = new RuntimeIshtarModule(vm.Vault, @internal, module, new IshtarVersion()); + foreach (var line in File.ReadAllLines(WorkDirectory.File("dependency.links").FullName) + .Select(x => new DirectoryInfo(x)) + .Where(x => x.Exists)) + Resolver.AddSearchPath(line); + } - return module; - } + private void ResolverOnResolved(in RuntimeIshtarModule* module) + { + module->ID = TokenGranted.GrantModuleID(); + Modules->Add(module); } + object AppVaultSync.TokenInterlockerGuard { get; } = new(); + internal uint LastModuleID; + internal uint LastClassID; + + public void Dispose() + { + VirtualMachine.GlobalPrintln($"Disposed vault '{Name}'"); + + Modules->ForEach(x => x->Dispose()); + Modules->Clear(); + IshtarGC.FreeList(Modules); + } - public interface AppVaultSync + public RuntimeIshtarModule* DefineModule(string @internal) { - object TokenInterlockerGuard { get; } + var module = IshtarGC.AllocateImmortalRoot(); + *module = new RuntimeIshtarModule(this, @internal, module, new IshtarVersion()); + + return module; } +} + +public interface AppVaultSync +{ + object TokenInterlockerGuard { get; } } diff --git a/runtime/ishtar.vm/runtime/DefaultWatchDog.cs b/runtime/ishtar.vm/runtime/DefaultWatchDog.cs deleted file mode 100644 index 22930ec9..00000000 --- a/runtime/ishtar.vm/runtime/DefaultWatchDog.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace ishtar; - -using System.Threading; - -[ExcludeFromCodeCoverage] -public unsafe class DefaultWatchDog(VirtualMachine vm) : IWatchDog -{ - private static readonly object guarder = new(); - - void IWatchDog.FastFail(WNE type, string msg, CallFrame* frame) - { - lock (guarder) - { - var result = new NativeException {code = type, msg = msg, frame = frame}; - Interlocked.Exchange(ref vm.CurrentException, result); - } - } - void IWatchDog.ValidateLastError() - { - lock (guarder) - { - if (vm.CurrentException is null) - return; - - CallFrame.FillStackTrace(vm.CurrentException.frame); - Console.ForegroundColor = ConsoleColor.Red; - var err = $"native exception was thrown.\n\t" + - $"[{vm.CurrentException.code}]\n\t" + - $"'{vm.CurrentException.msg}'"; - if (vm.CurrentException is not null && vm.CurrentException.frame is not null && !vm.CurrentException.frame->exception.IsDefault()) - err += $"\n{vm.CurrentException.frame->exception.GetStackTrace()}"; - vm.println(err); - Console.ForegroundColor = ConsoleColor.White; - vm.halt(); - } - } -} diff --git a/runtime/ishtar.vm/runtime/IAssemblyResolver.cs b/runtime/ishtar.vm/runtime/IAssemblyResolver.cs index e44dff29..9e8bca70 100644 --- a/runtime/ishtar.vm/runtime/IAssemblyResolver.cs +++ b/runtime/ishtar.vm/runtime/IAssemblyResolver.cs @@ -55,7 +55,7 @@ public override VeinModule ResolveDep(string name, Version version, IReadOnlyLis public RuntimeIshtarModule* Resolve(IshtarAssembly assembly) { var (_, code) = assembly.Sections.First(); - var deps = IshtarGC.AllocateList(Vault.vm.@ref); + var deps = IshtarGC.AllocateList(Vault.vm); var module = RuntimeIshtarModule.Read(Vault, code, deps, (s, version) => this.ResolveDep(s, version, deps)); @@ -106,7 +106,7 @@ private FileInfo FindInPaths(string name) $"\t {search_paths.Select(x => $"Path '{x}', Exist: {x.Exists}").Join("\n\t ")};"; if (files.Length != 0) text += $"\n\tfiles checked: {files.Select(x => $"{x}").Join("\n\t\t")}"; - Vault.vm.FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, text, sys_frame); + Vault.vm->FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, text, sys_frame); return null; } } @@ -114,6 +114,6 @@ private FileInfo FindInPaths(string name) protected override void debug(string s) { } - public CallFrame* sys_frame => Vault.vm.Frames->ModuleLoaderFrame; + public CallFrame* sys_frame => Vault.vm->Frames->ModuleLoaderFrame; } } diff --git a/runtime/ishtar.vm/runtime/IshtarArray.cs b/runtime/ishtar.vm/runtime/IshtarArray.cs index a7746aad..5b95d414 100644 --- a/runtime/ishtar.vm/runtime/IshtarArray.cs +++ b/runtime/ishtar.vm/runtime/IshtarArray.cs @@ -51,7 +51,7 @@ public void SetMemory(IshtarObject* obj) public IshtarObject* Get(uint index, CallFrame* frame) { if (!ElementClass->IsPrimitive) return elements[index]; - var result = frame->vm.GC.AllocObject(ElementClass, frame); + var result = frame->vm->gc->AllocObject(ElementClass, frame); var el = elements[index]; var offset = result->clazz->Field["!!value"]->vtable_offset; result->vtable[offset] = el->vtable[offset]; @@ -65,7 +65,7 @@ public void Set(uint index, IshtarObject* value, CallFrame* frame) VirtualMachine.Assert(value_class->TypeCode == ElementClass->TypeCode || value_class->IsInner(ElementClass), WNE.TYPE_MISMATCH, "Element type mismatch.", frame); if (index >= length) { - frame->vm.FastFail(WNE.OUT_OF_RANGE, $"", frame); + frame->vm->FastFail(WNE.OUT_OF_RANGE, $"", frame); return; } diff --git a/runtime/ishtar.vm/runtime/IshtarFrames.cs b/runtime/ishtar.vm/runtime/IshtarFrames.cs index 7640a016..0025f486 100644 --- a/runtime/ishtar.vm/runtime/IshtarFrames.cs +++ b/runtime/ishtar.vm/runtime/IshtarFrames.cs @@ -7,18 +7,18 @@ namespace ishtar; [CTypeExport("ishtar_frames_t")] public unsafe struct IshtarFrames { - private IshtarFrames(VirtualMachine vm) + private IshtarFrames(VirtualMachine* vm) { - EntryPoint = CallFrame.Create(vm.DefineEmptySystemMethod("ishtar_entry"), null); - ModuleLoaderFrame = CallFrame.Create(vm.DefineEmptySystemMethod("#module"), EntryPoint); - Jit = CallFrame.Create(vm.DefineEmptySystemMethod("#jit"), EntryPoint); - GarbageCollector = CallFrame.Create(vm.DefineEmptySystemMethod("#gc"), EntryPoint); - NativeLoader = CallFrame.Create(vm.DefineEmptySystemMethod("#ffi"), EntryPoint); + EntryPoint = CallFrame.Create(vm->DefineEmptySystemMethod("ishtar_entry"), null); + ModuleLoaderFrame = CallFrame.Create(vm->DefineEmptySystemMethod("#module"), EntryPoint); + Jit = CallFrame.Create(vm->DefineEmptySystemMethod("#jit"), EntryPoint); + GarbageCollector = CallFrame.Create(vm->DefineEmptySystemMethod("#gc"), EntryPoint); + NativeLoader = CallFrame.Create(vm->DefineEmptySystemMethod("#ffi"), EntryPoint); } - public static IshtarFrames* Create(VirtualMachine vm) + public static IshtarFrames* Create(VirtualMachine* vm) { - var result = IshtarGC.AllocateImmortal(vm.@ref); + var result = IshtarGC.AllocateImmortal(vm); *result = new IshtarFrames(vm); diff --git a/runtime/ishtar.vm/runtime/IshtarMarshal.cs b/runtime/ishtar.vm/runtime/IshtarMarshal.cs index 3fb466f8..fbe9be2f 100644 --- a/runtime/ishtar.vm/runtime/IshtarMarshal.cs +++ b/runtime/ishtar.vm/runtime/IshtarMarshal.cs @@ -8,14 +8,14 @@ public static unsafe class IshtarMarshal { public static IshtarObject* ToIshtarObject(this IshtarGC gc, string str, CallFrame* frame) { - var arg = gc.AllocObject(TYPE_STRING.AsRuntimeClass(gc.VM.Types), frame); + var arg = gc.AllocObject(TYPE_STRING.AsRuntimeClass(gc.VM->Types), frame); var clazz = arg->clazz; arg->vtable[clazz->Field["!!value"]->vtable_offset] = StringStorage.Intern(str, frame); return arg; } public static IshtarObject* ToIshtarObject(this IshtarGC gc, int dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_I4.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_I4.AsRuntimeClass(gc.VM->Types), frame); var clazz = obj->clazz; obj->vtable[clazz->Field["!!value"]->vtable_offset] = (int*)dotnet_value; @@ -24,7 +24,7 @@ public static unsafe class IshtarMarshal public static IshtarObject* ToIshtarObject(this IshtarGC gc, bool dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_BOOLEAN.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_BOOLEAN.AsRuntimeClass(gc.VM->Types), frame); var clazz = obj->clazz; obj->vtable[clazz->Field["!!value"]->vtable_offset] = (int*)(dotnet_value ? 1 : 0); @@ -32,7 +32,7 @@ public static unsafe class IshtarMarshal } public static IshtarObject* ToIshtarObject(this IshtarGC gc, short dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_I2.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_I2.AsRuntimeClass(gc.VM->Types), frame); var clazz = obj->clazz; obj->vtable[clazz->Field["!!value"]->vtable_offset] = (short*)dotnet_value; @@ -40,7 +40,7 @@ public static unsafe class IshtarMarshal } public static IshtarObject* ToIshtarObject(this IshtarGC gc, byte dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_I1.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_I1.AsRuntimeClass(gc.VM->Types), frame); var clazz = obj->clazz; obj->vtable[clazz->Field["!!value"]->vtable_offset] = (int*)dotnet_value; @@ -48,7 +48,7 @@ public static unsafe class IshtarMarshal } public static IshtarObject* ToIshtarObject(this IshtarGC gc, long dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_I8.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_I8.AsRuntimeClass(gc.VM->Types), frame); var clazz = obj->clazz; obj->vtable[clazz->Field["!!value"]->vtable_offset] = (long*)dotnet_value; @@ -57,7 +57,7 @@ public static unsafe class IshtarMarshal public static IshtarObject* ToIshtarObject(this IshtarGC gc, float dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_I8.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_I8.AsRuntimeClass(gc.VM->Types), frame); var clazz = obj->clazz; obj->vtable[clazz->Field["!!value"]->vtable_offset] = (int*)BitConverter.SingleToInt32Bits(dotnet_value); @@ -66,14 +66,14 @@ public static unsafe class IshtarMarshal public static IshtarObject* ToIshtarObject(this IshtarGC gc, nint dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_RAW.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_RAW.AsRuntimeClass(gc.VM->Types), frame); obj->vtable = (void**)dotnet_value; return obj; } public static IshtarObject* ToIshtarObject(this IshtarGC gc, ushort dotnet_value, CallFrame* frame) { - var obj = gc.AllocObject(TYPE_U2.AsRuntimeClass(gc.VM.Types), frame); + var obj = gc.AllocObject(TYPE_U2.AsRuntimeClass(gc.VM->Types), frame); var clazz = obj->clazz; obj->vtable[clazz->Field["!!value"]->vtable_offset] = (long*)dotnet_value; @@ -112,7 +112,7 @@ public static unsafe class IshtarMarshal case { } when typeof(X) == typeof(float): return gc.ToIshtarObject(cast(value), frame); default: - gc.VM.FastFail(WNE.TYPE_MISMATCH, + gc.VM->FastFail(WNE.TYPE_MISMATCH, $"[marshal::ToIshtarObject] converter for '{typeof(X).Name}' not support.", frame); return default; } @@ -149,7 +149,7 @@ public static unsafe class IshtarMarshal case { } when value is float: return gc.ToIshtarObject(cast(value), frame); default: - gc.VM.FastFail(WNE.TYPE_MISMATCH, + gc.VM->FastFail(WNE.TYPE_MISMATCH, $"[marshal::ToIshtarObject] converter for '{value.GetType().Name}' not support.", frame); return default; } @@ -186,7 +186,7 @@ public static X ToDotnet(IshtarObject* obj, CallFrame* frame) case { } when typeof(X) == typeof(string): return (X)(object)ToDotnetString(obj, frame); default: - frame->vm.FastFail(WNE.TYPE_MISMATCH, + frame->vm->FastFail(WNE.TYPE_MISMATCH, $"[marshal::ToDotnet] converter for '{typeof(X).Name}' not support.", frame); return default; } @@ -277,26 +277,26 @@ public static nint ToDotnetPointer(IshtarObject* obj, CallFrame* frame) public static IshtarObject* ToIshtarString(IshtarObject* obj, CallFrame* frame) => obj->clazz->TypeCode switch { - TYPE_U1 => frame->GetGC().ToIshtarObject($"{ToDotnetUInt8(obj, frame)}", frame), - TYPE_I1 => frame->GetGC().ToIshtarObject($"{ToDotnetInt8(obj, frame)}", frame), - TYPE_U2 => frame->GetGC().ToIshtarObject($"{ToDotnetUInt16(obj, frame)}", frame), - TYPE_I2 => frame->GetGC().ToIshtarObject($"{ToDotnetInt16(obj, frame)}", frame), - TYPE_U4 => frame->GetGC().ToIshtarObject($"{ToDotnetUInt32(obj, frame)}", frame), - TYPE_I4 => frame->GetGC().ToIshtarObject($"{ToDotnetInt32(obj, frame)}", frame), - TYPE_U8 => frame->GetGC().ToIshtarObject($"{ToDotnetUInt64(obj, frame)}", frame), - TYPE_I8 => frame->GetGC().ToIshtarObject($"{ToDotnetInt64(obj, frame)}", frame), - TYPE_R4 => frame->GetGC().ToIshtarObject($"{ToDotnetFloat(obj, frame)}", frame), - TYPE_BOOLEAN => frame->GetGC().ToIshtarObject($"{ToDotnetBoolean(obj, frame)}", frame), - TYPE_CHAR => frame->GetGC().ToIshtarObject($"{ToDotnetChar(obj, frame)}", frame), - TYPE_RAW => frame->GetGC().ToIshtarObject($"0x{ToDotnetPointer(obj, frame):X8}", frame), + TYPE_U1 => frame->GetGC()->ToIshtarObject($"{ToDotnetUInt8(obj, frame)}", frame), + TYPE_I1 => frame->GetGC()->ToIshtarObject($"{ToDotnetInt8(obj, frame)}", frame), + TYPE_U2 => frame->GetGC()->ToIshtarObject($"{ToDotnetUInt16(obj, frame)}", frame), + TYPE_I2 => frame->GetGC()->ToIshtarObject($"{ToDotnetInt16(obj, frame)}", frame), + TYPE_U4 => frame->GetGC()->ToIshtarObject($"{ToDotnetUInt32(obj, frame)}", frame), + TYPE_I4 => frame->GetGC()->ToIshtarObject($"{ToDotnetInt32(obj, frame)}", frame), + TYPE_U8 => frame->GetGC()->ToIshtarObject($"{ToDotnetUInt64(obj, frame)}", frame), + TYPE_I8 => frame->GetGC()->ToIshtarObject($"{ToDotnetInt64(obj, frame)}", frame), + TYPE_R4 => frame->GetGC()->ToIshtarObject($"{ToDotnetFloat(obj, frame)}", frame), + TYPE_BOOLEAN => frame->GetGC()->ToIshtarObject($"{ToDotnetBoolean(obj, frame)}", frame), + TYPE_CHAR => frame->GetGC()->ToIshtarObject($"{ToDotnetChar(obj, frame)}", frame), + TYPE_RAW => frame->GetGC()->ToIshtarObject($"0x{ToDotnetPointer(obj, frame):X8}", frame), TYPE_STRING => obj, - //TYPE_FUNCTION => frame->GetGC().ToIshtarObject(new IshtarLayerFunction(obj, frame).Name, frame), + //TYPE_FUNCTION => frame->GetGC()->ToIshtarObject(new IshtarLayerFunction(obj, frame).Name, frame), _ => ReturnDefault(nameof(ToIshtarString), $"Convert to '{obj->clazz->TypeCode}' not supported.", frame), }; private static IshtarObject* ReturnDefault(string name, string msg, CallFrame* frame) { - frame->vm.FastFail(WNE.TYPE_MISMATCH, + frame->vm->FastFail(WNE.TYPE_MISMATCH, $"[marshal::{name}] {msg}", frame); return default; } @@ -316,7 +316,7 @@ public static stackval UnBoxing(CallFrame* frame, IshtarObject* obj) if (@class->TypeCode is TYPE_NONE or > TYPE_ARRAY or < TYPE_NONE) { - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, $"Scalar value type cannot be extracted. [{@class->FullName->NameWithNS}]\n" + "Invalid memory address is possible.\n" + "Please report the problem into https://github.com/vein-lang/vein/issues", @@ -360,7 +360,7 @@ public static stackval UnBoxing(CallFrame* frame, IshtarObject* obj) val.data.f_r4 = ToDotnetFloat(obj, frame); break; case TYPE_R8 or TYPE_R2 or TYPE_R16: - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, "Unboxing operation error.\n" + $"Scalar value type '{val.type}' cannot be extracted.\n" + "Currently is not support.\n" + @@ -383,7 +383,7 @@ public static stackval LegacyBoxing(CallFrame* frame, VeinTypeCode type_code, st var val = new stackval { type = type_code }; if (type_code is TYPE_OBJECT or TYPE_CLASS or TYPE_ARRAY or TYPE_RAW or TYPE_FUNCTION or TYPE_NONE or TYPE_TOKEN or TYPE_VOID or TYPE_CHAR) { - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, $"[LegacyBoxing] Scalar value type cannot be extracted. [{type_code}]\n" + "Invalid memory address is possible.\n" + "Please report the problem into https://github.com/vein-lang/vein/issues", @@ -427,7 +427,7 @@ public static stackval LegacyBoxing(CallFrame* frame, VeinTypeCode type_code, st val.data.p = (nint)StringStorage.Intern(value, frame); break; case TYPE_R8 or TYPE_R2 or TYPE_R16: - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, "Unboxing operation error.\n" + $"Scalar value type '{val.type}' cannot be extracted.\n" + "Currently is not support.\n" + @@ -444,7 +444,7 @@ public static stackval LegacyBoxing(CallFrame* frame, VeinTypeCode type_code, st { if (p->type == TYPE_NONE) { - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, "Boxing operation error.\n" + $"p->type is NONE [{p->type}]\n" + "Invalid allocation or incorrect type setup possible.\n" + @@ -454,7 +454,7 @@ public static stackval LegacyBoxing(CallFrame* frame, VeinTypeCode type_code, st } if (p->type == TYPE_RAW) { - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, "Boxing operation error.\n" + $"p->type is RAW [{p->type}]\n" + "Cannot boxing pointer type.\n" + @@ -467,7 +467,7 @@ public static stackval LegacyBoxing(CallFrame* frame, VeinTypeCode type_code, st return (IshtarObject*)p->data.p; if (p->type is TYPE_NONE or > TYPE_ARRAY or < TYPE_NONE) { - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, "Boxing operation error.\n" + $"Scalar value type cannot be extracted. [{p->type}]\n" + "Invalid memory address is possible.\n" + @@ -477,14 +477,14 @@ public static stackval LegacyBoxing(CallFrame* frame, VeinTypeCode type_code, st } var gc = frame->GetGC(); - var clazz = p->type.AsRuntimeClass(gc.VM.Types); - var obj = gc.AllocObject(clazz, frame); + var clazz = p->type.AsRuntimeClass(gc->VM->Types); + var obj = gc->AllocObject(clazz, frame); ForeignFunctionInterface.StaticValidateField(frame, &obj, "!!value"); if (obj->vtable is null) { - frame->vm.FastFail(WNE.ACCESS_VIOLATION, + frame->vm->FastFail(WNE.ACCESS_VIOLATION, "Boxing operation error.\n" + $"vtable is null [{p->type}]\n" + "Invalid allocation or incorrect type setup possible.\n" + diff --git a/runtime/ishtar.vm/runtime/IshtarMasterFault.cs b/runtime/ishtar.vm/runtime/IshtarMasterFault.cs new file mode 100644 index 00000000..5d4cbe4a --- /dev/null +++ b/runtime/ishtar.vm/runtime/IshtarMasterFault.cs @@ -0,0 +1,38 @@ +namespace ishtar; + +public readonly unsafe struct IshtarMasterFault(WNE code, InternedString* msg, CallFrame* frame) +{ + public readonly WNE code = code; + public readonly InternedString* msg = msg; + public readonly CallFrame* frame = frame; +}; + +[CTypeExport("ishtar_error_e")] +[CEnumPrefix("ISHTAR_ERR_")] +public enum WNE +{ + NONE = 0, + MISSING_METHOD, + MISSING_FIELD, + MISSING_TYPE, + TYPE_LOAD, + TYPE_MISMATCH, + MEMBER_ACCESS, + STATE_CORRUPT, + ASSEMBLY_COULD_NOT_LOAD, + // unexpected end of executable memory. + END_EXECUTE_MEMORY, + OUT_OF_MEMORY, + ACCESS_VIOLATION, + OVERFLOW, + OUT_OF_RANGE, + NATIVE_LIBRARY_COULD_NOT_LOAD, + NATIVE_LIBRARY_SYMBOL_COULD_NOT_FOUND, + MEMORY_LEAK, + JIT_ASM_GENERATOR_TYPE_FAULT, + JIT_ASM_GENERATOR_INCORRECT_CAST, + GC_MOVED_UNMOVABLE_MEMORY, + PROTECTED_ZONE_LABEL_CORRUPT, + SEMAPHORE_FAILED, + THREAD_STATE_CORRUPTED +} diff --git a/runtime/ishtar.vm/runtime/IshtarObject.cs b/runtime/ishtar.vm/runtime/IshtarObject.cs index f90d4b26..30861fa3 100644 --- a/runtime/ishtar.vm/runtime/IshtarObject.cs +++ b/runtime/ishtar.vm/runtime/IshtarObject.cs @@ -1,5 +1,8 @@ namespace ishtar; +using LLVMSharp; +using vein.runtime; + [CTypeExport("ishtar_object_t")] public unsafe struct IshtarObject @@ -64,8 +67,101 @@ public static bool IsAssignableFrom(CallFrame* frame, RuntimeIshtarClass* c1, Ru // TODO: Array detection // TODO: Generic detection // TODO: Interfrace detection - if (c1->FullName == frame->vm.Types->ObjectClass->FullName) + if (c1->FullName == frame->vm->Types->ObjectClass->FullName) return true; return c1->IsInner(c2); } } + + +public static unsafe class IshtarObjectEx +{ + public static byte GetUInt8(this IshtarObject value) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U1, WNE.TYPE_MISMATCH, ""); + + return (byte)value.vtable[value.clazz->Field["!!value"]->vtable_offset]; + } + public static ushort GetUInt16(this IshtarObject value) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U2, WNE.TYPE_MISMATCH, ""); + + return (ushort)value.vtable[value.clazz->Field["!!value"]->vtable_offset]; + } + public static uint GetUInt32(this IshtarObject value) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U4, WNE.TYPE_MISMATCH, ""); + + return (uint)value.vtable[value.clazz->Field["!!value"]->vtable_offset]; + } + public static short GetInt16(this IshtarObject value) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_I2, WNE.TYPE_MISMATCH, ""); + + return (short)value.vtable[value.clazz->Field["!!value"]->vtable_offset]; + } + public static int GetInt32(this IshtarObject value) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_I4, WNE.TYPE_MISMATCH, ""); + + return (int)value.vtable[value.clazz->Field["!!value"]->vtable_offset]; + } + + public static ulong GetUInt64(this IshtarObject value) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U8, WNE.TYPE_MISMATCH, ""); + + return (ulong)value.vtable[value.clazz->Field["!!value"]->vtable_offset]; + } + public static long GetInt64(this IshtarObject value) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_I8, WNE.TYPE_MISMATCH, ""); + + return (long)value.vtable[value.clazz->Field["!!value"]->vtable_offset]; + } + + + public static void SetUInt8(this IshtarObject value, byte v) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U1, WNE.TYPE_MISMATCH, ""); + + value.vtable[value.clazz->Field["!!value"]->vtable_offset] = (void*)v; + } + public static void SetUInt16(this IshtarObject value, ushort v) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U2, WNE.TYPE_MISMATCH, ""); + + value.vtable[value.clazz->Field["!!value"]->vtable_offset] = (void*)v; + } + public static void SetUInt32(this IshtarObject value, uint v) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U4, WNE.TYPE_MISMATCH, ""); + + value.vtable[value.clazz->Field["!!value"]->vtable_offset] = (void*)v; + } + public static void SetUInt64(this IshtarObject value, ulong v) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_U8, WNE.TYPE_MISMATCH, ""); + + value.vtable[value.clazz->Field["!!value"]->vtable_offset] = (void*)v; + } + + public static void SetInt16(this IshtarObject value, short v) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_I2, WNE.TYPE_MISMATCH, ""); + + value.vtable[value.clazz->Field["!!value"]->vtable_offset] = (void*)v; + } + public static void SetInt32(this IshtarObject value, int v) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_I4, WNE.TYPE_MISMATCH, ""); + + value.vtable[value.clazz->Field["!!value"]->vtable_offset] = (void*)v; + } + public static void SetInt64(this IshtarObject value, long v) + { + VirtualMachine.Assert(value.clazz->TypeCode == VeinTypeCode.TYPE_I8, WNE.TYPE_MISMATCH, ""); + + value.vtable[value.clazz->Field["!!value"]->vtable_offset] = (void*)v; + } +} diff --git a/runtime/ishtar.vm/runtime/IshtarWatchDog.cs b/runtime/ishtar.vm/runtime/IshtarWatchDog.cs new file mode 100644 index 00000000..22be7ccc --- /dev/null +++ b/runtime/ishtar.vm/runtime/IshtarWatchDog.cs @@ -0,0 +1,40 @@ +namespace ishtar; + +using System.Threading; +using runtime.gc; + +[ExcludeFromCodeCoverage] +public readonly unsafe struct IshtarWatchDog(VirtualMachine* vm) +{ + private static readonly object guarder = new(); + + public void FastFail(WNE type, string msg, CallFrame* frame) + { + lock (guarder) + { + var result = IshtarGC.AllocateImmortal(frame); + *result = new (type, StringStorage.Intern(msg, frame), frame); + Interlocked.Exchange(ref Unsafe.AsRef(vm->currentFault), (nint)result); + } + } + public void ValidateLastError() + { + lock (guarder) + { + if (vm->currentFault is null) + return; + var exception = vm->currentFault; + + CallFrame.FillStackTrace(exception->frame); + Console.ForegroundColor = ConsoleColor.Red; + var err = $"native exception was thrown.\n\t" + + $"[{exception->code}]\n\t" + + $"'{StringStorage.GetStringUnsafe(exception->msg)}'"; + if (exception is not null && exception->frame is not null && !exception->frame->exception.IsDefault()) + err += $"\n{exception->frame->exception.GetStackTrace()}"; + vm->println(err); + Console.ForegroundColor = ConsoleColor.White; + vm->halt(); + } + } +} diff --git a/runtime/ishtar.vm/runtime/KnowTypes.cs b/runtime/ishtar.vm/runtime/KnowTypes.cs index 6d6e2509..f378b536 100644 --- a/runtime/ishtar.vm/runtime/KnowTypes.cs +++ b/runtime/ishtar.vm/runtime/KnowTypes.cs @@ -12,12 +12,13 @@ public static unsafe partial class KnowTypes public static QualityTypeName NullPointerExceptionTypeName = create("std", "NullPointerException", "std"); public static QualityTypeName IncorrectCastFaultTypeName = create("std", "IncorrectCastFault", "std"); + public static QualityTypeName SocketFaultTypeName = create("std", "SocketFault", "std"); public static QualityTypeName FreeImmortalObjectFaultTypeName = create("std", nameof(FreeImmortalObjectFault), "std"); public static QualityTypeName TypeNotFoundFaultTypeName = - create("std", nameof(TypeNotFoundFault), "std/reflection"); + create("std", nameof(TypeNotFoundFault), "std::reflection"); public static QualityTypeName MultipleTypeFoundFaultTypeName = - create("std", nameof(MultipleTypeFoundFault), "std/reflection"); + create("std", nameof(MultipleTypeFoundFault), "std::reflection"); public static QualityTypeName PlatformIsNotSupportFaultTypeName = create("std", nameof(PlatformIsNotSupportFault), "std"); public static QualityTypeName IshtarFault = create("std", nameof(IshtarFault), "std"); @@ -47,6 +48,9 @@ private static QualityTypeName create(string @module, string name, string @names public static RuntimeIshtarClass* NativeFault(CallFrame* frame) => findType(IshtarFault, frame); + public static RuntimeIshtarClass* SocketFault(CallFrame* frame) + => findType(SocketFaultTypeName, frame); + public static RuntimeIshtarClass* Type(CallFrame* frame) => findType(TypeInfoTypeName, frame); public static RuntimeIshtarClass* Field(CallFrame* frame) @@ -74,7 +78,7 @@ private static QualityTypeName create(string @module, string name, string @names if (t->IsUnresolved) { - frame->vm.FastFail(WNE.MISSING_TYPE, $"Cannot find '{q->NameWithNS}' bulitin type", frame); + frame->vm->FastFail(WNE.MISSING_TYPE, $"Cannot find '{q->NameWithNS}' bulitin type", frame); return null; } diff --git a/runtime/ishtar.vm/runtime/NativeException.cs b/runtime/ishtar.vm/runtime/NativeException.cs deleted file mode 100644 index 5e6f63d2..00000000 --- a/runtime/ishtar.vm/runtime/NativeException.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace ishtar -{ - public unsafe class NativeException - { - public WNE code; - public string msg; - public CallFrame* frame; - }; - - [CTypeExport("ishtar_error_e")] - [CEnumPrefix("ISHTAR_ERR_")] - public enum WNE - { - NONE = 0, - MISSING_METHOD, - MISSING_FIELD, - MISSING_TYPE, - TYPE_LOAD, - TYPE_MISMATCH, - MEMBER_ACCESS, - STATE_CORRUPT, - ASSEMBLY_COULD_NOT_LOAD, - // unexpected end of executable memory. - END_EXECUTE_MEMORY, - OUT_OF_MEMORY, - ACCESS_VIOLATION, - OVERFLOW, - OUT_OF_RANGE, - NATIVE_LIBRARY_COULD_NOT_LOAD, - NATIVE_LIBRARY_SYMBOL_COULD_NOT_FOUND, - MEMORY_LEAK, - JIT_ASM_GENERATOR_TYPE_FAULT, - JIT_ASM_GENERATOR_INCORRECT_CAST, - GC_MOVED_UNMOVABLE_MEMORY, - PROTECTED_ZONE_LABEL_CORRUPT, - SEMAPHORE_FAILED, - THREAD_STATE_CORRUPTED - } -} diff --git a/runtime/ishtar.vm/runtime/RuntimeInfo.cs b/runtime/ishtar.vm/runtime/RuntimeInfo.cs index 5f05ba88..731e1d3c 100644 --- a/runtime/ishtar.vm/runtime/RuntimeInfo.cs +++ b/runtime/ishtar.vm/runtime/RuntimeInfo.cs @@ -1,4 +1,4 @@ -namespace ishtar.vm.runtime; +namespace ishtar.runtime; public readonly struct RuntimeInfo() { diff --git a/runtime/ishtar.vm/runtime/StringStorage.cs b/runtime/ishtar.vm/runtime/StringStorage.cs index ad72b058..6b785241 100644 --- a/runtime/ishtar.vm/runtime/StringStorage.cs +++ b/runtime/ishtar.vm/runtime/StringStorage.cs @@ -49,7 +49,7 @@ public static string GetString(InternedString* p, CallFrame* frame) ForeignFunctionInterface.StaticValidate(p, frame); if (storage_l.ContainsKey((nint)p)) return storage_l[(nint)p]; - frame->vm.FastFail(WNE.ACCESS_VIOLATION, "Pointer incorrect.", frame); + frame->vm->FastFail(WNE.ACCESS_VIOLATION, "Pointer incorrect.", frame); return null; } diff --git a/runtime/ishtar.vm/runtime/Trace.cs b/runtime/ishtar.vm/runtime/Trace.cs index cab2a058..7214fee7 100644 --- a/runtime/ishtar.vm/runtime/Trace.cs +++ b/runtime/ishtar.vm/runtime/Trace.cs @@ -1,13 +1,12 @@ -namespace ishtar.vm.runtime; +namespace ishtar.runtime; using System.Text; using ishtar.runtime; -using runtime; [CTypeExport("ishtar_trace_t")] -internal readonly struct IshtarTrace() +internal readonly unsafe struct IshtarTrace(VirtualMachine* vm) { - private readonly bool useConsole = Environment.GetCommandLineArgs().Contains("--sys::log::use-console=1"); + private readonly bool useConsole = vm->Config.UseConsole; [Conditional("DEBUG")] public void Setup() diff --git a/runtime/ishtar.vm/runtime/allocators/IshtarAllocatorPool.cs b/runtime/ishtar.vm/runtime/allocators/IshtarAllocatorPool.cs index 29b4d2cf..13f5e4fb 100644 --- a/runtime/ishtar.vm/runtime/allocators/IshtarAllocatorPool.cs +++ b/runtime/ishtar.vm/runtime/allocators/IshtarAllocatorPool.cs @@ -13,7 +13,7 @@ private IIshtarAllocator GetAllocator(CallFrame* frame) if (layout is not null) return new GCLayoutAllocator(layout); - if (frame->vm.Config.UseDebugAllocator) + if (frame->vm->@ref->Config.UseDebugAllocator) return new DebugManagedAllocator(); throw new NotImplementedException(); diff --git a/runtime/ishtar.vm/runtime/gc/IshtarGC.cs b/runtime/ishtar.vm/runtime/gc/IshtarGC.cs index 21eef60a..3410ce55 100644 --- a/runtime/ishtar.vm/runtime/gc/IshtarGC.cs +++ b/runtime/ishtar.vm/runtime/gc/IshtarGC.cs @@ -2,22 +2,23 @@ namespace ishtar.runtime.gc { using allocators; using ishtar; - using System.Collections.Generic; using collections; + using libuv; using vein.runtime; using static vein.runtime.VeinTypeCode; - using libuv; + using static libuv.LibUV; - // todo replace to libuv mutex - public struct GCSync(object guarder) : IDisposable + + public unsafe struct GCSync(uv_mutex_t* g) : IDisposable { private bool lockTaken; - public static IDisposable Begin(object g) => new GCSync(g).begin(); + public static IDisposable Begin(uv_mutex_t* g) => new GCSync(g).begin(); private IDisposable begin() { - Monitor.Enter(guarder, ref lockTaken); + uv_mutex_lock(g); + lockTaken = true; return this; } @@ -25,99 +26,83 @@ public void Dispose() { if (lockTaken) { - Monitor.Exit(guarder); + uv_mutex_unlock(g); + lockTaken = false; } } - } - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void IshtarFinalizationProc(nint p, nint i); + public static uv_mutex_t* create() + { + var al = IshtarGC.AllocateImmortal(null); + var err = uv_mutex_init(al); + + if (err != UV_ERR.OK) + throw new NotSupportedException(); + + return al; + } + + public static void destroy(uv_mutex_t* handle) => uv_mutex_destroy(handle); + } // ReSharper disable once ClassTooBig - public unsafe class IshtarGC(VirtualMachine vm) : IDisposable + public unsafe struct IshtarGC(VirtualMachine* vm) : IDisposable { - public readonly GCStats Stats = new(); - private readonly LinkedList RefsHeap = new(); - private readonly LinkedList ArrayRefsHeap = new(); - private readonly LinkedList ImmortalHeap = new(); - private readonly LinkedList TemporaryHeap = new(); + public static IshtarGC* Create(VirtualMachine* v) + { + var gc = AllocateImmortal(v); + *gc = new IshtarGC(v); + + gc->mutex = GCSync.create(); + return gc; + } - private readonly LinkedList allocationTreeDebugInfos = new(); - private readonly Dictionary allocationDebugInfos = new(); - private IIshtarAllocatorPool allocatorPool; + private static readonly IIshtarAllocatorPool allocatorPool + = new IshtarAllocatorPool(gcLayout = new BoehmGCLayout()); #if BOEHM_GC - private static readonly GCLayout gcLayout = new BoehmGCLayout(); + private static readonly GCLayout gcLayout; #else private static GCLayout gcLayout = null; #error No defined GC layout #endif + public VirtualMachine* VM => vm; + private readonly bool check_memory_leak = true; - public string DebugGet() => - $"RefsHeap: {RefsHeap.Count}\n" + - $"ArrayRefsHeap: {ArrayRefsHeap.Count}\n" + - $"ImmortalHeap: {ImmortalHeap.Count}\n" + - $"TemporaryHeap: {TemporaryHeap.Count}\n"; + private uv_mutex_t* mutex; - public class GCStats - { - private ulong TotalAllocation; - private ulong TotalBytesAllocated; - - public long total_allocations - { - get => (long)TotalAllocation; - set => TotalAllocation = checked((ulong)value); - } - - public long total_bytes_requested - { - set => TotalBytesAllocated = checked((ulong)value); - get => (long)TotalBytesAllocated; - } - public ulong alive_objects; - } - - public record AllocationDebugInfo(ulong BytesAllocated, string Method, nint pointer) - { - public string Trace; + private bool is_disposed; - public void Bump() => Trace = new StackTrace(true).ToString(); - } + private ulong TotalAllocation; + private ulong TotalBytesAllocated; + public ulong alive_objects; +#if DEBUG + public static string debug_previousDisposeStackTrace; +#endif - public enum GcColor + public long total_allocations { - RED, - GREEN, - YELLOW + get => (long)TotalAllocation; + set => TotalAllocation = checked((ulong)value); } - - public void init() + public long total_bytes_requested { - if (is_inited) - throw new NotImplementedException(); - allocatorPool = new IshtarAllocatorPool(gcLayout); - - is_inited = true; + set => TotalBytesAllocated = checked((ulong)value); + get => (long)TotalBytesAllocated; } - private bool is_inited; - - public VirtualMachine VM => vm; - public bool check_memory_leak = true; - - private bool is_disposed; - public static string previousDisposeStackTrace; public void Dispose() { if (is_disposed) throw new InvalidOperationException(); is_disposed = true; - previousDisposeStackTrace = Environment.StackTrace; +#if DEBUG + debug_previousDisposeStackTrace = Environment.StackTrace; +#endif var gcHeapSizeBefore = gcLayout.get_heap_size(); var gcFreeBytesBefore = gcLayout.get_free_bytes(); var gcHeapUsageBefore = gcLayout.get_heap_usage(); @@ -126,17 +111,17 @@ public void Dispose() //var hasCollected = gcLayout.try_collect(); gcLayout.finalize_all(); - foreach (var p in RefsHeap.ToArray()) - { - FreeObject((IshtarObject*)p, VM.Frames->GarbageCollector); - } - RefsHeap.Clear(); + //foreach (var p in RefsHeap.ToArray()) + //{ + // FreeObject((IshtarObject*)p, VM.Frames->GarbageCollector); + //} + //RefsHeap.Clear(); - foreach (var p in ArrayRefsHeap.ToArray()) - { - FreeArray((IshtarArray*)p, VM.Frames->GarbageCollector); - } - ArrayRefsHeap.Clear(); + //foreach (var p in ArrayRefsHeap.ToArray()) + //{ + // FreeArray((IshtarArray*)p, VM.Frames->GarbageCollector); + //} + //ArrayRefsHeap.Clear(); //hasCollected = gcLayout.try_collect(); @@ -148,38 +133,21 @@ public void Dispose() if (gcHeapUsage.pbytes_since_gc != 0) { - vm.FastFail(WNE.MEMORY_LEAK, $"After clear all allocated memory, total_bytes_requested is not zero ({Stats.total_bytes_requested})", VM.Frames->GarbageCollector); + vm->FastFail(WNE.MEMORY_LEAK, $"After clear all allocated memory, total_bytes_requested is not zero ({total_bytes_requested})", VM->Frames->GarbageCollector); return; } } - private void InsertDebugData(AllocationDebugInfo info) - { - using var _ = GCSync.Begin(this); - allocationTreeDebugInfos.AddLast(info); - allocationDebugInfos[info.pointer] = info; - info.Bump(); - } - - private void DeleteDebugData(nint pointer) - { - using var _ = GCSync.Begin(this); - allocationTreeDebugInfos.Remove(allocationDebugInfos[pointer]); - } /// Allocating stackval of memory failed. public stackval* AllocValue(CallFrame* frame) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); var allocator = allocatorPool.Rent(out var p, AllocationKind.no_reference, frame); - Stats.total_allocations++; - Stats.total_bytes_requested += allocator.TotalSize; - - TemporaryHeap.AddLast((nint)p); - InsertDebugData(new((ulong)sizeof(stackval), - nameof(AllocValue), (nint)p)); + total_allocations++; + total_bytes_requested += allocator.TotalSize; return p; } @@ -187,16 +155,12 @@ private void DeleteDebugData(nint pointer) /// Allocating stackval of memory failed. public rawval* AllocRawValue(CallFrame* frame) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); var allocator = allocatorPool.Rent(out var p, AllocationKind.reference, frame); - Stats.total_allocations++; - Stats.total_bytes_requested += allocator.TotalSize; - - TemporaryHeap.AddLast((nint)p); - InsertDebugData(new((ulong)sizeof(rawval), - nameof(AllocValue), (nint)p)); + total_allocations++; + total_bytes_requested += allocator.TotalSize; return p; } @@ -204,35 +168,28 @@ private void DeleteDebugData(nint pointer) public stackval* AllocateStack(CallFrame* frame, int size) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); var allocator = allocatorPool.RentArray(out var p, size, frame); - vm.println($"Allocated stack '{size}' for '{frame->method->Name}'"); - - Stats.total_allocations++; - Stats.total_bytes_requested += allocator.TotalSize; - - InsertDebugData(new((ulong)allocator.TotalSize, - nameof(AllocateStack), (nint)p)); - - ImmortalHeap.AddLast((nint)p); + vm->println($"Allocated stack '{size}' for '{frame->method->Name}'"); + total_allocations++; + total_bytes_requested += allocator.TotalSize; + return p; } public void FreeStack(CallFrame* frame, stackval* stack, int size) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); - ImmortalHeap.Remove((nint)stack); - DeleteDebugData((nint)stack); - Stats.total_allocations--; - Stats.total_bytes_requested -= allocatorPool.Return(stack); + total_allocations--; + total_bytes_requested -= allocatorPool.Return(stack); } public void UnsafeAllocValueInto(RuntimeIshtarClass* @class, stackval* pointer) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); if (!@class->IsPrimitive) return; @@ -243,7 +200,7 @@ public void UnsafeAllocValueInto(RuntimeIshtarClass* @class, stackval* pointer) /// Allocating stackval of memory failed. public stackval* AllocValue(VeinClass @class, CallFrame* frame) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); if (!@class.IsPrimitive) return null; @@ -253,58 +210,76 @@ public void UnsafeAllocValueInto(RuntimeIshtarClass* @class, stackval* pointer) return p; } + public T* AllocateSystemStruct(CallFrame* frame) where T : unmanaged + { + using var _ = GCSync.Begin(mutex); + + var allocator = allocatorPool.Rent(out var p, AllocationKind.reference, frame); + + total_allocations++; + total_bytes_requested += allocator.TotalSize; + + return p; + } + + public T* AllocateUVStruct(CallFrame* frame) where T : unmanaged + { + using var _ = GCSync.Begin(mutex); + + var allocator = allocatorPool.Rent(out var p, AllocationKind.reference, frame); + + total_allocations++; + total_bytes_requested += allocator.TotalSize; + + return (T*)p; + } + public void FreeRawValue(rawval* value) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); - TemporaryHeap.Remove((nint)value); - DeleteDebugData((nint)value); - Stats.total_allocations--; - Stats.total_bytes_requested -= allocatorPool.Return(value); + total_allocations--; + total_bytes_requested -= allocatorPool.Return(value); } public void FreeValue(stackval* value) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); - TemporaryHeap.Remove((nint)value); - DeleteDebugData((nint)value); - Stats.total_allocations--; - Stats.total_bytes_requested -= allocatorPool.Return(value); + total_allocations--; + total_bytes_requested -= allocatorPool.Return(value); } public void FreeArray(IshtarArray* array, CallFrame* frame) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); - DeleteDebugData((nint)array); - ArrayRefsHeap.Remove((nint)array); - Stats.total_bytes_requested -= allocatorPool.Return(array); - Stats.total_allocations--; - Stats.alive_objects--; + total_bytes_requested -= allocatorPool.Return(array); + total_allocations--; + alive_objects--; } public IshtarArray* AllocArray(RuntimeIshtarClass* @class, ulong size, byte rank, CallFrame* frame) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); if (!@class->is_inited) throw new NotImplementedException(); if (size >= IshtarArray.MAX_SIZE) { - vm.FastFail(WNE.OVERFLOW, "", frame); + vm->FastFail(WNE.OVERFLOW, "", frame); return null; } if (rank != 1) { - vm.FastFail(WNE.TYPE_LOAD, "Currently array rank greater 1 not supported.", frame); + vm->FastFail(WNE.TYPE_LOAD, "Currently array rank greater 1 not supported.", frame); return null; } - var arr = TYPE_ARRAY.AsRuntimeClass(vm.Types); + var arr = TYPE_ARRAY.AsRuntimeClass(vm->Types); var bytes_len = @class->computed_size * size * rank; // enter critical zone @@ -318,7 +293,7 @@ public void FreeArray(IshtarArray* array, CallFrame* frame) if (arr_obj is null) { - vm.FastFail(WNE.OUT_OF_MEMORY, "", frame); + vm->FastFail(WNE.OUT_OF_MEMORY, "", frame); return null; } @@ -350,148 +325,137 @@ public void FreeArray(IshtarArray* array, CallFrame* frame) //IshtarSync.LeaveCriticalSection(ref @class.Owner.Interlocker.INIT_ARRAY_BARRIER); - InsertDebugData(new(checked((ulong)allocator.TotalSize), - nameof(AllocArray), (nint)arr_obj)); - #if DEBUG - arr_obj->__gc_id = (long)Stats.alive_objects++; + arr_obj->__gc_id = (long)alive_objects++; #else GCStats.alive_objects++; #endif - - Stats.total_bytes_requested += allocator.TotalSize; - Stats.total_allocations++; - - ArrayRefsHeap.AddLast((nint)arr_obj); + total_bytes_requested += allocator.TotalSize; + total_allocations++; return arr_obj; } - - private readonly Dictionary _types_cache = new(); - private readonly Dictionary> _fields_cache = new(); - private readonly Dictionary> _methods_cache = new(); - - + // TODO public void** AllocVTable(uint size) { var p = (void**)gcLayout.alloc((uint)(size * sizeof(void*))); if (p is null) - vm.FastFail(WNE.TYPE_LOAD, "Out of memory.", vm.Frames->GarbageCollector); + vm->FastFail(WNE.TYPE_LOAD, "Out of memory.", vm->Frames->GarbageCollector); return p; } - public IshtarObject* AllocTypeInfoObject(RuntimeIshtarClass* @class, CallFrame* frame) - { - using var _ = GCSync.Begin(this); + //public IshtarObject* AllocTypeInfoObject(RuntimeIshtarClass* @class, CallFrame* frame) + //{ + // using var _ = GCSync.Begin(this); - if (!@class->is_inited) - throw new NotImplementedException(); + // if (!@class->is_inited) + // throw new NotImplementedException(); - //IshtarSync.EnterCriticalSection(ref @class.Owner.Interlocker.INIT_TYPE_BARRIER); + // //IshtarSync.EnterCriticalSection(ref @class.Owner.Interlocker.INIT_TYPE_BARRIER); - if (_types_cache.TryGetValue(@class->runtime_token, out nint value)) - return (IshtarObject*)value; + // if (_types_cache.TryGetValue(@class->runtime_token, out nint value)) + // return (IshtarObject*)value; - var tt = KnowTypes.Type(frame); - var obj = AllocObject(tt, frame); - var gc = frame->GetGC(); + // var tt = KnowTypes.Type(frame); + // var obj = AllocObject(tt, frame); + // var gc = frame->GetGC(); - obj->flags |= GCFlags.IMMORTAL; + // obj->flags |= GCFlags.IMMORTAL; - obj->vtable[tt->Field["_unique_id"]->vtable_offset] = gc.ToIshtarObjectT(@class->runtime_token.ClassID, frame); - obj->vtable[tt->Field["_module_id"]->vtable_offset] = gc.ToIshtarObjectT(@class->runtime_token.ModuleID, frame); - obj->vtable[tt->Field["_flags"]->vtable_offset] = gc.ToIshtarObject((int)@class->Flags, frame); - obj->vtable[tt->Field["_name"]->vtable_offset] = gc.ToIshtarObject(@class->Name, frame); - obj->vtable[tt->Field["_namespace"]->vtable_offset] = gc.ToIshtarObject(@class->FullName->Namespace, frame); + // obj->vtable[tt->Field["_unique_id"]->vtable_offset] = gc->ToIshtarObjectT(@class->runtime_token.ClassID, frame); + // obj->vtable[tt->Field["_module_id"]->vtable_offset] = gc->ToIshtarObjectT(@class->runtime_token.ModuleID, frame); + // obj->vtable[tt->Field["_flags"]->vtable_offset] = gc->ToIshtarObject((int)@class->Flags, frame); + // obj->vtable[tt->Field["_name"]->vtable_offset] = gc->ToIshtarObject(@class->Name, frame); + // obj->vtable[tt->Field["_namespace"]->vtable_offset] = gc->ToIshtarObject(@class->FullName->Namespace, frame); - _types_cache[@class->runtime_token] = (nint)obj; + // _types_cache[@class->runtime_token] = (nint)obj; - //IshtarSync.LeaveCriticalSection(ref @class.Owner.Interlocker.INIT_TYPE_BARRIER); + // //IshtarSync.LeaveCriticalSection(ref @class.Owner.Interlocker.INIT_TYPE_BARRIER); - return obj; - } + // return obj; + //} - public IshtarObject* AllocFieldInfoObject(RuntimeIshtarField* field, CallFrame* frame) - { - using var _ = GCSync.Begin(this); + //public IshtarObject* AllocFieldInfoObject(RuntimeIshtarField* field, CallFrame* frame) + //{ + // using var _ = GCSync.Begin(this); - var @class = field->Owner; - if (!@class->is_inited) - throw new NotImplementedException(); + // var @class = field->Owner; + // if (!@class->is_inited) + // throw new NotImplementedException(); - var name = field->Name; - var gc = frame->GetGC(); + // var name = field->Name; + // var gc = frame->GetGC(); - //IshtarSync.EnterCriticalSection(ref @class.Owner.Interlocker.INIT_FIELD_BARRIER); + // //IshtarSync.EnterCriticalSection(ref @class.Owner.Interlocker.INIT_FIELD_BARRIER); - if (_fields_cache.ContainsKey(@class->runtime_token) && _fields_cache[@class->runtime_token].ContainsKey(name)) - return (IshtarObject*)_fields_cache[@class->runtime_token][name]; + // if (_fields_cache.ContainsKey(@class->runtime_token) && _fields_cache[@class->runtime_token].ContainsKey(name)) + // return (IshtarObject*)_fields_cache[@class->runtime_token][name]; - var tt = KnowTypes.Field(frame); - var obj = AllocObject(tt, frame); + // var tt = KnowTypes.Field(frame); + // var obj = AllocObject(tt, frame); - obj->flags |= GCFlags.IMMORTAL; + // obj->flags |= GCFlags.IMMORTAL; - var field_owner = AllocTypeInfoObject(@class, frame); + // var field_owner = AllocTypeInfoObject(@class, frame); - obj->vtable[tt->Field["_target"]->vtable_offset] = field_owner; - obj->vtable[tt->Field["_name"]->vtable_offset] = gc.ToIshtarObject(name, frame); - obj->vtable[tt->Field["_vtoffset"]->vtable_offset] = gc.ToIshtarObject((long)field->vtable_offset, frame); + // obj->vtable[tt->Field["_target"]->vtable_offset] = field_owner; + // obj->vtable[tt->Field["_name"]->vtable_offset] = gc->ToIshtarObject(name, frame); + // obj->vtable[tt->Field["_vtoffset"]->vtable_offset] = gc->ToIshtarObject((long)field->vtable_offset, frame); - if (!_fields_cache.ContainsKey(@class->runtime_token)) - _fields_cache[@class->runtime_token] = new(); - _fields_cache[@class->runtime_token][name] = (nint)obj; + // if (!_fields_cache.ContainsKey(@class->runtime_token)) + // _fields_cache[@class->runtime_token] = new(); + // _fields_cache[@class->runtime_token][name] = (nint)obj; - //IshtarSync.LeaveCriticalSection(ref @class.Owner.Interlocker.INIT_FIELD_BARRIER); + // //IshtarSync.LeaveCriticalSection(ref @class.Owner.Interlocker.INIT_FIELD_BARRIER); - return obj; - } + // return obj; + //} - public IshtarObject* AllocMethodInfoObject(RuntimeIshtarMethod* method, CallFrame* frame) - { - using var _ = GCSync.Begin(this); + //public IshtarObject* AllocMethodInfoObject(RuntimeIshtarMethod* method, CallFrame* frame) + //{ + // using var _ = GCSync.Begin(this); - var @class = method->Owner; - if (!@class->is_inited) - throw new NotImplementedException(); + // var @class = method->Owner; + // if (!@class->is_inited) + // throw new NotImplementedException(); - var key = method->Name; - var gc = frame->GetGC(); + // var key = method->Name; + // var gc = frame->GetGC(); - //IshtarSync.EnterCriticalSection(ref @class.Owner.Interlocker.INIT_METHOD_BARRIER); + // //IshtarSync.EnterCriticalSection(ref @class.Owner.Interlocker.INIT_METHOD_BARRIER); - if (_fields_cache.ContainsKey(@class->runtime_token) && _fields_cache[@class->runtime_token].ContainsKey(key)) - return (IshtarObject*)_fields_cache[@class->runtime_token][key]; + // if (_fields_cache.ContainsKey(@class->runtime_token) && _fields_cache[@class->runtime_token].ContainsKey(key)) + // return (IshtarObject*)_fields_cache[@class->runtime_token][key]; - var tt = KnowTypes.Function(frame); - var obj = AllocObject(tt, frame); + // var tt = KnowTypes.Function(frame); + // var obj = AllocObject(tt, frame); - obj->flags |= GCFlags.IMMORTAL; + // obj->flags |= GCFlags.IMMORTAL; - var method_owner = AllocTypeInfoObject(@class, frame); + // var method_owner = AllocTypeInfoObject(@class, frame); - obj->vtable[tt->Field["_target"]->vtable_offset] = method_owner; - obj->vtable[tt->Field["_name"]->vtable_offset] = gc.ToIshtarObject(method->RawName, frame); - obj->vtable[tt->Field["_quality_name"]->vtable_offset] = gc.ToIshtarObject(method->Name, frame); - obj->vtable[tt->Field["_vtoffset"]->vtable_offset] = gc.ToIshtarObject((long)method->vtable_offset, frame); + // obj->vtable[tt->Field["_target"]->vtable_offset] = method_owner; + // obj->vtable[tt->Field["_name"]->vtable_offset] = gc->ToIshtarObject(method->RawName, frame); + // obj->vtable[tt->Field["_quality_name"]->vtable_offset] = gc->ToIshtarObject(method->Name, frame); + // obj->vtable[tt->Field["_vtoffset"]->vtable_offset] = gc->ToIshtarObject((long)method->vtable_offset, frame); - if (!_methods_cache.ContainsKey(@class->runtime_token)) - _methods_cache[@class->runtime_token] = new(); - _methods_cache[@class->runtime_token][key] = (nint)obj; + // if (!_methods_cache.ContainsKey(@class->runtime_token)) + // _methods_cache[@class->runtime_token] = new(); + // _methods_cache[@class->runtime_token][key] = (nint)obj; - //IshtarSync.LeaveCriticalSection(ref @class.Owner.Interlocker.INIT_METHOD_BARRIER); + // //IshtarSync.LeaveCriticalSection(ref @class.Owner.Interlocker.INIT_METHOD_BARRIER); - return obj; - } + // return obj; + //} public IshtarObject* AllocObject(RuntimeIshtarClass* @class, CallFrame* frame) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); var allocator = allocatorPool.Rent(out var p, AllocationKind.reference, frame); @@ -507,7 +471,7 @@ public void FreeArray(IshtarArray* array, CallFrame* frame) (uint)@class->computed_size * (uint)sizeof(void*)); p->clazz = @class; p->vtable_size = (uint)@class->computed_size; - p->__gc_id = (long)Stats.alive_objects++; + p->__gc_id = (long)alive_objects++; #if DEBUG p->m1 = IshtarObject.magic1; p->m2 = IshtarObject.magic2; @@ -515,13 +479,9 @@ public void FreeArray(IshtarArray* array, CallFrame* frame) #endif @class->computed_size = @class->computed_size; - Stats.total_allocations++; - Stats.total_bytes_requested += allocator.TotalSize; - - InsertDebugData(new(checked((ulong)allocator.TotalSize), - nameof(AllocObject), (nint)p)); - RefsHeap.AddLast((nint)p); - + total_allocations++; + total_bytes_requested += allocator.TotalSize; + ObjectRegisterFinalizer(p, &_direct_finalizer, frame); return p; @@ -542,33 +502,30 @@ private static void _direct_finalizer(nint obj, nint __) } var vm = o->clazz->Owner->vm; - var gc = vm.GC; + var gc = vm->gc; - using var _ = GCSync.Begin(gc); + using var _ = GCSync.Begin(gc->mutex); - var frame = vm.Frames->GarbageCollector; + var frame = vm->Frames->GarbageCollector; - gc.ObjectRegisterFinalizer(o, null, frame); + gc->ObjectRegisterFinalizer(o, null, frame); - if (vm.Config.DisabledFinalization) + if (vm->Config.DisabledFinalization) return; var clazz = o->clazz; var finalizer = clazz->GetDefaultDtor(); - vm.println($"@@[dtor] called! for instance of {clazz->FullName->NameWithNS}"); + vm->println($"@@[dtor] called! for instance of {clazz->FullName->NameWithNS}"); if (finalizer is not null) { - vm.exec_method(frame->CreateChild(finalizer)); - vm.watcher.ValidateLastError(); + vm->exec_method(frame->CreateChild(finalizer)); + vm->watcher.ValidateLastError(); } - gc.RefsHeap.Remove((nint)o); - gc.DeleteDebugData(obj); - - gc.Stats.total_allocations--; - gc.Stats.alive_objects--; + gc->total_allocations--; + gc->alive_objects--; gcLayout.free((void**)&o); @@ -577,45 +534,40 @@ private static void _direct_finalizer(nint obj, nint __) public void FreeObject(IshtarObject* obj, CallFrame* frame) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); if (obj->IsDestroyedObject()) { gcLayout.register_finalizer_no_order(obj, null, frame); - DeleteDebugData((nint)obj); - RefsHeap.Remove((nint)obj); - Stats.total_bytes_requested -= allocatorPool.Return(obj); - Stats.total_allocations--; - Stats.alive_objects--; + total_bytes_requested -= allocatorPool.Return(obj); + total_allocations--; + alive_objects--; return; } if (!obj->IsValidObject()) { - VM.FastFail(WNE.STATE_CORRUPT, "trying free memory of invalid object", frame); + vm->FastFail(WNE.STATE_CORRUPT, "trying free memory of invalid object", frame); return; } if (obj->flags.HasFlag(GCFlags.NATIVE_REF)) { - VM.FastFail(WNE.ACCESS_VIOLATION, "trying free memory of static native object", frame); + vm->FastFail(WNE.ACCESS_VIOLATION, "trying free memory of static native object", frame); return; } gcLayout.register_finalizer_no_order(obj, null, frame); - - DeleteDebugData((nint)obj); - RefsHeap.Remove((nint)obj); - Stats.total_bytes_requested -= allocatorPool.Return(obj); - Stats.total_allocations--; - Stats.alive_objects--; + total_bytes_requested -= allocatorPool.Return(obj); + total_allocations--; + alive_objects--; gcLayout.free((void**)&obj); } public bool IsAlive(IshtarObject* obj) { - using var _ = GCSync.Begin(this); + using var _ = GCSync.Begin(mutex); return obj->IsValidObject() && gcLayout.is_marked(obj); } @@ -650,7 +602,7 @@ public void UnRegisterWeakLink(void** link, bool longLive) #region internal - private static AllocatorBlock CreateAllocatorWithParent(void* parent) => + public static AllocatorBlock CreateAllocatorWithParent(void* parent) => new(parent, &IshtarGC_Free, &IshtarGC_Realloc, &AllocateImmortal, &AllocateImmortal); private static void IshtarGC_Free(void* ptr) @@ -706,6 +658,13 @@ public static void FreeConcurrentDictionary(NativeConcurrentDictio return p; } + + public static T* AllocateUVImmortal() where T : unmanaged + { + var p = (T*)gcLayout.alloc_immortal((uint)sizeof(nint)); + return p; + } + public static void* AllocateImmortal(uint size, void* parent) { var p = gcLayout.alloc_immortal(size); @@ -753,27 +712,29 @@ public static void FreeImmortalRoot(T* ptr, int size) where T : unmanaged private static readonly Dictionary disposedImmortals = new(); public static void FreeImmortal(T* t) where T : unmanaged { - using var _ = GCSync.Begin(typeof(T)); - if (!gcLayout.isOwnerShip((void**)&t)) - { - Debug.WriteLine($"Trying free pointer without access"); - return; - } - - var stackTrace = Environment.StackTrace; - if (allocatedImmortals.Remove((nint)t)) - { - disposedImmortals[(nint)t] = stackTrace; - gcLayout.free((void**)&t); - } - else if (disposedImmortals.TryGetValue((nint)t, out var result)) + lock (typeof(T)) { - if (stackTrace.Equals(result)) + if (!gcLayout.isOwnerShip((void**)&t)) + { + Debug.WriteLine($"Trying free pointer without access"); return; - throw new TryingFreeAlreadyDisposedImmortalObject(disposedImmortals[(nint)t]); + } + + var stackTrace = Environment.StackTrace; + if (allocatedImmortals.Remove((nint)t)) + { + disposedImmortals[(nint)t] = stackTrace; + gcLayout.free((void**)&t); + } + else if (disposedImmortals.TryGetValue((nint)t, out var result)) + { + if (stackTrace.Equals(result)) + return; + throw new TryingFreeAlreadyDisposedImmortalObject(disposedImmortals[(nint)t]); + } + else + throw new BadMemoryOfImmortalObject(); } - else - throw new BadMemoryOfImmortalObject(); } #endregion diff --git a/runtime/ishtar.vm/runtime/io/IshtarThreading.cs b/runtime/ishtar.vm/runtime/io/IshtarThreading.cs index a062863f..38c22041 100644 --- a/runtime/ishtar.vm/runtime/io/IshtarThreading.cs +++ b/runtime/ishtar.vm/runtime/io/IshtarThreading.cs @@ -7,9 +7,9 @@ namespace ishtar.io; [CTypeExport("ishtar_threading_t")] -public unsafe struct IshtarThreading(VirtualMachine vm) +public unsafe struct IshtarThreading(VirtualMachine* vm) { - public NativeList* threads = IshtarGC.AllocateList(vm.@ref); + public NativeList* threads = IshtarGC.AllocateList(vm); public IshtarRawThread* CreateRawThread(RuntimeIshtarModule* mainModule, delegate* frame, string name) { @@ -29,7 +29,7 @@ public unsafe struct IshtarThreading(VirtualMachine vm) *threadContext = new IshtarThreadContext(threadId, locker); *thread = new IshtarThread(threadId, frame, threadContext); - frame->vm.println($"thread start {threadId}"); + frame->vm->println($"thread start {threadId}"); threads->Add(thread); @@ -38,13 +38,13 @@ public unsafe struct IshtarThreading(VirtualMachine vm) public static void DestroyThread(IshtarThread* thread) { - thread->callFrame->vm.println($"[thread] exit thread with status {thread->ctx->Status} {thread->threadId}"); + thread->callFrame->vm->println($"[thread] exit thread with status {thread->ctx->Status} {thread->threadId}"); uv_sem_destroy(ref thread->ctx->Locker); IshtarGC.FreeImmortal(thread->ctx); IshtarGC.FreeImmortal(thread); } - public TaskScheduler* CreateScheduler(VirtualMachine vm) => TaskScheduler.Create(vm); + public TaskScheduler* CreateScheduler(VirtualMachine* vm) => TaskScheduler.Create(vm); public void FreeScheduler(TaskScheduler* scheduler) => TaskScheduler.Free(scheduler); private static void execute(nint arg) @@ -61,16 +61,16 @@ private static void execute(nint arg) var vm = threadData->callFrame->vm; var stackbase = new GC_stack_base(); - vm.GC.get_stack_base(&stackbase); - vm.GC.register_thread(&stackbase); + vm->gc->get_stack_base(&stackbase); + vm->gc->register_thread(&stackbase); - vm.exec_method(frame); + vm->exec_method(frame); - vm.GC.unregister_thread(); + vm->gc->unregister_thread(); threadData->complete(); - vm.threading.threads->Remove(threadData); + vm->threading.threads->Remove(threadData); DestroyThread(threadData); } diff --git a/runtime/ishtar.vm/runtime/io/TaskScheduler.cs b/runtime/ishtar.vm/runtime/io/TaskScheduler.cs index b6ab1466..88df9238 100644 --- a/runtime/ishtar.vm/runtime/io/TaskScheduler.cs +++ b/runtime/ishtar.vm/runtime/io/TaskScheduler.cs @@ -16,13 +16,16 @@ public unsafe struct TaskScheduler(NativeQueue* queue) : IDisposable private readonly NativeQueue* _queue = queue; - public static TaskScheduler* Create(VirtualMachine vm) + public nint getLoop() => loop; + + + public static TaskScheduler* Create(VirtualMachine* vm) { - var scheduler = IshtarGC.AllocateImmortal(vm.@ref); + var scheduler = IshtarGC.AllocateImmortal(vm); var queue = IshtarGC.AllocateQueue(scheduler); *scheduler = new TaskScheduler(queue); - var asyncHeader = IshtarGC.AllocateImmortal(vm.@ref); + var asyncHeader = IshtarGC.AllocateImmortal(vm); scheduler->loop = uv_default_loop(); Assert(uv_async_init(scheduler->loop, (nint)asyncHeader, on_async) == 0, WNE.THREAD_STATE_CORRUPTED, "scheduler has failed create async io"); @@ -51,7 +54,7 @@ public static void on_async(nint handler) var queue = taskScheduler->_queue; while (queue->TryDequeue(out var task)) { - task->Frame->vm.exec_method(task->Frame); + task->Frame->vm->exec_method(task->Frame); uv_sem_post(ref task->Data->semaphore); } } @@ -64,7 +67,7 @@ public void execute_method(CallFrame* frame) } private void doExecute(CallFrame* frame) - => frame->vm.exec_method(frame); + => frame->vm->exec_method(frame); private void doAsyncExecute(CallFrame* frame) { @@ -106,17 +109,17 @@ static void execute_scheduler(IshtarRawThread* thread) var gcInfo = new GC_stack_base(); - vm.GC.get_stack_base(&gcInfo); + vm->gc->get_stack_base(&gcInfo); - vm.GC.register_thread(&gcInfo); + vm->gc->register_thread(&gcInfo); - vm.task_scheduler->run(); + vm->task_scheduler->run(); - vm.GC.unregister_thread(); + vm->gc->unregister_thread(); GlobalPrintln("execute_scheduler:end"); } - entryModule->vm.threading + entryModule->vm->threading .CreateRawThread(entryModule, &execute_scheduler, "IshtarScheduler::&execute"); } } diff --git a/runtime/ishtar.vm/runtime/jit/ABI.cs b/runtime/ishtar.vm/runtime/jit/ABI.cs index 2e0fbeb8..59b83217 100644 --- a/runtime/ishtar.vm/runtime/jit/ABI.cs +++ b/runtime/ishtar.vm/runtime/jit/ABI.cs @@ -13,11 +13,11 @@ public void LoadNativeLibrary(NativeImportEntity entity, CallFrame* frame) if (_cache.ContainsKey(entity.Entry)) return; - var result = frame->vm.NativeStorage.TryLoad(new FileInfo(entity.Entry), out var handle); + var result = frame->vm->NativeStorage.TryLoad(new FileInfo(entity.Entry), out var handle); if (!result) { - frame->vm.FastFail(WNE.NATIVE_LIBRARY_COULD_NOT_LOAD, $"{entity.Entry}", frame); + frame->vm->FastFail(WNE.NATIVE_LIBRARY_COULD_NOT_LOAD, $"{entity.Entry}", frame); return; } @@ -33,14 +33,14 @@ public void LoadNativeSymbol(NativeImportEntity entity, CallFrame* frame) try { - var symbol = frame->vm.NativeStorage.GetSymbol(cached.handle, entity.Fn); + var symbol = frame->vm->NativeStorage.GetSymbol(cached.handle, entity.Fn); cached.ImportedSymbols.Add(entity.Fn, symbol); entity.Handle = symbol; } catch { - frame->vm.FastFail(WNE.NATIVE_LIBRARY_SYMBOL_COULD_NOT_FOUND, $"{entity.Entry}::{entity.Fn}", frame); + frame->vm->FastFail(WNE.NATIVE_LIBRARY_SYMBOL_COULD_NOT_FOUND, $"{entity.Entry}::{entity.Fn}", frame); } } diff --git a/runtime/ishtar.vm/runtime/jit/IshtarJIT.cs b/runtime/ishtar.vm/runtime/jit/IshtarJIT.cs index 329f0957..73493d8d 100644 --- a/runtime/ishtar.vm/runtime/jit/IshtarJIT.cs +++ b/runtime/ishtar.vm/runtime/jit/IshtarJIT.cs @@ -4,7 +4,7 @@ namespace ishtar; using vein.runtime; using static Iced.Intel.AssemblerRegisters; -public unsafe class IshtarJIT(VirtualMachine vm) +public unsafe class IshtarJIT(VirtualMachine* vm) { public static Architecture Architecture => RuntimeInformation.ProcessArchitecture; @@ -206,9 +206,9 @@ public void GenerateHeader(Assembler asm, int stackSize, nint procedure) if (argInfo.Instruction is x64_AssemblerStep.InstructionTarget.push) { - vm.FastFail(WNE.JIT_ASM_GENERATOR_INCORRECT_CAST, + vm->FastFail(WNE.JIT_ASM_GENERATOR_INCORRECT_CAST, $"Direct call is not supported push operations", - vm.Frames->Jit); + vm->Frames->Jit); } else { @@ -223,9 +223,9 @@ public void GenerateHeader(Assembler asm, int stackSize, nint procedure) asm.mov(__dword_ptr[rdi - (sbpOffset += argInfo.Register.GetSize())], new AssemblerRegister32(argInfo.Register)); else - vm.FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, + vm->FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, $"cannot move int32 into 16/8 bit register.", - vm.Frames->Jit); + vm->Frames->Jit); } else if (atype is VeinTypeCode.TYPE_I8) asm.mov(__dword_ptr[rdi - (sbpOffset += argInfo.Register.GetSize())], new AssemblerRegister64(argInfo.Register)); @@ -234,9 +234,9 @@ public void GenerateHeader(Assembler asm, int stackSize, nint procedure) else if (atype is VeinTypeCode.TYPE_R4 or VeinTypeCode.TYPE_R8) asm.movss(__dword_ptr[rdi - (sbpOffset += VeinTypeCode.TYPE_R4.GetNativeSize())], new AssemblerRegisterXMM(argInfo.Register)); else - vm.FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, + vm->FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, $"type code '{atype}' is not supported.", - vm.Frames->Jit); + vm->Frames->Jit); } } @@ -268,7 +268,7 @@ public void GenerateHeader(Assembler asm, int stackSize, nint procedure) asm.pop(rbp); } asm.ret(); - if (vm.HasFaulted()) + if (vm->HasFaulted()) return null; return RecollectExecutableMemory(asm); } @@ -322,9 +322,9 @@ public void GenerateHeader(Assembler asm, int stackSize, nint procedure) asm.mov(__dword_ptr[rsp + stackOffset], val.data.i); stackOffset += 8; } - else vm.FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, + else vm->FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, $"type code '{val.type}' is not supported.", - vm.Frames->Jit); + vm->Frames->Jit); } else { @@ -340,18 +340,18 @@ public void GenerateHeader(Assembler asm, int stackSize, nint procedure) else if (argInfo.Register.IsGPR32()) asm.mov(new AssemblerRegister32(argInfo.Register), val.data.i); else - vm.FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, + vm->FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, $"cannot move int32 into 16/8 bit register.", - vm.Frames->Jit); + vm->Frames->Jit); } else if (val.type is VeinTypeCode.TYPE_I8) asm.mov(new AssemblerRegister64(argInfo.Register), val.data.l); else if (val.type is VeinTypeCode.TYPE_RAW) asm.mov(new AssemblerRegister64(argInfo.Register), __[argumentValues[index++].data.p]); else - vm.FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, + vm->FastFail(WNE.JIT_ASM_GENERATOR_TYPE_FAULT, $"type code '{val.type}' is not supported.", - vm.Frames->Jit); + vm->Frames->Jit); } } @@ -376,7 +376,7 @@ public void GenerateHeader(Assembler asm, int stackSize, nint procedure) asm.pop(rbp); } asm.ret(); - if (vm.HasFaulted()) + if (vm->HasFaulted()) return null; return RecollectExecutableMemory(asm); } @@ -612,7 +612,7 @@ public static void DumpExecutableProcedure(byte[] body) FlushInstructions(asm_mem, asm_size); if (!NativeApi.VirtualProtect(asm_mem, asm_size, NativeApi.Protection.PAGE_EXECUTE_READ, out _)) { - vm.FastFail(WNE.STATE_CORRUPT, "virtual protect failed set PAGE_EXECUTE_READ", vm.Frames->Jit); + vm->FastFail(WNE.STATE_CORRUPT, "virtual protect failed set PAGE_EXECUTE_READ", vm->Frames->Jit); return null; } return asm_mem; diff --git a/runtime/ishtar.vm/runtime/libuv_gc_allocator.cs b/runtime/ishtar.vm/runtime/libuv_gc_allocator.cs index 3985dcb6..3d1df184 100644 --- a/runtime/ishtar.vm/runtime/libuv_gc_allocator.cs +++ b/runtime/ishtar.vm/runtime/libuv_gc_allocator.cs @@ -1,4 +1,4 @@ -namespace ishtar.vm.runtime; +namespace ishtar.runtime; using static ishtar.runtime.gc.BoehmGCLayout.Native; using static libuv.LibUV; diff --git a/runtime/ishtar.vm/runtime/stackval.cs b/runtime/ishtar.vm/runtime/stackval.cs index cb5805e1..11454154 100644 --- a/runtime/ishtar.vm/runtime/stackval.cs +++ b/runtime/ishtar.vm/runtime/stackval.cs @@ -36,9 +36,9 @@ static void freeArray(CallFrame* frame, rawval* stack, int size) => throw new NotSupportedException(); static rawval* alloc(CallFrame* frame, int size) - => frame->vm.GC.AllocRawValue(frame); + => frame->vm->gc->AllocRawValue(frame); static void free(CallFrame* frame, rawval* stack, int size) - => frame->vm.GC.FreeRawValue(stack); + => frame->vm->gc->FreeRawValue(stack); var p = new SmartPointer(size, frame, @@ -70,14 +70,14 @@ public static unsafe SmartPointer Allocate(CallFrame* frame, ushort si throw new ArgumentException($"size is not allowed zero"); static stackval* allocArray(CallFrame* frame, int size) - => frame->vm.GC.AllocateStack(frame, size); + => frame->vm->gc->AllocateStack(frame, size); static void freeArray(CallFrame* frame, stackval* stack, int size) - => frame->vm.GC.FreeStack(frame, stack, size); + => frame->vm->gc->FreeStack(frame, stack, size); static stackval* alloc(CallFrame* frame, int size) - => frame->vm.GC.AllocValue(frame); + => frame->vm->gc->AllocValue(frame); static void free(CallFrame* frame, stackval* stack, int size) - => frame->vm.GC.FreeValue(stack); + => frame->vm->gc->FreeValue(stack); var p = new SmartPointer(size, frame, diff --git a/runtime/ishtar.vm/runtime/transit/RuntimeLayerObject.cs b/runtime/ishtar.vm/runtime/transit/RuntimeLayerObject.cs index e9be315f..c10c67ea 100644 --- a/runtime/ishtar.vm/runtime/transit/RuntimeLayerObject.cs +++ b/runtime/ishtar.vm/runtime/transit/RuntimeLayerObject.cs @@ -55,7 +55,7 @@ // method = runtime_method // }; -// _frame.vm.exec_method(callFrame); +// _frame.vm->exec_method(callFrame); // if (callFrame.exception is not null) // _frame.exception = callFrame.exception; diff --git a/runtime/ishtar.vm/runtime/types/S_NativeHandle.cs b/runtime/ishtar.vm/runtime/types/S_NativeHandle.cs index a814f6b8..f5a2fb4a 100644 --- a/runtime/ishtar.vm/runtime/types/S_NativeHandle.cs +++ b/runtime/ishtar.vm/runtime/types/S_NativeHandle.cs @@ -13,7 +13,7 @@ public static partial class WrappedTypes // public IntPtr Handle // { // get => IshtarMarshal.ToDotnetPointer((IshtarObject*)_obj->vtable[GetFieldOffset("_handle")], _frame); - // set => _obj->vtable[GetFieldOffset("_handle")] = _frame.GetGC().ToIshtarObject(value, _frame); + // set => _obj->vtable[GetFieldOffset("_handle")] = _frame.GetGC()->ToIshtarObject(value, _frame); // } //} } diff --git a/runtime/ishtar.vm/runtime/vin/NativeStorage.cs b/runtime/ishtar.vm/runtime/vin/NativeStorage.cs index e7e2f4c2..3de3e5ff 100644 --- a/runtime/ishtar.vm/runtime/vin/NativeStorage.cs +++ b/runtime/ishtar.vm/runtime/vin/NativeStorage.cs @@ -2,7 +2,7 @@ namespace ishtar.runtime.vin; using ishtar.vin.loaders; -public class NativeStorage(VirtualMachine vm) +public unsafe class NativeStorage(VirtualMachine* vm) { private readonly object guarder = new(); private readonly Dictionary _cache = new(); diff --git a/runtime/ishtar.vm/runtime/vm/CallFrame.cs b/runtime/ishtar.vm/runtime/vm/CallFrame.cs index 4d26dd64..c9aeaf7b 100644 --- a/runtime/ishtar.vm/runtime/vm/CallFrame.cs +++ b/runtime/ishtar.vm/runtime/vm/CallFrame.cs @@ -3,9 +3,9 @@ namespace ishtar using System.Text; using runtime.gc; - public static class CallFrameEx + public static unsafe class CallFrameEx { - public static IshtarGC GetGC(this CallFrame frame) => frame.vm.GC; + public static IshtarGC* GetGC(this CallFrame frame) => frame.vm->gc; } [CTypeExport("call_frame_t")] @@ -29,7 +29,7 @@ public CallFrame(RuntimeIshtarMethod* m, CallFrame* parent, CallFrame* self) public SmartPointer returnValue; public stackval* args; public OpCodeValue last_ip; - public VirtualMachine vm => method->Owner->Owner->vm; + public VirtualMachine* vm => method->Owner->Owner->vm; public CallFrameException exception; @@ -44,6 +44,15 @@ public CallFrame(RuntimeIshtarMethod* m, CallFrame* parent, CallFrame* self) return frame; } + public static CallFrame* Create(RuntimeIshtarMethod* method) + { + var frame = IshtarGC.AllocateImmortal(null); + + *frame = new CallFrame(method, null, frame); + + return frame; + } + private static void Free(CallFrame* frame) => IshtarGC.FreeImmortal(frame); @@ -51,34 +60,34 @@ public void assert(bool conditional, [CallerArgumentExpression("conditional")] s { if (conditional) return; - vm.FastFail(WNE.STATE_CORRUPT, $"Static assert failed: '{msg}'", Self); + vm->FastFail(WNE.STATE_CORRUPT, $"Static assert failed: '{msg}'", Self); } public void assert(bool conditional, WNE type, [CallerArgumentExpression("conditional")] string msg = default) { if (conditional) return; - vm.FastFail(type, $"Static assert failed: '{msg}'", Self); + vm->FastFail(type, $"Static assert failed: '{msg}'", Self); } public void ThrowException(RuntimeIshtarClass* @class) => this.exception = new CallFrameException() { - value = vm.GC.AllocObject(@class, Self) + value = vm->gc->AllocObject(@class, Self) }; public void ThrowException(RuntimeIshtarClass* @class, string message) { this.exception = new CallFrameException() { - value = vm.GC.AllocObject(@class, Self) + value = vm->gc->AllocObject(@class, Self) }; if (@class->FindField("message") is null) throw new InvalidOperationException($"Class '{@class->FullName->NameWithNS}' is not contained 'message' field."); this.exception.value->vtable[@class->Field["message"]->vtable_offset] - = vm.GC.ToIshtarObject(message, Self); + = vm->gc->ToIshtarObject(message, Self); } diff --git a/runtime/ishtar.vm/runtime/vm/IshtarTypes.cs b/runtime/ishtar.vm/runtime/vm/IshtarTypes.cs index 40a2fa32..ebde467f 100644 --- a/runtime/ishtar.vm/runtime/vm/IshtarTypes.cs +++ b/runtime/ishtar.vm/runtime/vm/IshtarTypes.cs @@ -81,8 +81,8 @@ public readonly unsafe struct IshtarTypes( public static IshtarTypes* Create(AppVault vault) { - var r = IshtarGC.AllocateImmortal(vault.vm.InternalModule); - var module = IshtarGC.AllocateImmortal(vault.vm.InternalModule); + var r = IshtarGC.AllocateImmortal(vault.vm->InternalModule); + var module = IshtarGC.AllocateImmortal(vault.vm->InternalModule); *module = new RuntimeIshtarModule(vault, "std", module, new IshtarVersion(0, 0)); diff --git a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarClass.cs b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarClass.cs index fd70fb36..ffc79efd 100644 --- a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarClass.cs +++ b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarClass.cs @@ -228,7 +228,7 @@ internal void ReplaceParent(RuntimeIshtarClass* parent) } #if DEBUG_VTABLE - public static Dictionary dvtables = new(); + private static readonly Dictionary dvtables = new(); public debug_vtable dvtable => dvtables[ID]; @@ -247,7 +247,7 @@ private readonly struct native_disposer(T* ptr, UnsafeVoid_Delegate dispos public void Dispose() => disposer(ptr); } - public void init_vtable(VirtualMachine vm, CallFrame* fr = null) + public void init_vtable(VirtualMachine* vm, CallFrame* fr = null) { if (is_inited) return; @@ -268,7 +268,7 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) { computed_size = (ulong)sizeof(void*); vtable_size = (ulong)sizeof(void*); - vtable = vm.GC.AllocVTable(1); + vtable = vm->gc->AllocVTable(1); is_inited = true; return; } @@ -280,13 +280,13 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) { if (Parent->IsUnresolved) { - vm.FastFail(TYPE_MISMATCH, "Cannot init vtable when parent type is unresolved", frame); + vm->FastFail(TYPE_MISMATCH, "Cannot init vtable when parent type is unresolved", frame); return; } if (IsUnresolved) { - vm.FastFail(TYPE_MISMATCH, "Cannot init vtable when type is unresolved", frame); + vm->FastFail(TYPE_MISMATCH, "Cannot init vtable when type is unresolved", frame); return; } @@ -307,7 +307,7 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) if (computed_size >= long.MaxValue) // fuck IntPtr ctor limit { - vm.FastFail(TYPE_LOAD, $"'{FullName->ToString()}' too big object.", frame); + vm->FastFail(TYPE_LOAD, $"'{FullName->ToString()}' too big object.", frame); return; } @@ -328,7 +328,7 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) dvtable.vtable_info = new string[computed_size]; #endif - vtable = vm.GC.AllocVTable((uint)computed_size); + vtable = vm->gc->AllocVTable((uint)computed_size); #if DEBUG_VTABLE dvtable.vtable_methods = new RuntimeIshtarMethod*[(long)computed_size]; @@ -356,7 +356,7 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) if ((method->Flags & MethodFlags.Abstract) != 0 && (Flags & ClassFlags.Abstract) == 0) { - vm.FastFail(TYPE_LOAD, + vm->FastFail(TYPE_LOAD, $"Method '{method->Name}' in '{Name}' type has invalid mapping.", frame); return; } @@ -373,7 +373,7 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) { var w = Parent->FindMethod(method->Name); if (w == null && (method->Flags & MethodFlags.Override) != 0) - vm.FastFail(MISSING_METHOD, + vm->FastFail(MISSING_METHOD, $"Method '{method->Name}' mark as OVERRIDE," + $" but parent class '{Parent->Name}'" + $" no contained virtual/abstract method.", frame); @@ -399,7 +399,7 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) if ((field->Flags & FieldFlags.Abstract) != 0 && (Flags & ClassFlags.Abstract) == 0) { - vm.FastFail(TYPE_LOAD, + vm->FastFail(TYPE_LOAD, $"Field '{field->Name}' in '{this.Name}' type has invalid mapping.", frame); return; } @@ -437,7 +437,7 @@ public void init_vtable(VirtualMachine vm, CallFrame* fr = null) var w = Parent->FindField(field->FullName); if (w == null && (field->Flags & FieldFlags.Override) != 0) - vm.FastFail(MISSING_FIELD, + vm->FastFail(MISSING_FIELD, $"Field '{field->Name}' mark as OVERRIDE," + $" but parent class '{Parent->Name}' " + $"no contained virtual/abstract method.", frame); diff --git a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarField.cs b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarField.cs index 89e8781a..658ed783 100644 --- a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarField.cs +++ b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarField.cs @@ -79,7 +79,7 @@ public bool init_mapping(CallFrame* frame) { bool failMapping(int code, RuntimeIshtarField* field) { - frame->vm.FastFail(WNE.TYPE_LOAD, + frame->vm->FastFail(WNE.TYPE_LOAD, $"Native aspect has incorrect mapping for '{field->FullName->Name}' field. [0x{code:X}]", frame); return false; } diff --git a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarMethod.cs b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarMethod.cs index 7c3f926e..b8493f38 100644 --- a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarMethod.cs +++ b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarMethod.cs @@ -48,7 +48,7 @@ public void Dispose() return lst; } - public static NativeList* Create(VirtualMachine vm, VeinArgumentRef[] data, void* parent) + public static NativeList* Create(VirtualMachine* vm, VeinArgumentRef[] data, void* parent) { if (data.Length == 0) return IshtarGC.AllocateList(parent); @@ -59,7 +59,7 @@ public void Dispose() { var a = IshtarGC.AllocateImmortal(parent); - *a = new RuntimeMethodArgument(vm.Vault.GlobalFindType(tuple.Type.FullName.T(a)), StringStorage.Intern(tuple.Name, a), a); + *a = new RuntimeMethodArgument(vm->Vault.GlobalFindType(tuple.Type.FullName.T(a)), StringStorage.Intern(tuple.Name, a), a); lst->Add(a); } @@ -280,9 +280,7 @@ public void Dispose() if (_self is null) return; DiagnosticDtorTraces[(nint)_self] = Environment.StackTrace; - - VirtualMachine.GlobalPrintln($"Disposed method '{Name}'"); - + if (Header is not null) IshtarGC.FreeImmortal(Header); (Arguments)->ForEach(x => x->Dispose()); diff --git a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarModule.cs b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarModule.cs index c578cfaf..5ac3f0ea 100644 --- a/runtime/ishtar.vm/runtime/vm/RuntimeIshtarModule.cs +++ b/runtime/ishtar.vm/runtime/vm/RuntimeIshtarModule.cs @@ -20,10 +20,10 @@ public unsafe struct RuntimeIshtarModule(AppVault vault, string name, RuntimeIsh { [field: CTypeOverride("void*")] public WeakRef* Vault { get; private set; } = WeakRef.Create(vault, self); - public VirtualMachine vm => Vault->Value.vm; + public VirtualMachine* vm => Vault->Value.vm; public uint ID { get; internal set; } - public IshtarVersion Version { get; internal set; } = version; + public IshtarVersion Version { get; private set; } = version; [field: CTypeOverride("void*")] @@ -255,7 +255,7 @@ public string Name public static RuntimeIshtarModule* Read(AppVault vault, byte[] arr, NativeList* deps, ModuleResolverCallback resolver) { - var module = IshtarGC.AllocateImmortal(vault.vm.@ref); + var module = IshtarGC.AllocateImmortal(vault.vm); *module = new RuntimeIshtarModule(vault, "unnamed", module, new IshtarVersion()); @@ -274,7 +274,7 @@ public string Name { var exp = new ILCompatibleException(ilVersion, OpCodes.SetVersion); - vault.vm.FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, $"Unable to load assembly: '{exp.Message}'.", vault.vm.Frames->ModuleLoaderFrame); + vault.vm->FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, $"Unable to load assembly: '{exp.Message}'.", vault.vm->Frames->ModuleLoaderFrame); return null; } @@ -300,7 +300,7 @@ public string Name var name = reader.ReadIshtarString(); var t = new QualityTypeName(new NameSymbol(name), new NamespaceSymbol(ns), new ModuleNameSymbol(module->Name)).T(module); - var predefined = module->vm.Types->ByQualityName(t); + var predefined = module->vm->Types->ByQualityName(t); if (predefined is not null) { VirtualMachine.GlobalPrintln($"read typename: [{key}] '{t->NameWithNS}' and linked by predefined type"); @@ -308,7 +308,7 @@ public string Name } else if (asmName.Equals(module->Name)) { - var c = module->DefineClass(t, module->vm.Types->ObjectClass); + var c = module->DefineClass(t, module->vm->Types->ObjectClass); c->Flags |= ClassFlags.NotCompleted; VirtualMachine.GlobalPrintln($"read typename: [{key}] '{t->NameWithNS}' and set not completed"); } @@ -489,14 +489,14 @@ public string Name module->const_storage = IshtarGC.AllocateImmortal(module); *module->const_storage = new RuntimeConstStorage(module); - FillConstStorage(module->const_storage, const_body, module->vm.Frames->ModuleLoaderFrame); + FillConstStorage(module->const_storage, const_body, module->vm->Frames->ModuleLoaderFrame); VirtualMachine.GlobalPrintln($"Read {module->Name} module success"); module->Version = IshtarVersion.Parse(module->GetConstStringByIndex(vdx)); - module->aspects_table->AddRange(RuntimeAspect.Deconstruct(module->const_storage, module->vm.Frames->ModuleLoaderFrame, vault.vm.Types)); + module->aspects_table->AddRange(RuntimeAspect.Deconstruct(module->const_storage, module->vm->Frames->ModuleLoaderFrame, vault.vm->Types)); module->DefineBootstrapper(); @@ -504,7 +504,7 @@ public string Name ValidateRuntimeTokens(module); module->LinkFFIMethods(module); #if DEBUG - module->vm.Jitter.GetExecutionModule().PrintToFile($"{module->Name}_ffi.ll"); + module->vm->Jitter.GetExecutionModule().PrintToFile($"{module->Name}_ffi.ll"); #endif InitVTables(module); @@ -594,7 +594,7 @@ public static void DistributionAspects(RuntimeIshtarModule* module) @class->Aspects->Add(aspect); } else - module->vm.println($"Aspect '{aspect->Name}': class '{GetStringUnsafe(classAspect.ClassName)}' not found."); + module->vm->println($"Aspect '{aspect->Name}': class '{GetStringUnsafe(classAspect.ClassName)}' not found."); break; } case AspectTarget.Method: @@ -610,7 +610,7 @@ public static void DistributionAspects(RuntimeIshtarModule* module) if (@class is null) { var debug = classes->ToList(); - module->vm.println($"Aspect '{aspect->Name}': method '{GetStringUnsafe(ma.ClassName)}/{GetStringUnsafe(ma.MethodName)}' not found. [no class found]"); + module->vm->println($"Aspect '{aspect->Name}': method '{GetStringUnsafe(ma.ClassName)}/{GetStringUnsafe(ma.MethodName)}' not found. [no class found]"); return; } var method = @class->Methods->FirstOrNull(m => m->Name.Equals(GetStringUnsafe(ma.MethodName))); @@ -619,7 +619,7 @@ public static void DistributionAspects(RuntimeIshtarModule* module) else { var methods = @class->Methods->ToList(); - module->vm.println($"Aspect '{aspect->Name}': method '{GetStringUnsafe(ma.ClassName)}/{GetStringUnsafe(ma.MethodName)}' not found."); + module->vm->println($"Aspect '{aspect->Name}': method '{GetStringUnsafe(ma.ClassName)}/{GetStringUnsafe(ma.MethodName)}' not found."); } break; } @@ -633,14 +633,14 @@ public static void DistributionAspects(RuntimeIshtarModule* module) if (@class is null) { - module->vm.println($"Aspect '{aspect->Name}': field '{GetStringUnsafe(fa.ClassName)}/{GetStringUnsafe(fa.FieldName)}' not found. [no class found]"); + module->vm->println($"Aspect '{aspect->Name}': field '{GetStringUnsafe(fa.ClassName)}/{GetStringUnsafe(fa.FieldName)}' not found. [no class found]"); return; } var field = @class->Fields->FirstOrNull(m => m->Name.Equals(GetStringUnsafe(fa.FieldName))); if (field is not null) field->Aspects->Add(aspect); else - module->vm.println($"Aspect '{aspect->Name}': field '{GetStringUnsafe(fa.ClassName)}/{GetStringUnsafe(fa.FieldName)}' not found."); + module->vm->println($"Aspect '{aspect->Name}': field '{GetStringUnsafe(fa.ClassName)}/{GetStringUnsafe(fa.FieldName)}' not found."); break; } } @@ -794,7 +794,7 @@ public List DecodeField(BinaryReader binary, RuntimeIshtarC { if (types_table->TryGetValue(idx, out var result)) return result; - vm.FastFail(WNE.TYPE_LOAD, $"No found type by '{idx}'", frame); + vm->FastFail(WNE.TYPE_LOAD, $"No found type by '{idx}'", frame); return null; } @@ -825,13 +825,13 @@ public void LinkFFIMethod(RuntimeIshtarMethod* method) var name = method->Name; if (aspect is null) { - vm.FastFail(WNE.TYPE_LOAD, $"(0x1) Extern function without native aspect. [{name}]", sys_frame); + vm->FastFail(WNE.TYPE_LOAD, $"(0x1) Extern function without native aspect. [{name}]", sys_frame); return; } if (aspect->Arguments->Length != 2) { - vm.FastFail(WNE.TYPE_LOAD, $"(0x1) Native aspect incorrect arguments. [{name}]", sys_frame); + vm->FastFail(WNE.TYPE_LOAD, $"(0x1) Native aspect incorrect arguments. [{name}]", sys_frame); return; } @@ -839,7 +839,7 @@ public void LinkFFIMethod(RuntimeIshtarMethod* method) if (import_tg->Value.type is not VeinTypeCode.TYPE_STRING) { - vm.FastFail(WNE.TYPE_LOAD, $"(0x2) Native aspect incorrect arguments. [{name}]", sys_frame); + vm->FastFail(WNE.TYPE_LOAD, $"(0x2) Native aspect incorrect arguments. [{name}]", sys_frame); return; } @@ -847,7 +847,7 @@ public void LinkFFIMethod(RuntimeIshtarMethod* method) if (import_fn->Value.type is not VeinTypeCode.TYPE_STRING) { - vm.FastFail(WNE.TYPE_LOAD, $"(0x2) Native aspect incorrect arguments. [{name}]", sys_frame); + vm->FastFail(WNE.TYPE_LOAD, $"(0x2) Native aspect incorrect arguments. [{name}]", sys_frame); return; } @@ -871,7 +871,7 @@ public void LinkFFIMethods(RuntimeIshtarMethod*[] methods) } private void LinkInternalNative(string name, RuntimeIshtarMethod* method) { - vm.FFI.GetMethod(name, out var header); + vm->FFI.GetMethod(name, out var header); method->PIInfo = header; } @@ -907,7 +907,7 @@ private void LinkInternalNative(string name, RuntimeIshtarMethod* method) var endAddr = bin.ReadInt32(); var filterAddr = bin.ReadIntArray().ToNative(module); var catchAddr = bin.ReadIntArray().ToNative(module); - var catchClass = bin.ReadTypesArray((x) => (nint)module->GetTypeNameByIndex(x, module->vm.Frames->ModuleLoaderFrame)).ToNative(module); + var catchClass = bin.ReadTypesArray((x) => (nint)module->GetTypeNameByIndex(x, module->vm->Frames->ModuleLoaderFrame)).ToNative(module); var types = bin.ReadSpecialDirectByteArray().ToNative(module); var item = IshtarGC.AllocateImmortal(module); @@ -967,7 +967,7 @@ internal static void ConstructIL(RuntimeIshtarMethod* method, byte[] body, short - var a = RuntimeMethodArgument.Create(ishtarModule->vm.Types, ishtarModule->GetConstStringByIndex(nIdx), + var a = RuntimeMethodArgument.Create(ishtarModule->vm->Types, ishtarModule->GetConstStringByIndex(nIdx), argType, ishtarModule); args->Add(a); } @@ -979,7 +979,7 @@ private void DefineBootstrapper() public RuntimeIshtarClass* Bootstrapper { get; private set; } - public CallFrame* sys_frame => Vault->Value.vm.Frames->ModuleLoaderFrame; + public CallFrame* sys_frame => Vault->Value.vm->Frames->ModuleLoaderFrame; public static bool Eq(RuntimeIshtarModule* p1, RuntimeIshtarModule* p2) => p1->ID == p2->ID; } public static unsafe class QualityTypeEx diff --git a/vein_lang.sln.DotSettings b/vein_lang.sln.DotSettings index 4c65dfd2..0fa1dd1d 100644 --- a/vein_lang.sln.DotSettings +++ b/vein_lang.sln.DotSettings @@ -12,12 +12,17 @@ True True True + True + True True + True True True + True True True True + True True True True @@ -60,7 +65,10 @@ True True True + True + True True + True True True True @@ -79,6 +87,7 @@ True True True + True True True True @@ -93,6 +102,7 @@ True True True + True True True True @@ -103,6 +113,7 @@ True True True + True True True True From ca54041f2f9863ad8e33bb0e2a9ce7db4b121fe3 Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Mon, 12 Aug 2024 05:14:06 +0300 Subject: [PATCH 5/6] update ffi to unsafe --- .../ishtar.vm/FFI/ForeignFunctionInterface.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/runtime/ishtar.vm/FFI/ForeignFunctionInterface.cs b/runtime/ishtar.vm/FFI/ForeignFunctionInterface.cs index ba8aaf09..bbd1c683 100644 --- a/runtime/ishtar.vm/FFI/ForeignFunctionInterface.cs +++ b/runtime/ishtar.vm/FFI/ForeignFunctionInterface.cs @@ -3,7 +3,7 @@ namespace ishtar; using System.Collections.Generic; using System.Linq; using collections; -using ishtar.vm.__builtin.networks; +using ishtar.__builtin.networks; using networks; using runtime; using runtime.gc; @@ -11,18 +11,18 @@ namespace ishtar; public unsafe class ForeignFunctionInterface { - public readonly VirtualMachine vm; + public readonly VirtualMachine* vm; public NativeDictionary* methods { get; } public Dictionary method_table { get; } = new(); public AtomicNativeDictionary* deferMethods { get; } private ulong _index; - public ForeignFunctionInterface(VirtualMachine vm) + public ForeignFunctionInterface(VirtualMachine* vm) { this.vm = vm; - methods = IshtarGC.AllocateDictionary(vm.@ref); - deferMethods = IshtarGC.AllocateAtomicDictionary(vm.@ref); + methods = IshtarGC.AllocateDictionary(vm); + deferMethods = IshtarGC.AllocateAtomicDictionary(vm); INIT(); } public PInvokeInfo AsNative(delegate* p) @@ -62,7 +62,7 @@ private void INIT() } public RuntimeIshtarMethod* Add(string name, MethodFlags flags, VeinTypeCode returnType, params (string name, VeinTypeCode type)[] args) - => Add(name, flags, vm.Types->ByTypeCode(returnType), args); + => Add(name, flags, vm->Types->ByTypeCode(returnType), args); public RuntimeIshtarMethod* Add(string name, MethodFlags flags, RuntimeIshtarClass* returnType, params (string name, VeinTypeCode type)[] args) { @@ -72,10 +72,10 @@ private void INIT() for (int index = 0; index < args.Length; index++) { var (_, type) = args[index]; - arr[index] = vm.Types->ByTypeCode(type); + arr[index] = vm->Types->ByTypeCode(type); } - var method = vm.CreateInternalMethod( + var method = vm->CreateInternalMethod( RuntimeIshtarMethod.GetFullName(name, returnType, arr), flags, args); method->Assert(method); method_table.Add(method->Name, _index); @@ -94,7 +94,7 @@ public void Add(string fullName, PInvokeInfo nativeInfo) public static void StaticValidate(void* p, CallFrame* frame) { if (p != null) return; - frame->vm.FastFail(WNE.STATE_CORRUPT, "Null pointer state.", frame); + frame->vm->FastFail(WNE.STATE_CORRUPT, "Null pointer state.", frame); } [Conditional("STATIC_VALIDATE_IL")] @@ -149,7 +149,7 @@ public void GetMethod(string FullName, out PInvokeInfo nativeHeader) return; } } - vm.FastFail(WNE.MISSING_METHOD, $"method '{FullName}' is not found", vm.Frames->NativeLoader); + vm->FastFail(WNE.MISSING_METHOD, $"method '{FullName}' is not found", vm->Frames->NativeLoader); throw new EntryPointNotFoundException(FullName); } @@ -159,7 +159,7 @@ public void GetMethod(string FullName, out PInvokeInfo nativeHeader) public static void LinkExternalNativeLibrary(string importModule, string fnName, RuntimeIshtarMethod* importCaller) { - var jitter = importCaller->Owner->Owner->vm.Jitter; + var jitter = importCaller->Owner->Owner->vm->Jitter; jitter.CompileFFI(importCaller, importModule, fnName); } @@ -168,7 +168,7 @@ public static void LinkExternalNativeLibrary(string importModule, string fnName, public void DisplayDefinedMapping() { foreach (var (key, value) in method_table) - vm.trace.log($"ffi map '{key}' -> 'sys::FFI/{(GetMethod(value))->Name}'"); + vm->trace.log($"ffi map '{key}' -> 'sys::FFI/{(GetMethod(value))->Name}'"); } } From 1f8c4c6582cbe1b55d76322f5f638a8660cf8e4b Mon Sep 17 00:00:00 2001 From: Yuuki Wesp Date: Mon, 12 Aug 2024 05:14:20 +0300 Subject: [PATCH 6/6] add proxy types for ip and other network classes --- .../FFI/generated/Vein_ClosureDelegate.cs | 12 ++++++++ .../FFI/generated/Vein_IpEndpoint.cs | 21 ++++++++++++++ .../ishtar.vm/FFI/generated/Vein_Ipv4Addr.cs | 28 +++++++++++++++++++ .../FFI/generated/Vein_SocketHandle.cs | 13 +++++++++ 4 files changed, 74 insertions(+) create mode 100644 runtime/ishtar.vm/FFI/generated/Vein_ClosureDelegate.cs create mode 100644 runtime/ishtar.vm/FFI/generated/Vein_IpEndpoint.cs create mode 100644 runtime/ishtar.vm/FFI/generated/Vein_Ipv4Addr.cs create mode 100644 runtime/ishtar.vm/FFI/generated/Vein_SocketHandle.cs diff --git a/runtime/ishtar.vm/FFI/generated/Vein_ClosureDelegate.cs b/runtime/ishtar.vm/FFI/generated/Vein_ClosureDelegate.cs new file mode 100644 index 00000000..10fe60e9 --- /dev/null +++ b/runtime/ishtar.vm/FFI/generated/Vein_ClosureDelegate.cs @@ -0,0 +1,12 @@ +namespace ishtar; + +public readonly unsafe struct Vein_ClosureDelegate(IshtarObject* o) +{ + public readonly IshtarObject* Object = o; + + public IshtarObject* Scope => ((IshtarObject*)Object->vtable[Object->clazz->Field["_scope"]->vtable_offset]); + + public rawval* Function => ((rawval*)Object->vtable[Object->clazz->Field["_fn"]->vtable_offset]); + + public bool IsVolatile => Scope is null; +} diff --git a/runtime/ishtar.vm/FFI/generated/Vein_IpEndpoint.cs b/runtime/ishtar.vm/FFI/generated/Vein_IpEndpoint.cs new file mode 100644 index 00000000..e2dfdc3f --- /dev/null +++ b/runtime/ishtar.vm/FFI/generated/Vein_IpEndpoint.cs @@ -0,0 +1,21 @@ +namespace ishtar; + +using ishtar.__builtin.networks; + +public readonly unsafe struct Vein_IpEndpoint(IshtarObject* o) +{ + public readonly IshtarObject* Object = o; + + + public ushort port + { + get => ((IshtarObject*)Object->vtable[Object->clazz->Field["port"]->vtable_offset])->GetUInt16(); + set => ((IshtarObject*)Object->vtable[Object->clazz->Field["port"]->vtable_offset])->SetUInt16(value); + } + + public Vein_Ipv4Addr address + { + get => new((IshtarObject*)Object->vtable[Object->clazz->Field["address"]->vtable_offset]); + set => Object->vtable[Object->clazz->Field["address"]->vtable_offset] = value.Object; + } +} diff --git a/runtime/ishtar.vm/FFI/generated/Vein_Ipv4Addr.cs b/runtime/ishtar.vm/FFI/generated/Vein_Ipv4Addr.cs new file mode 100644 index 00000000..1a247830 --- /dev/null +++ b/runtime/ishtar.vm/FFI/generated/Vein_Ipv4Addr.cs @@ -0,0 +1,28 @@ +namespace ishtar; + +public readonly unsafe struct Vein_Ipv4Addr(IshtarObject* o) +{ + public readonly IshtarObject* Object = o; + + public byte first + { + get => ((IshtarObject*)Object->vtable[Object->clazz->Field["first"]->vtable_offset])->GetUInt8(); + set => ((IshtarObject*)Object->vtable[Object->clazz->Field["first"]->vtable_offset])->SetUInt8(value); + } + public byte second + { + get => ((IshtarObject*)Object->vtable[Object->clazz->Field["second"]->vtable_offset])->GetUInt8(); + set => ((IshtarObject*)Object->vtable[Object->clazz->Field["second"]->vtable_offset])->SetUInt8(value); + } + public byte third + { + get => ((IshtarObject*)Object->vtable[Object->clazz->Field["third"]->vtable_offset])->GetUInt8(); + set => ((IshtarObject*)Object->vtable[Object->clazz->Field["third"]->vtable_offset])->SetUInt8(value); + } + public byte fourth + { + get => ((IshtarObject*)Object->vtable[Object->clazz->Field["fourth"]->vtable_offset])->GetUInt8(); + set => ((IshtarObject*)Object->vtable[Object->clazz->Field["fourth"]->vtable_offset])->SetUInt8(value); + } +} + diff --git a/runtime/ishtar.vm/FFI/generated/Vein_SocketHandle.cs b/runtime/ishtar.vm/FFI/generated/Vein_SocketHandle.cs new file mode 100644 index 00000000..7f1b28a6 --- /dev/null +++ b/runtime/ishtar.vm/FFI/generated/Vein_SocketHandle.cs @@ -0,0 +1,13 @@ +namespace ishtar; + +using static libuv.LibUV; + +public readonly unsafe struct Vein_SocketHandle(IshtarObject* o) +{ + public uv_tcp_t* server_handle + { + get => (uv_tcp_t*)o->vtable[o->clazz->Field["server_handle"]->vtable_offset]; + set => o->vtable[o->clazz->Field["server_handle"]->vtable_offset] = value; + } +} +