Skip to content

Commit

Permalink
New ops for unsigned native int results in dispatch
Browse files Browse the repository at this point in the history
  • Loading branch information
niner committed Mar 4, 2022
1 parent 80fca1a commit 1001613
Show file tree
Hide file tree
Showing 16 changed files with 885 additions and 429 deletions.
608 changes: 318 additions & 290 deletions lib/MAST/Ops.nqp

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions src/core/args.c
Expand Up @@ -778,6 +778,50 @@ void MVM_args_set_result_int(MVMThreadContext *tc, MVMint64 result, MVMint32 fra
}
}

void MVM_args_set_result_uint(MVMThreadContext *tc, MVMuint64 result, MVMint32 frameless) {
MVMFrame *target;
if (frameless) {
target = tc->cur_frame;
}
else {
if (MVM_spesh_log_is_caller_logging(tc))
MVM_spesh_log_return_type(tc, NULL);
else if (MVM_spesh_log_is_logging(tc))
MVM_spesh_log_return_to_unlogged(tc);
target = tc->cur_frame->caller;
}
if (target) {
switch (target->return_type) {
case MVM_RETURN_VOID:
if (tc->cur_frame->static_info->body.has_exit_handler)
save_for_exit_handler(tc,
MVM_repr_box_int(tc, MVM_hll_current(tc)->int_box_type, result));
break;
case MVM_RETURN_INT:
target->return_value->i64 = result;
break;
case MVM_RETURN_UINT:
target->return_value->u64 = result;
break;
case MVM_RETURN_NUM:
target->return_value->n64 = (MVMnum64)result;
break;
case MVM_RETURN_OBJ: {
/* dereference target first to avoid GC issue */
MVMRegister *return_value = (frameless ? tc->cur_frame : tc->cur_frame->caller)->return_value;
autobox_int(tc, target, result, return_value->o);
break;
}
case MVM_RETURN_ALLOMORPH:
target->return_type = MVM_RETURN_UINT;
target->return_value->u64 = result;
break;
default:
MVM_exception_throw_adhoc(tc, "Result return coercion from uint NYI; expects type %u", target->return_type);
}
}
}

