-
Notifications
You must be signed in to change notification settings - Fork 114
Add binary_part/3
to BIFs
#1569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the NIF function can be completely dropped.
A number of CI fixes has been made in release-0.6. Let's rebase it on latest release-0.6. |
cac7b78
to
0b91671
Compare
src/libAtomVM/opcodesswitch.h
Outdated
*return_value = gcbif->gcbif1_ptr(ctx, 0, 1, ctx->x[0]); | ||
return true; | ||
} | ||
case 2: { | ||
*return_value = gcbif->gcbif2_ptr(ctx, 0, 0, ctx->x[0], ctx->x[1]); | ||
*return_value = gcbif->gcbif2_ptr(ctx, 0, 2, ctx->x[0], ctx->x[1]); | ||
return true; | ||
} | ||
case 3: { | ||
*return_value = gcbif->gcbif3_ptr(ctx, 0, 0, ctx->x[0], ctx->x[1], ctx->x[2]); | ||
*return_value = gcbif->gcbif3_ptr(ctx, 0, 3, ctx->x[0], ctx->x[1], ctx->x[2]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll rebase after #1610 is merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need this, see my other comments.
src/libAtomVM/bif.c
Outdated
RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM); | ||
} | ||
|
||
return term_maybe_create_sub_binary(ctx->x[0], slice.pos, slice.len, &ctx->heap, ctx->global); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be arg1, not ctx->x[0]
src/libAtomVM/bif.c
Outdated
RAISE_ERROR_BIF(fail_label, BADARG_ATOM); | ||
} | ||
|
||
if (UNLIKELY(memory_ensure_free_with_roots(ctx, slice.heap_size, live, ctx->x, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to add arg1 to ctx->[live], and pass live+1 with a comment saying you can do that because x has size MAX_REGS+1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand. If live
is always zero, we'd clobber x[1]
in that case and preserve nothing since roots length is still 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the confusion.
I meant:
if (UNLIKELY(memory_ensure_free_with_roots(ctx, slice.heap_size, live, ctx->x, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { | |
// We can always use ctx->x[live] as ctx->x has MAX_REGS+1 slots | |
ctx->x[live] = arg1; | |
if (UNLIKELY(memory_ensure_free_with_roots(ctx, slice.heap_size, live + 1, ctx->x, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { |
If live
is 0, you can clobber x[1]. This is what live
being 0 means.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the implementation then. In maybe_call_native
we hardcode live=0
. It's used in tail-calls (which is fine) and in apply
. Why it's fine to clobber registers in apply
case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it's fine to clobber x regs in any NIF or external calls. My understanding is that x regs are used for args and results for NIF or external calls, and they do not need to be preserved. It is as if live was equal to 0. Caller does not even ensure that they are valid beyond argc. On return, only x[0] is considered valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @pguyot, it works with both NIFs and BIFs.
src/libAtomVM/opcodesswitch.h
Outdated
*return_value = gcbif->gcbif1_ptr(ctx, 0, 1, ctx->x[0]); | ||
return true; | ||
} | ||
case 2: { | ||
*return_value = gcbif->gcbif2_ptr(ctx, 0, 0, ctx->x[0], ctx->x[1]); | ||
*return_value = gcbif->gcbif2_ptr(ctx, 0, 2, ctx->x[0], ctx->x[1]); | ||
return true; | ||
} | ||
case 3: { | ||
*return_value = gcbif->gcbif3_ptr(ctx, 0, 0, ctx->x[0], ctx->x[1], ctx->x[2]); | ||
*return_value = gcbif->gcbif3_ptr(ctx, 0, 3, ctx->x[0], ctx->x[1], ctx->x[2]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need this, see my other comments.
src/libAtomVM/opcodesswitch.h
Outdated
@@ -1612,15 +1612,15 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f | |||
const struct GCBif *gcbif = EXPORTED_FUNCTION_TO_GCBIF(exported_bif); | |||
switch (arity) { | |||
case 1: { | |||
*return_value = gcbif->gcbif1_ptr(ctx, 0, 0, ctx->x[0]); | |||
*return_value = gcbif->gcbif1_ptr(ctx, 0, 1, ctx->x[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, since we have another open discussion on this topic, and the issue we experienced here turned out to be something different (did I understood this right?), I suggest removing this change from here and making this PR focused on just binary_part.
Let's move forward with binary_part, and let's have an additional (but separated) discussion about live parameter when doing the NIF trick on that specific PR. |
0b91671
to
ec4baea
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with this approach, it is a matter of polishing. Correct naming and placing functions in the right place is important to keep everything maintainable.
src/libAtomVM/bif.c
Outdated
@@ -108,6 +108,48 @@ term bif_erlang_bit_size_1(Context *ctx, uint32_t fail_label, int live, term arg | |||
return term_from_int32(len); | |||
} | |||
|
|||
bool get_sub_binary_slice(term bin_term, term pos_term, term len_term, struct SubBinarySlice *slice) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name didn't suggest me the purpose of this function without looking at the actual implementation. What about maybe_get_sub_binary_slice
or even sanitize_sub_binary_slice
.
Furthermore,
- we keep prefixing "public" function names, so a "public" function declared in
bif.h
is named such asbif_sanitize_sub_binary_slice
. - I would keep this function in term.h, since it is a common helper between nifs and bifs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be even a more reusable API if take indexes as avm_int_t, so we might use it internally in other situations.
src/libAtomVM/bif.h
Outdated
@@ -39,11 +39,20 @@ extern "C" { | |||
|
|||
#define MAX_BIF_NAME_LEN 260 | |||
|
|||
struct SubBinarySlice |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using this struct only as an output of get_sub_binary_slice
, so we might link better the 2 names when we rename the function. It might be called SlicedBinary
or SanitizedSlice
or whatever we'll use as new name.
Also let's not forget to do the typedef trick, so we don't have to use all around struct
SubBinarySlice foo_bar;
Signed-off-by: Jakub Gonet <[email protected]>
ec4baea
to
19395fa
Compare
return pos_len.pos == -1 && pos_len.len == -1; | ||
} | ||
|
||
static inline BinaryPosLen term_invalid_binary_pos_len(void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, last minute review: term_is_invalid_binary_pos_len
and term_invalid_binary_pos_len
are unused, let's remove them.
Also, for the future: it is not necessary having (void)
for functions with no parameters. ()
is ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, forget my last comment. I didn't notice this was required for #1621
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later