#Vinix
1 messages ยท Page 2 of 1
also thanks, i will definitely use this flag soon on my code to make sure i'm not doing anything silly
now it has v -warn-about-allocs which does the same thing as the command above
but no escape analysis via commandline flags yet
but it does do it internally, right?
yeah
in C you only have sprintf/strcat going past the bounds of the buffer and giving an attacker code execution so yeah!
much better
no one is forcing you to use that garbage tho
struct string_view
but im not sure about your point, are you suggesting that solving potential memory bugs requires hidden allocations?
nah it doesn't
i meant that c isn't that much better with this
it doesn't fwiw
you can even see in the go output that "SDF" + s1 is marked as "does not escape", i.e. does not allocate on the heap (probably... definitely doesn't hit gc though)
Anyway if you stick to legacy C with strcat and shit then yeah, you will probably have memory bugs
but with modern apis and tools you can avoid that
ofc
modern apis as in "yeah so now you have to pass in the length manually and hope you don't have an off by one?"
string_view like i mentioned
still better than gets though
is that in the c standard?
it was in some draft i think
so no
i mean lol
thats not a good point
C is not a language u can use solely with the standard library
its not like c++ with tons of shit there
true
i mean
you can
i did :^)
mfw c++ still has no networking there
until i gave in and pulled in a json parsing library because fuck that shit
oh yeah and that
(i mean i was writing c++ but let's call it c style c++, no stl involved)
like yaml and json are supported as first class stuff in a lot of langauges now
go is very nice with taht
go only has json in the stdlib
im not that familiar with it, but i worked with a codebase that had struct fields marked with yaml:whatever
and the yaml parsing library i use (and iirc k8s uses) takes yaml
converts it to json
and then parses that with the stdlib
it's reflection metadata
you can query it yourself
yeah
its like fieldinfo.structtag or something
which is (a) rather silly
its for auto serialization right?
but does work well enough
i mean, that's the intent i think
yeah
for renaming json fields mostly
because for the stdlib to deserialize into a field it must be exported (i.e. start with an uppercase letter)
and {"Foo":"bar"} is not a common style in json
true
updated
i've added 4 more sources of allocations to the warning as well
i think that covers 90% of them
i'll bring it up to 100% today
already found one missing (casts to sum types)
I'll add a per function option too, so that it doesn't spam
on my end i have been fighting with trying to get better refcounting going for a few days now
@upbeat crest uh i don't think this is working modules/time/time.v:25:18: warning: allocation (string concatenation) 23 | 24 | pub fn (mut this TimeSpec) add(interval TimeSpec) { 25 | if this.tv_nsec + interval.tv_nsec > 999999999 { | ^ 26 | diff := (this.tv_nsec + interval.tv_nsec) - 1000000000 27 | this.tv_nsec = diff
it literally warns for every addition
this is just an example, but this is an integer addition, not a concatenation
and it definitely doesn't allocate
lol fixed
v up
and use -experimental for the interface nil fix to work for now, will remove that requirement later today
@upbeat crest how do i make V's allocation warnings shut up if i am manually freeing?
(for a given allocation)
i think it should be made so it automatically shuts up once it sees you free it manually
yeah but it doesn't do that, plus in certain cases it cannot do that either
so there needs to be a method to make it shut up
manually
do not use -warn-about-allocs
logic for detecting frees on allocating expressions is too complex
we'll get another rust this way ๐
and it won't work anyway
if false {
x.free() // will shut it up, but it's fake
}
couldn't this be sort of made a bit better with some syntactic sugar?
@upbeat crest can you not have a C-style, stack allocated array in V?
arr = [1,2,3]!
wtf
! means fixed size stack allocated array
i couldn't come up with a better syntax
as opposed to [1,2,3]
why not just make [1,2,3] be a value
and then it becomes a dynamic array the moment you put it on the heap
syntax like what. any ideas?
oh yeah! i forgot about that
that's bound to save a lot of memory leaks
idk, perhaps something like uncheck ptr1, ptr2, ...
or maybe __uncheck
to avoid an extra "standard" keyword
x := [1,2,3] // __uncheck
sounds good
ok will do
// unchecked?
that's a common word though

// unleaked 
maybe // v:uncheck
oh yeah lets use a utf8
i mean that v: part is a very good idea
yup
// ๐คก
i like this
also what is this even checking, i think its a good idea for it to be verbose
and yeah the v: is a good idea but i prefer it without space
what if you add more diagnostics in the future
yeah me too
just make it work with both
without space leaves less room for error
although x := [1,2,3] // v:freed is probably clearer
yeah that's fine too
// v:trust me bro
there are so many arrays for events allocated on the local scope on tight loops
they could've been all []! but weren't
no wonder there's a lot of leakage lol
why are stack arrays not the default option?
Are they allocated using alloca? Or only once at the entry of the function?
V tries to balance between C and python
they use C syntax for allocating arrays with known elements
no alloca
Nice
known elements/known size
very counter-intuitive imo, but if its like python then sure
! thing was just a meme
(lets add this temp token for now)
4 years later i have no idea what's better
looks like it'll stay
i considered fixed([1,2,3])
[..][1,2,3]
etc
dyn[1,2,3] 
i still stand by my &[1,2,3] for heap allocated arrays
lines up with syntax for heap allocating other things
i stand by anything that makes allocations opt-in
guess thats not something up for discussion?
yeah im confused about that too, clearly needs a change but i got no feedback on my idea (twice) :^)
its not a bad idea
but would break so much existing code
and confuse python kids
i think 95% of arrays used are dynamic arrays, at least in vlang/v
is that because people wanted dynamic arrays or because they didnt know of the fixed syntax
and just assumed it was already fixed
i mean if you can't read the documentation it's your fault lol
not the best philosophy for designing something lol
just read the damn docs and figure out that if you want a dynamic array you do the other thing instead
and if you can't read the docs you probably should pick another hobby
no experienced engineer will go read "how to make array" most likely
they will just look at code examples
exactly
tahts why i want opt-in dynamic arrays, not the other way around
you probably go figure out why, and you hit the docs page and you figure out [] is a fixed array, to make it dynamic you do &[]
or as you said, you just find code examples and see people doing &[]
you can't use fixed arrays in things like parsers
error: cannot push to a fixed-size array, did you mean &[...]?
unless you write old school pascal/c style code
with [255]elems // >255? lol good luck
you could do [1, 2, 3]
for both
and then do escape analysis to figure out if the value escapes or can be kept on the stack
or [size]type{1, 2, 3} like in go works okay enough too
interesting, a bit against the "be as explicit as possible", but could work
as soon as you try to append to an array or allocate too much, it escapes
it's similar to my idea of auto (de)referencing
good in theory, nice for the developer
but comes with lots of hidden issues
it also means that the "default" approach is the optimal one already
which is good, that's what you want
go slices work like this, afaik
go differentiates between basic arrays and slices (dynamic arrays)
[...]int vs []int
while the semantics of a go slice are always gc-allocated ones, go does not always allocate the backing buffer on the heap (instead, if they prove that the value cannot escape out of the function, they allocate it on the stack)
arr := []int{1,2,3}
./a.go:18:14: []int{...} does not escape
So "does not escape" means that Go doesn't do an allocation, always?
they probably heap allocate if it's "big enough"
once I added fmt.Println(arr), it changed to ./a.go:18:14: []int{...} escapes to heap
so probably yes
how do you get that print?
is this some compiler switch?
i didnt know go had something like that
go build -gcflags -m a.go
yeah
quite possibly
ok sounds good, will do the same
@upbeat crest how do you make V output all the warnings instead of stopping (and failing) if there are too many?
what message do you get?
need it to grep
builder error: too many errors/warnings/notices
@orchid tartan v -message-limit 10000 foo.v
it's a major performance gain too
thank you
ok this is good
@upbeat crest i just need that comment-based warning suppression and then i promise i'll stop bothering :p
no bothering ๐ I'll do v:fixed today
it's a bit trickier than the previous fix
ty!
btw
i get a lot of warning: allocation (cast to interface)
these seem to be spurious if the previous fix is still in effect
can you paste a full example, with source code line it points to?
also btw what about this one? https://github.com/vlang/vinix/pull/139
actually it doesn't seem to be spurious
i do pass -experimental...
it still seems to allocate though
that is a good one but regrettably i haven't had the time to review it in depth
i'd like to do that before merging it
modules/sched/sched.v:357:78: error: invalid expression: unexpected token `,`
355 | }
356 |
357 | mut new_thread := new_user_thread(process, false, pc, voidptr(0), stack, []!, []!, voidptr(0), false) or {
| ^
omg
i think this should work?
checking
empty fixed size arrays aren't supported in C by default
Zero Length (Using the GNU Compiler Collection (GCC))
you can just give them no storage in codegen though
or convert them to a struct emptyarray {};
int main(int argc, char** argv) {
int a[0];
printf("a: %p; sizeof(a): %ld \n", (void*)a, sizeof(a));
return 0;
}
this compiles with:
#0 17:16:52 ^ master /space/v/oo> clang-18 -std=c99 -pedantic x.c
x.c:3:10: warning: zero size arrays are an extension [-Wzero-length-array]
3 | int a[0];
| ^
1 warning generated.```
this v:freed thing is very tricky because all comments are stripped for performance on the scanner level
unless the scanner is used for vfmt
i'd have to modify the scanner to look ahead at the comment and see if it has v:freed
yeah, i know, it's a very "fun" feature
i thought []! arrays still had internal V structure like cap and whatnot, just that they pointed to data preallocated on the stack
therefore it would make sense to have one with length of 0, because i'd agree that passing a C struct of 0 size to a function directly is wrong
but i guess they are actually plain C arrays
that complicates things
since the functions i pass them to check for the length of the array, but in this case they cannot
i fixed it by just using a variable and freeing that
a bit ugly but works
@upbeat crest could you please take a look at why your interface cast fix doesn't work even with -experimental?
Sure. Will be home in 15
aight
works for me
main__Resource* resource = /*nili*/((void*)0);
what's your code?
that would mean using alloca?
i mean i do escape analysis and still need to use alloca to allocate it on stack
alloca bad
exactly
always
you can, however, make arrays by-value
i guess
and a zero length array is codegenned into an empty struct
and crucially, a slice can be coerced from a pointer to an array
that just has cap=len
and then escape analysis on that to move it to stack if it's okay
and a slice literal is just
make an array
and slice it
@orchid tartan can you paste your code that resulted in an interface cast alloc
oh yeah sorry i forgot, one sec, let me double check that i'm not saying stupid things
i figured the issue out
the allocation happens when i cast from voidptr(0) instead of unsafe { nil }
no problem, i'll just change it all to unsafe { nil }
that makes sense, it only checks for unsafe{nil} or just nil
i think nil should always be used instead of voidptr(0)
i see
i can update vfmt to replace it with nil
we could yeah
i can also do it manually with a sed
it should be a relatively safe thing to do
we gonna build a GC in pure V this year and replace boehm with it
or at least provide it as an option (-gc new) until its super stable
boehm doesn't compile with tcc on all platforms, and that's an issue
@orchid tartan v:freed via comments is hard to add, also comments are not safe (not checked, typos etc)
what about attributes?
x := [1,2,3] @[freed]
in the future [] will be removed
and it'll just be
x := [1,2,3] @freed
that sounds cool!
i think that's a better idea, lang-design wise
yeah me too
attributes sounds good
i do not have strong preferences as long as the general jist of it as is the same
might be easier to parse a prefix attribute though? unless you already have some suffix ones already
hm
and it lines up with other attributes more (e.g. function attributes)
also, note that the reason e.g. rust has [] around the name is because of operator precedence
because you could reasonably do like, @foo (3 + 4)
and then is it @foo(3+4) 5 or @foo (3 + 4);, you don't know until you parse the rest which is unfun
yeah and i want to make it like # in python
entire line after @ is an attribute
that matters if you have parametrized ones though
huh, why?
to avoid extra() []
okay fair enough
you could force @[] around parameter-having attributes only though
and @foo is then always unambigously parameter-free
yeah good idea
but isn't @ already used to disambiguate identifiers from keywords?
that will be removed
@orchid tartan lol i just made a 200 line GC in pure V that's only 2.5x slower than boehm and Go's GC (which both perform the same)
Go's GC has a better algo than boehm, but Clang's -O2 is a better optimizer
Custom GC benchmark completed in 125.95225ms
Boehm GC benchmark completed in 53.423 ms
Go's GC benchmark completed in 50.614583ms
this is insane:
Custom GC benchmark completed in 177.99275ms```
I'm almost at Go level
will need more advanced tests, perhaps I'm missing something
interesting
i think i will still stick to manual memory management for the reasons we've already discussed though
sure, V needs it in general
boehm doesn't compile with tcc on macos
There are a lot of different things to measure like how well the GC responds to spikes in allocations and pressure, how well it handles a bunch of objects that are alive, how it handles a bunch of objects that are dead, how it handles multi-threading (and constantly changing mutators state)
There are some common tests that people use to test both single core and multi core, obv you would need to port the tests since I think they are mostly written for java
and how bad your gc pauses are
That's where optimizing for single core and multi core differs
Or well, single thread or multi thread
@orchid tartan new statement attrs and @[freed] will be available today
was a big project
awesome!
done, you can pull from here https://github.com/medvednikov/v2
will be live on vlang/v within ~2 hours (after tests)
fn foo() {
x := [1, 2, 3] @[freed]
unsafe {
x.free()
}
println('x is freed')
}
i decided to make it a suffix attribute
similar to our suffix attrs for struct fields (like in Go), and takes less space, less invasive than
@[freed]
x := [1, 2, 3]
fwiw that's a massive margin
it has bugs, so performance will drop most likely, we'll see
i'd be happy with 3x slower
3x is like, v -js margin isn't it
@upbeat crest banter muted me in the Vinix discord lol
also, that banter is EOL, you may wanna kick it and either replace it with @strange hornet or just have no such bot
banter2 ftw
ok
@upbeat crest hey, if you add me on this new discord it would be nice
it would also be nice if we could continue working on Vinix!!
i miss working on the project, i have such a big backlog of fixes and improvements
@lilac pewter remind me to add uacpi
whenever i can work on this
i need to make all the bindings ๐ญ
letsgo
at least it will be way less painful than Ada
Cynix dead?
hm no
yeah same
funding should come at the end of February, fingers crossed
which one?
this very account
ok, what happened to your old one?
i wanted a bit of a clean break so i moved to a new account (which already existed, it was just dormant)
FR sent
accepted, thanks!
i made it so interrupts are automatically disabled on spinlocks and it increased stability significantly
i still need to diagnose the memory leak(s) and an issue with the scheduler where stuff seems to be descheduled randomly (but it may also be an event system issue)
wait, if your spinlocks used to not disable interrupts, what were they used for?
poor man's mutexes
synchronizing between different cores?
i am not even sure myself
Vinix does not have mutexes, only spinlocks
which are used for synchr
ah
it's honestly fast enough like this rn
with just spinlocks (but disabling interrupts)
or rather
when i say fast enough i don't mean that i don't want mutexes
it might become a bottleneck at some point, to be honest
but if you arent heavily contending them
especially with a lot of interrupts
there's no real penalty
also yes contention
and enabling/disabling interrupts is really pricey
this is more of a band aid to make it not crap the bed when you blow on it
it probably increased stability because something somewhere incorrectly wrote to state shared with interrupt handlers
the idea is to replace the spinlocks with more granular mutexes once stability is achieved
me when the (when the)
Damn
nice!
nice
nice
@glad peak
ty lol
not that hard tbh
it kinda looks like Go
but not really
it's fast to compile if you use a lightweight backend yes
Rust in shambles crying and screaming
@upbeat crest how can one use an enum from C in V?
something like enum C.whatever {} doesn't seem to work
@lilac pewter i encountered the first roadblock
trying to get enums to play nice
cc @candid yoke
Isnt that kinda the most basic c thing
Damn very few lines too
Btw u aren't calling namespace initialize etc
checking
@wild halo hm using a virtual C.enum would still require defining the values
so I'd just translate it with v translate
and use a V enum
once v translate is fully integrated into #include "foo.h" (right now it only translates function defs), it won't be necessary
with the changes from today, type C.EnumName = int could work potentially
interesting thanks, i just solved by not including the C header at all
and using different types, that way the compiler didn't complain...
...not ideal, but works
@wild halo i think it's the most liked tweet ๐
Congrats, that's p cool
ah! amazing, i am glad to hear
@upbeat crest why does V not autogenerate function prototypes for external C functions?
it seems like it would make more sense than plain #includeing headers manually, which at the end of the day don't really matter because V doesn't really parse them
plus they only really work on the C backend and not any other hypothetical backend like the native one
imho V should just rely on the user provided interface by means of actual V code (and autoemit prototypes in the C backend)
it seems like a significantly sounder design, unless i am missing something
i also understand that dropping #include now may be an issue if a lot of things rely on it, but one could opt into the new behaviour (or alternatively opt out of it if made default)
one thing the new behaviour would also help with is binding functions that have prototypes that V doesn't necessarily play nice with, but would be very cleanly bound by relying on V code only and emit a C prototype based on that
something like #592294828432424960 message comes to mind
the aforementioned workaround was me literally not including the C header, but of course that is not ideal without proper prototypes being emitted
it does with v -experimental
#includes are translated with c2v then
hm
what i am saying is more akin to "why are includes necessary at all to begin with"
like i'd rather not have includes and/or V attempt to autotranslate them, perhaps unreliably
i just want V to create (very easily) prototypes based on my function definition for interfacing with C
(for the C backend)
for the native backend it doesn't even need the step of creating the prototypes, it should already know by default
btw this is how it works in most other languages like Ada
( @upbeat crest )
how would that look like?
C.myfunction(arg0 voidptr, arg1 u64, arg2 u32) bool
->
bool myfunction(void *arg0, uint64_t arg1, uint32_t arg2);```
you can already do that with
fn myfunction(arg0 voidptr, arg1 u64, arg2 u32) bool
just the definition
wouldn't the prototype end up being somemodule__myfunction?
@upbeat crest error: cannot call a function that does not have a body
i have been working on Vinix though
i have been reworking refcounting and that's annoying to debug and tedious
hence why not that many other commits
but it should make the system more stable
fair
sounds fun /s
i meant with sacrasm lol
sorry shouldve added a tone indicator or smt
oops
nah my bad
@wild halo please see if https://github.com/vlang/v/blob/master/vlib/v/gen/c/testdata/c_extern_on_C_fn_declarations.vv is suitable for your needs.
The TDLR is that:
@[c_extern] fn C.GifErrorString(ecode int) &char
generates:
extern char* GifErrorString(int ecode);
but it does not generate a separate .h file, the prototypes are still part of the .c file
we could add another tag, that could add them to a separate .h file, but it is not clear to me, how it should be named, and should that be parametrizable etc
if you have link(s) to info, about how other language do what you need, please post them
extern <function decl> is basically how most languages do that
so @[c_extern] <function decl> is pretty much what i'd expect from V
no, that's fine, i did intend that
thanks, this seems to do what i wanted
one slight suggestion i have is to allow @[import: 'c_function_name']
you already have @[export: 'c_function_name']
which allows a V function to be available via a C symbol name (as well as the V function name)
while this c_extern is fine for what i needed, i think it would be prettier to have import, which then allows you to define a V function name, available properly via a module, without C. prefix
often C functions have libraryname_whatever prepended to it, which in V can turn into libraryname.libraryname_whatever which is annoying
the import mechanism solves this
(and yes, i tried it and it doesn't work)
personally, if added, i'd remove c_extern entirely as it is just redundant and worse
here's an example of export
just to show how sensible adding import would be
@upbeat crest @tender hornet 5439ff9cdebb3072a015cc0166206e90d6c1034a breaks Vinix
also please note what i said above, i think it would be a great improvement to V
why?
well that i am not sure
it was working before, now it isn't, and i bisected V to that commit being the issue
do you have a pub fn (mut a []string) free() { method in builtin?
previously it was not used
no i don't have that, i am also not sure what that means exactly, sorry
the commit passed on the V CI, but it only builds vinix, it does not run it
yeah, it builds fine
the issue is at runtime
should've specified
i didn't debug that yet, specifically
i will generate C output from the 2 commits and compare it guess?
before that commit, V called pub fn (a &array) free() {, so if you had a := ['abc', 'def'] for example, and used -autofree, the generated a.free() call would have freed only the memory for a itself, but not for the elements; after that commit, it frees first the elements, and then the array too
so what happens could be that i have a call to .free() for the strings inside first, then for the array
would that result in a double free?
yes
after that commit, the loop that frees the elements is not needed anymore
since it is done inside the a.free() call
if you want, I can add a -d do_not_free_strings_in_array switch to restore the old behavior for now?
i'd rather understand the actual issue
the diff isn't huge
it's mainly only a couple of calls to array_free being replaced with Array_string_free
yes, Array_string_free does a loop to free the elements first
i fixed it
it was indeed about this issue in a spot in the kernel
btw
do you think it is possible to use a longer version of the commit hash in the commit messages of vc?
it only uses 7 characters but that could lead to collisions i think, given the amount of commits in v
yes, afaik they are not read by humans, only by automated systems
what do you think is a reasonable count?
the full commit?
the full commit would be perfect because there is no chance of collision
@upbeat crest what do you think?
else i guess something like 9 or 10? idk if there is a way to ask git how long the commit hash should be to have no collisions
can we replace the hash in the messages with the full one?
i am saying this because i am automating pulling the right vc commit based on the v commit now, as seen in that commit above
i used this to make bisecting much easier
but i was always concerned about the possibility of collisions
afaik we do not shorten the hash ourselves, but use the result of git rev-parse --short HEAD
I'll have to see what its documentation is
I think that command guarantees that there will be no collisions, the output will be just longer if there would be:
https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt---shortltlengthgt
Same as --verify but shortens the object name to a unique prefix with at least length characters. The minimum length is 4, the default is the effective value of the core.abbrev configuration variable (see git-config[1]).
but using the full hash is better for automation anyways
I've changed it - see https://github.com/vlang/vc/commits/master/
happy to help when I can
i'm fine with 9
ah you did the full ones already
ok
full ones are way better
@upbeat crest @tender hornet it would be nice if, alongside labelled break/continue, you could support something like break 2
where 2 means to break to the 2nd level of loop
so it's unnecessary to manually label loops
so break without an argument is equivalent to break 1, then break 2, 3, and so on
__global (
freelist_head = &u64(unsafe { nil })
)
fn freelist_free(page u64) {
unsafe {
mut ptr := &u64(page + higher_half)
*ptr = freelist_head
freelist_head = ptr
}
}```
why would freelist_head get automatically dereferenced in *ptr = freelist_head?
like i get that i should be casting it to u64
but i would expect an error or warning rather than it silently dereferencing the var
you're right
should be an error
report via github please
will fix today
wouldn't this mess up if more levels are added
i think readability would suffer compared to labels
depends? it would still refer to the loop containing the current loop, it is up to the user to make sure it makes sense, like many other things in code
the readability argument is matter of taste i guess, i personally find labels to be too cluttering but i accept a differing opinion
it's not a big deal, just a suggestion
alright will do
i think the other thing this messes with is the ability to use break <value> like rust and zig can
(where you can break a loop with a specific value)
though i guess they both have special syntax for labels to disambiguate?
@upbeat crest https://github.com/vlang/v/issues/23991
Describe the bug V should error out on wrong code that does not properly cast, but, instead, it generates broken code, and, in non-prod, merely generates a warning. In prod it errors out due to tha...
uacpi type system 
it's more about the dereference semantics being a bit wishy washy in V sometimes
but this at least had a warning
V has auto (de)reference which i'm going to remove for unsafe
and maybe for everything
V 0.4.10 is out! 400+ items in the changelog!
awesome!
@wild halo I fixed it: #592320321995014154 message
will be merged after tests pass
soon
thanks!
merged finally
had to fix a lot of stuff
thanks, i'll update Vinix shortly
i'm glad this fix allowed you to fix bugs on the V side too

Vinix more like goneix
@wild halo I've added arm64 support to Vinix
Vinix is back to life???