void MVM_args_set_dispatch_result_int(MVMThreadContext *tc, MVMFrame *target, MVMint64 result) {
switch (target->return_type) {
case MVM_RETURN_VOID:
Expand Down
1 change: 1 addition & 0 deletions src/core/args.h
Expand Up @@ -121,6 +121,7 @@ void MVM_args_assert_nameds_used(MVMThreadContext *tc, MVMArgProcContext *ctx);
/* Result setting. */
void MVM_args_set_result_obj(MVMThreadContext *tc, MVMObject *result, MVMint32 frameless);
void MVM_args_set_result_int(MVMThreadContext *tc, MVMint64 result, MVMint32 frameless);
void MVM_args_set_result_uint(MVMThreadContext *tc, MVMuint64 result, MVMint32 frameless);
void MVM_args_set_result_num(MVMThreadContext *tc, MVMnum64 result, MVMint32 frameless);
void MVM_args_set_result_str(MVMThreadContext *tc, MVMString *result, MVMint32 frameless);
void MVM_args_assert_void_return_ok(MVMThreadContext *tc, MVMint32 frameless);
Expand Down
162 changes: 162 additions & 0 deletions src/core/coerce.c
Expand Up @@ -490,6 +490,168 @@ MVMint64 MVM_coerce_s_i(MVMThreadContext *tc, MVMString *str) {
return result;
}

MVMuint64 MVM_coerce_s_u(MVMThreadContext *tc, MVMString *str) {
MVMStringIndex strgraphs = MVM_string_graphs(tc, str);
MVMuint64 result = 0;
MVMint32 any = 0, negative = 0;

signed long long cutoff;
MVMint32 cutlim;

if (!strgraphs)
return result;

/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* copied from https://github.com/gcc-mirror/gcc/blob/0c0f453c4af4880c522c8472c33eef42bee9eda1/libiberty/strtoll.c
* with minor modifications to simplify and work in MoarVM
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
if (str->body.storage_type == MVM_STRING_GRAPHEME_ASCII) {
const MVMGraphemeASCII *s = str->body.storage.blob_ascii;
MVMStringIndex i = 0;
MVMGraphemeASCII c;
do {
c = *s++;
++i;
/* The original C code was processing a NUL terminated string, hence
* it could always be sure that it could read a value into c for
* which isspace(c) was false, and so for a string entirely
* whitespace this loop would terminate with c == 0 (without reading
* beyond the end) and the code below would behave correctly too.
*
* Instead we can use the length test to terminate the loop
* unconditionally just after we read the last character. This would
* be for strings which are entirely whitespace - eg " ", " " etc.
* They all return 0, and we don't need to optimise their handling,
* so we simply drop through into the rest of the code with c == ' '
* for them. */
/* isspace(...) is any of "\t\n\v\f\r ", ie [9 .. 13, 32] */
} while (i != strgraphs && (c == ' ' || (c >= '\t' && c <= '\r')));

/* `i` counts how many octets we have read. Hence `i == strgraphs` at
* the point where `c` holds the final ASCII character of the string,
* and there is no more to read. */
if (c == '-') {
negative = 1;
if (i++ == strgraphs)
return 0;
c = *s++;
} else if (c == '+') {
if (i++ == strgraphs)
return 0;
c = *s++;
}

cutoff = negative ? -(unsigned long long)LLONG_MIN : LLONG_MAX;
cutlim = cutoff % (unsigned long long)10;
cutoff /= (unsigned long long)10;

while (1) {
if (c >= '0' && c <= '9')
c -= '0';
else
break;

if (any < 0 || result > cutoff || (result == cutoff && c > cutlim))
any = -1;
else {
any = 1;
result *= 10;
result += c;
}
if (i++ == strgraphs)
break;
c = *s++;
}

if (any < 0)
result = negative ? LLONG_MIN : LLONG_MAX;
else if (negative)
result = -result;
}
else {
MVMCodepointIter ci;
MVM_string_ci_init(tc, &ci, str, 0, 0);
MVMCodepoint ord;

do {
ord = MVM_string_ci_get_codepoint(tc, &ci);
} while ((ord == ' ' || (ord >= '\t' && ord <= '\r')) && MVM_string_ci_has_more(tc, &ci));

if (ord == '-') {
negative = 1;
if (!MVM_string_ci_has_more(tc, &ci))
return 0;
ord = MVM_string_ci_get_codepoint(tc, &ci);
}
else if (ord == '+') {
if (!MVM_string_ci_has_more(tc, &ci))
return 0;
ord = MVM_string_ci_get_codepoint(tc, &ci);
}

cutoff = negative ? -(unsigned long long)LLONG_MIN : LLONG_MAX;
cutlim = cutoff % (unsigned long long)10;
cutoff /= (unsigned long long)10;

while (1) {
if (ord >= '0' && ord <= '9')
ord -= '0';
else
break;

if (any < 0 || result > cutoff || (result == cutoff && ord > cutlim))
any = -1;
else {
any = 1;
result *= 10;
result += ord;
}
if (!MVM_string_ci_has_more(tc, &ci))
break;
ord = MVM_string_ci_get_codepoint(tc, &ci);
};

if (any < 0)
result = negative ? LLONG_MIN : LLONG_MAX;
else if (negative)
result = -result;
}

if (negative) {
MVM_exception_throw_adhoc(tc, "Cannot coerce negative number from string to native unsigned integer");
}

return result;
}

MVMint64 MVM_coerce_simple_intify(MVMThreadContext *tc, MVMObject *obj) {
/* Handle null and non-concrete case. */
if (MVM_is_null(tc, obj) || !IS_CONCRETE(obj)) {
Expand Down
1 change: 1 addition & 0 deletions src/core/coerce.h
Expand Up @@ -8,6 +8,7 @@ MVMString * MVM_coerce_n_s(MVMThreadContext *tc, MVMnum64 n);

/* Numification. */
MVMint64 MVM_coerce_s_i(MVMThreadContext *tc, MVMString *s);
MVMuint64 MVM_coerce_s_u(MVMThreadContext *tc, MVMString *s);
MVMint64 MVM_coerce_simple_intify(MVMThreadContext *tc, MVMObject *obj);
MVMObject* MVM_radix(MVMThreadContext *tc, MVMint64 radix, MVMString *str, MVMint64 offset, MVMint64 flag);

Expand Down
93 changes: 87 additions & 6 deletions src/core/interp.c
Expand Up @@ -549,6 +549,12 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
if (MVM_frame_try_return(tc) == 0)
goto return_label;
goto NEXT;
OP(return_u):
MVM_args_set_result_uint(tc, GET_REG(cur_op, 0).u64,
MVM_RETURN_CALLER_FRAME);
if (MVM_frame_try_return(tc) == 0)
goto return_label;
goto NEXT;
OP(return_n):
MVM_args_set_result_num(tc, GET_REG(cur_op, 0).n64,
MVM_RETURN_CALLER_FRAME);
Expand Down Expand Up @@ -951,6 +957,10 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
GET_REG(cur_op, 0).i64 = MVM_coerce_s_i(tc, GET_REG(cur_op, 2).s);
cur_op += 4;
goto NEXT;
OP(coerce_su):
GET_REG(cur_op, 0).u64 = MVM_coerce_s_u(tc, GET_REG(cur_op, 2).s);
cur_op += 4;
goto NEXT;
OP(coerce_sn):
GET_REG(cur_op, 0).n64 = MVM_coerce_s_n(tc, GET_REG(cur_op, 2).s);
cur_op += 4;
Expand Down Expand Up @@ -5396,6 +5406,22 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
tc->cur_frame->static_info, bytecode_offset);
goto NEXT;
}
OP(dispatch_u): {
MVMDispInlineCacheEntry **ice_ptr = MVM_disp_inline_cache_get(
cur_op, bytecode_start, tc->cur_frame);
MVMDispInlineCacheEntry *ice = *ice_ptr;
MVMString *id = MVM_cu_string(tc, cu, GET_UI32(cur_op, 2));
MVMCallsite *callsite = cu->body.callsites[GET_UI16(cur_op, 6)];
MVMuint16 *args = (MVMuint16 *)(cur_op + 8);
MVMuint32 bytecode_offset = (cur_op - bytecode_start) - 2;
tc->cur_frame->return_value = &GET_REG(cur_op, 0);
tc->cur_frame->return_type = MVM_RETURN_UINT;
cur_op += 8 + 2 * callsite->flag_count;
tc->cur_frame->return_address = cur_op;
ice->run_dispatch(tc, ice_ptr, ice, id, callsite, args, tc->cur_frame->work,
tc->cur_frame->static_info, bytecode_offset);
goto NEXT;
}
OP(dispatch_n): {
MVMDispInlineCacheEntry **ice_ptr = MVM_disp_inline_cache_get(
cur_op, bytecode_start, tc->cur_frame);
Expand Down Expand Up @@ -5804,6 +5830,23 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
sf, -1);
goto NEXT;
}
OP(sp_dispatch_u): {
MVMString *id = MVM_cu_string(tc, cu, GET_UI32(cur_op, 2));
MVMCallsite *callsite = cu->body.callsites[GET_UI16(cur_op, 6)];
MVMStaticFrame *sf = (MVMStaticFrame *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 8)];
MVMDispInlineCacheEntry **ice_ptr = MVM_disp_inline_cache_get_spesh(sf,
GET_UI32(cur_op, 10));
MVMDispInlineCacheEntry *ice = *ice_ptr;
MVMuint16 *args = (MVMuint16 *)(cur_op + 14);
tc->cur_frame->return_value = &GET_REG(cur_op, 0);
tc->cur_frame->return_type = MVM_RETURN_UINT;
cur_op += 14 + 2 * callsite->flag_count;
tc->cur_frame->return_address = cur_op;
ice->run_dispatch(tc, ice_ptr, ice, id, callsite, args, tc->cur_frame->work,
sf, -1);
goto NEXT;
}
OP(sp_dispatch_n): {
MVMString *id = MVM_cu_string(tc, cu, GET_UI32(cur_op, 2));
MVMCallsite *callsite = cu->body.callsites[GET_UI16(cur_op, 6)];
Expand Down Expand Up @@ -6468,6 +6511,21 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
MVM_frame_dispatch(tc, code, args, spesh_cand);
goto NEXT;
}
OP(sp_runbytecode_u): {
MVMCode *code = (MVMCode *)GET_REG(cur_op, 2).o;
MVMint16 spesh_cand = GET_I16(cur_op, 12);
MVMArgs args = {
.callsite = (MVMCallsite *)GET_UI64(cur_op, 4),
.source = reg_base,
.map = (MVMuint16 *)(cur_op + 14)
};
tc->cur_frame->return_value = &GET_REG(cur_op, 0);
tc->cur_frame->return_type = MVM_RETURN_UINT;
cur_op += 14 + 2 * args.callsite->flag_count;
tc->cur_frame->return_address = cur_op;
MVM_frame_dispatch(tc, code, args, spesh_cand);
goto NEXT;
}
OP(sp_runbytecode_n): {
MVMCode *code = (MVMCode *)GET_REG(cur_op, 2).o;
MVMint16 spesh_cand = GET_I16(cur_op, 12);
Expand Down Expand Up @@ -6540,6 +6598,20 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
code->body.func(tc, args);
goto NEXT;
}
OP(sp_runcfunc_u): {
MVMCFunction *code = (MVMCFunction *)GET_REG(cur_op, 2).o;
MVMArgs args = {
.callsite = (MVMCallsite *)GET_UI64(cur_op, 4),
.source = reg_base,
.map = (MVMuint16 *)(cur_op + 12)
};
tc->cur_frame->return_value = &GET_REG(cur_op, 0);
tc->cur_frame->return_type = MVM_RETURN_UINT;
cur_op += 12 + 2 * args.callsite->flag_count;
tc->cur_frame->return_address = cur_op;
code->body.func(tc, args);
goto NEXT;
}
OP(sp_runcfunc_n): {
MVMCFunction *code = (MVMCFunction *)GET_REG(cur_op, 2).o;
MVMArgs args = {
Expand Down Expand Up @@ -6611,6 +6683,21 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
MVM_nativecall_dispatch(tc, result_type, site, args);
goto NEXT;
}
OP(sp_runnativecall_u): {
MVMObject *site = GET_REG(cur_op, 2).o;
MVMArgs args = {
.callsite = (MVMCallsite *)GET_UI64(cur_op, 4),
.source = reg_base,
.map = (MVMuint16 *)(cur_op + 12)
};
MVMObject *result_type = GET_REG(cur_op, 12).o;
tc->cur_frame->return_value = &GET_REG(cur_op, 0);
tc->cur_frame->return_type = MVM_RETURN_UINT;
cur_op += 12 + 2 * args.callsite->flag_count;
tc->cur_frame->return_address = cur_op;
MVM_nativecall_dispatch(tc, result_type, site, args);
goto NEXT;
}
OP(sp_runnativecall_n): {
MVMObject *site = GET_REG(cur_op, 2).o;
MVMArgs args = {
Expand Down Expand Up @@ -6705,12 +6792,6 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
* even though the op numbers are technically out of order. */
OP(DEPRECATED_6):
MVM_exception_throw_adhoc(tc, "The getregref_* ops were removed in MoarVM 2017.01.");
OP(DEPRECATED_22):
MVM_exception_throw_adhoc(tc, "The readall_fh op was removed in MoarVM 2017.06.");
OP(DEPRECATED_23):
MVM_exception_throw_adhoc(tc, "The read_fhs op was removed in MoarVM 2017.06.");
OP(DEPRECATED_24):
MVM_exception_throw_adhoc(tc, "The setinputlinesep op was removed in MoarVM 2017.06.");
OP(DEPRECATED_25):
MVM_exception_throw_adhoc(tc, "The setinputlineseps op was removed in MoarVM 2017.06.");
OP(DEPRECATED_27):
Expand Down

0 comments on commit 1001613

Please sign in to comment.