mirror of
https://github.com/janet-lang/janet
synced 2025-01-12 16:40:27 +00:00
Inlining for all built in comparators.
This commit is contained in:
parent
b860b0a3c5
commit
1acd2d1de7
@ -76,6 +76,7 @@ static const DstInstructionDef dst_ops[] = {
|
|||||||
{"eq", DOP_EQUALS},
|
{"eq", DOP_EQUALS},
|
||||||
{"eqi", DOP_EQUALS_INTEGER},
|
{"eqi", DOP_EQUALS_INTEGER},
|
||||||
{"eqim", DOP_EQUALS_IMMEDIATE},
|
{"eqim", DOP_EQUALS_IMMEDIATE},
|
||||||
|
{"eqn", DOP_NUMERIC_EQUAL},
|
||||||
{"eqr", DOP_EQUALS_REAL},
|
{"eqr", DOP_EQUALS_REAL},
|
||||||
{"err", DOP_ERROR},
|
{"err", DOP_ERROR},
|
||||||
{"get", DOP_GET},
|
{"get", DOP_GET},
|
||||||
@ -83,7 +84,9 @@ static const DstInstructionDef dst_ops[] = {
|
|||||||
{"gt", DOP_GREATER_THAN},
|
{"gt", DOP_GREATER_THAN},
|
||||||
{"gti", DOP_GREATER_THAN_INTEGER},
|
{"gti", DOP_GREATER_THAN_INTEGER},
|
||||||
{"gtim", DOP_GREATER_THAN_IMMEDIATE},
|
{"gtim", DOP_GREATER_THAN_IMMEDIATE},
|
||||||
|
{"gtn", DOP_NUMERIC_GREATER_THAN},
|
||||||
{"gtr", DOP_GREATER_THAN_REAL},
|
{"gtr", DOP_GREATER_THAN_REAL},
|
||||||
|
{"gten", DOP_NUMERIC_GREATER_THAN_EQUAL},
|
||||||
{"gter", DOP_GREATER_THAN_EQUAL_REAL},
|
{"gter", DOP_GREATER_THAN_EQUAL_REAL},
|
||||||
{"jmp", DOP_JUMP},
|
{"jmp", DOP_JUMP},
|
||||||
{"jmpif", DOP_JUMP_IF},
|
{"jmpif", DOP_JUMP_IF},
|
||||||
@ -99,7 +102,9 @@ static const DstInstructionDef dst_ops[] = {
|
|||||||
{"lt", DOP_LESS_THAN},
|
{"lt", DOP_LESS_THAN},
|
||||||
{"lti", DOP_LESS_THAN_INTEGER},
|
{"lti", DOP_LESS_THAN_INTEGER},
|
||||||
{"ltim", DOP_LESS_THAN_IMMEDIATE},
|
{"ltim", DOP_LESS_THAN_IMMEDIATE},
|
||||||
|
{"ltn", DOP_NUMERIC_LESS_THAN},
|
||||||
{"ltr", DOP_LESS_THAN_REAL},
|
{"ltr", DOP_LESS_THAN_REAL},
|
||||||
|
{"lten", DOP_NUMERIC_LESS_THAN_EQUAL},
|
||||||
{"lter", DOP_LESS_THAN_EQUAL_REAL},
|
{"lter", DOP_LESS_THAN_EQUAL_REAL},
|
||||||
{"mkarr", DOP_MAKE_ARRAY},
|
{"mkarr", DOP_MAKE_ARRAY},
|
||||||
{"mkbuf", DOP_MAKE_BUFFER},
|
{"mkbuf", DOP_MAKE_BUFFER},
|
||||||
|
@ -102,7 +102,12 @@ enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT] = {
|
|||||||
DIT_S, /* DOP_MAKE_TUPLE */
|
DIT_S, /* DOP_MAKE_TUPLE */
|
||||||
DIT_S, /* DOP_MAKE_STRUCT */
|
DIT_S, /* DOP_MAKE_STRUCT */
|
||||||
DIT_S, /* DOP_MAKE_TABLE */
|
DIT_S, /* DOP_MAKE_TABLE */
|
||||||
DIT_S /* DOP_MAKE_STRING */
|
DIT_S, /* DOP_MAKE_STRING */
|
||||||
|
DIT_SSS, /* DOP_NUMERIC_LESS_THAN */
|
||||||
|
DIT_SSS, /* DOP_NUMERIC_LESS_THAN_EQUAL */
|
||||||
|
DIT_SSS, /* DOP_NUMERIC_GREATER_THAN */
|
||||||
|
DIT_SSS, /* DOP_NUMERIC_GREATER_THAN_EQUAL */
|
||||||
|
DIT_SSS /* DOP_NUMERIC_EQUAL */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Verify some bytecode */
|
/* Verify some bytecode */
|
||||||
|
100
src/core/cfuns.c
100
src/core/cfuns.c
@ -118,7 +118,7 @@ static DstSlot do_apply1(DstFopts opts, DstSlot *args) {
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Varidadic operatros specialization */
|
/* Varidadic operators specialization */
|
||||||
|
|
||||||
static DstSlot do_add(DstFopts opts, DstSlot *args) {
|
static DstSlot do_add(DstFopts opts, DstSlot *args) {
|
||||||
return opreduce(opts, args, DOP_ADD, dst_wrap_integer(0));
|
return opreduce(opts, args, DOP_ADD, dst_wrap_integer(0));
|
||||||
@ -154,6 +154,82 @@ static DstSlot do_bnot(DstFopts opts, DstSlot *args) {
|
|||||||
return genericSS(opts, DOP_BNOT, args[0]);
|
return genericSS(opts, DOP_BNOT, args[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specialization for comparators */
|
||||||
|
static DstSlot compreduce(
|
||||||
|
DstFopts opts,
|
||||||
|
DstSlot *args,
|
||||||
|
int op,
|
||||||
|
int invert) {
|
||||||
|
DstCompiler *c = opts.compiler;
|
||||||
|
int32_t i, len;
|
||||||
|
len = dst_v_count(args);
|
||||||
|
int32_t *labels = NULL;
|
||||||
|
DstSlot t;
|
||||||
|
if (len < 2) {
|
||||||
|
return invert
|
||||||
|
? dstc_cslot(dst_wrap_false())
|
||||||
|
: dstc_cslot(dst_wrap_true());
|
||||||
|
}
|
||||||
|
t = dstc_gettarget(opts);
|
||||||
|
for (i = 1; i < len; i++) {
|
||||||
|
dstc_emit_sss(c, op, t, args[i - 1], args[i], 1);
|
||||||
|
if (i != (len - 1)) {
|
||||||
|
int32_t label = dstc_emit_si(c, DOP_JUMP_IF_NOT, t, 0, 1);
|
||||||
|
dst_v_push(labels, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int32_t end = dst_v_count(c->buffer);
|
||||||
|
if (invert) {
|
||||||
|
dstc_emit_si(c, DOP_JUMP_IF, t, 3, 0);
|
||||||
|
dstc_emit_s(c, DOP_LOAD_TRUE, t, 1);
|
||||||
|
dstc_emit(c, DOP_JUMP | (2 << 8));
|
||||||
|
dstc_emit_s(c, DOP_LOAD_FALSE, t, 1);
|
||||||
|
}
|
||||||
|
for (i = 0; i < dst_v_count(labels); i++) {
|
||||||
|
int32_t label = labels[i];
|
||||||
|
c->buffer[label] |= ((end - label) << 16);
|
||||||
|
}
|
||||||
|
dst_v_free(labels);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DstSlot do_order_gt(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_GREATER_THAN, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_order_lt(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_LESS_THAN, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_order_gte(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_LESS_THAN, 1);
|
||||||
|
}
|
||||||
|
static DstSlot do_order_lte(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_GREATER_THAN, 1);
|
||||||
|
}
|
||||||
|
static DstSlot do_order_eq(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_EQUALS, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_order_neq(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_EQUALS, 1);
|
||||||
|
}
|
||||||
|
static DstSlot do_gt(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_NUMERIC_GREATER_THAN, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_lt(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_NUMERIC_LESS_THAN, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_gte(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_NUMERIC_GREATER_THAN_EQUAL, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_lte(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_NUMERIC_LESS_THAN_EQUAL, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_eq(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_NUMERIC_EQUAL, 0);
|
||||||
|
}
|
||||||
|
static DstSlot do_neq(DstFopts opts, DstSlot *args) {
|
||||||
|
return compreduce(opts, args, DOP_NUMERIC_EQUAL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Arranged by tag */
|
/* Arranged by tag */
|
||||||
static const DstFunOptimizer optimizers[] = {
|
static const DstFunOptimizer optimizers[] = {
|
||||||
{fixarity0, do_debug},
|
{fixarity0, do_debug},
|
||||||
@ -174,14 +250,28 @@ static const DstFunOptimizer optimizers[] = {
|
|||||||
{NULL, do_lshift},
|
{NULL, do_lshift},
|
||||||
{NULL, do_rshift},
|
{NULL, do_rshift},
|
||||||
{NULL, do_rshiftu},
|
{NULL, do_rshiftu},
|
||||||
{fixarity1, do_bnot}
|
{fixarity1, do_bnot},
|
||||||
|
{NULL, do_order_gt},
|
||||||
|
{NULL, do_order_lt},
|
||||||
|
{NULL, do_order_gte},
|
||||||
|
{NULL, do_order_lte},
|
||||||
|
{NULL, do_order_eq},
|
||||||
|
{NULL, do_order_neq},
|
||||||
|
{NULL, do_gt},
|
||||||
|
{NULL, do_lt},
|
||||||
|
{NULL, do_gte},
|
||||||
|
{NULL, do_lte},
|
||||||
|
{NULL, do_eq},
|
||||||
|
{NULL, do_neq}
|
||||||
};
|
};
|
||||||
|
|
||||||
const DstFunOptimizer *dstc_funopt(uint32_t flags) {
|
const DstFunOptimizer *dstc_funopt(uint32_t flags) {
|
||||||
uint32_t tag = flags & DST_FUNCDEF_FLAG_TAG;
|
uint32_t tag = flags & DST_FUNCDEF_FLAG_TAG;
|
||||||
if (tag == 0 || tag >=
|
if (tag == 0)
|
||||||
((sizeof(optimizers)/sizeof(uint32_t) - 1)))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
return optimizers + tag - 1;
|
uint32_t index = tag - 1;
|
||||||
|
if (index >= (sizeof(optimizers)/sizeof(optimizers[0])))
|
||||||
|
return NULL;
|
||||||
|
return optimizers + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,18 @@
|
|||||||
#define DST_FUN_RSHIFT 17
|
#define DST_FUN_RSHIFT 17
|
||||||
#define DST_FUN_RSHIFTU 18
|
#define DST_FUN_RSHIFTU 18
|
||||||
#define DST_FUN_BNOT 19
|
#define DST_FUN_BNOT 19
|
||||||
|
#define DST_FUN_ORDER_GT 20
|
||||||
|
#define DST_FUN_ORDER_LT 21
|
||||||
|
#define DST_FUN_ORDER_GTE 22
|
||||||
|
#define DST_FUN_ORDER_LTE 23
|
||||||
|
#define DST_FUN_ORDER_EQ 24
|
||||||
|
#define DST_FUN_ORDER_NEQ 25
|
||||||
|
#define DST_FUN_GT 26
|
||||||
|
#define DST_FUN_LT 27
|
||||||
|
#define DST_FUN_GTE 28
|
||||||
|
#define DST_FUN_LTE 29
|
||||||
|
#define DST_FUN_EQ 30
|
||||||
|
#define DST_FUN_NEQ 31
|
||||||
|
|
||||||
/* Compiler typedefs */
|
/* Compiler typedefs */
|
||||||
typedef struct DstCompiler DstCompiler;
|
typedef struct DstCompiler DstCompiler;
|
||||||
|
@ -527,12 +527,18 @@ DstTable *dst_core_env(void) {
|
|||||||
templatize_varop(env, DST_FUN_RSHIFTU, ">>>", 1, 1, DOP_SHIFT_RIGHT_UNSIGNED);
|
templatize_varop(env, DST_FUN_RSHIFTU, ">>>", 1, 1, DOP_SHIFT_RIGHT_UNSIGNED);
|
||||||
|
|
||||||
/* Variadic comparators */
|
/* Variadic comparators */
|
||||||
templatize_comparator(env, 0, "order>", 0, DOP_GREATER_THAN);
|
templatize_comparator(env, DST_FUN_ORDER_GT, "order>", 0, DOP_GREATER_THAN);
|
||||||
templatize_comparator(env, 0, "order<", 0, DOP_LESS_THAN);
|
templatize_comparator(env, DST_FUN_ORDER_LT, "order<", 0, DOP_LESS_THAN);
|
||||||
templatize_comparator(env, 0, "order>=", 1, DOP_LESS_THAN);
|
templatize_comparator(env, DST_FUN_ORDER_GTE, "order>=", 1, DOP_LESS_THAN);
|
||||||
templatize_comparator(env, 0, "order<=", 1, DOP_GREATER_THAN);
|
templatize_comparator(env, DST_FUN_ORDER_LTE, "order<=", 1, DOP_GREATER_THAN);
|
||||||
templatize_comparator(env, 0, "=", 0, DOP_EQUALS);
|
templatize_comparator(env, DST_FUN_ORDER_EQ, "=", 0, DOP_EQUALS);
|
||||||
templatize_comparator(env, 0, "not=", 1, DOP_EQUALS);
|
templatize_comparator(env, DST_FUN_ORDER_NEQ, "not=", 1, DOP_EQUALS);
|
||||||
|
templatize_comparator(env, DST_FUN_GT, ">", 0, DOP_NUMERIC_GREATER_THAN);
|
||||||
|
templatize_comparator(env, DST_FUN_LT, "<", 0, DOP_NUMERIC_LESS_THAN);
|
||||||
|
templatize_comparator(env, DST_FUN_GTE, ">=", 0, DOP_NUMERIC_GREATER_THAN_EQUAL);
|
||||||
|
templatize_comparator(env, DST_FUN_LTE, "<=", 0, DOP_NUMERIC_LESS_THAN_EQUAL);
|
||||||
|
templatize_comparator(env, DST_FUN_EQ, "==", 0, DOP_NUMERIC_EQUAL);
|
||||||
|
templatize_comparator(env, DST_FUN_NEQ, "not==", 1, DOP_NUMERIC_EQUAL);
|
||||||
|
|
||||||
dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION));
|
dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION));
|
||||||
|
|
||||||
|
@ -129,35 +129,8 @@ static int dst_not(DstArgs args) {
|
|||||||
DST_RETURN_BOOLEAN(args, !dst_truthy(args.v[0]));
|
DST_RETURN_BOOLEAN(args, !dst_truthy(args.v[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_NUMERIC_COMP(name, op) \
|
|
||||||
int dst_numeric_##name(DstArgs args) { \
|
|
||||||
int32_t i; \
|
|
||||||
for (i = 1; i < args.n; i++) { \
|
|
||||||
double x = 0, y = 0; \
|
|
||||||
DST_ARG_NUMBER(x, args, i-1);\
|
|
||||||
DST_ARG_NUMBER(y, args, i);\
|
|
||||||
if (!(x op y)) { \
|
|
||||||
DST_RETURN(args, dst_wrap_false()); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
DST_RETURN(args, dst_wrap_true()); \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEF_NUMERIC_COMP(gt, >)
|
|
||||||
DEF_NUMERIC_COMP(lt, <)
|
|
||||||
DEF_NUMERIC_COMP(lte, <=)
|
|
||||||
DEF_NUMERIC_COMP(gte, >=)
|
|
||||||
DEF_NUMERIC_COMP(eq, ==)
|
|
||||||
DEF_NUMERIC_COMP(neq, !=)
|
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"%", dst_remainder},
|
{"%", dst_remainder},
|
||||||
{"==", dst_numeric_eq},
|
|
||||||
{"not==", dst_numeric_neq},
|
|
||||||
{"<", dst_numeric_lt},
|
|
||||||
{">", dst_numeric_gt},
|
|
||||||
{"<=", dst_numeric_lte},
|
|
||||||
{">=", dst_numeric_gte},
|
|
||||||
{"not", dst_not},
|
{"not", dst_not},
|
||||||
{"int", dst_int},
|
{"int", dst_int},
|
||||||
{"real", dst_real},
|
{"real", dst_real},
|
||||||
|
@ -190,6 +190,11 @@ static void *op_lookup[255] = {
|
|||||||
&&label_DOP_MAKE_STRUCT,
|
&&label_DOP_MAKE_STRUCT,
|
||||||
&&label_DOP_MAKE_TABLE,
|
&&label_DOP_MAKE_TABLE,
|
||||||
&&label_DOP_MAKE_TUPLE,
|
&&label_DOP_MAKE_TUPLE,
|
||||||
|
&&label_DOP_NUMERIC_LESS_THAN,
|
||||||
|
&&label_DOP_NUMERIC_LESS_THAN_EQUAL,
|
||||||
|
&&label_DOP_NUMERIC_GREATER_THAN,
|
||||||
|
&&label_DOP_NUMERIC_GREATER_THAN_EQUAL,
|
||||||
|
&&label_DOP_NUMERIC_EQUAL,
|
||||||
&&label_unknown_op
|
&&label_unknown_op
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
@ -257,6 +262,23 @@ static void *op_lookup[255] = {
|
|||||||
vm_next();\
|
vm_next();\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define vm_numcomp(op)\
|
||||||
|
{\
|
||||||
|
Dst op1 = stack[oparg(2, 0xFF)];\
|
||||||
|
Dst op2 = stack[oparg(3, 0xFF)];\
|
||||||
|
vm_assert_types(op1, DST_TFLAG_NUMBER);\
|
||||||
|
vm_assert_types(op2, DST_TFLAG_NUMBER);\
|
||||||
|
stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_checktype(op1, DST_INTEGER)\
|
||||||
|
? (dst_checktype(op2, DST_INTEGER)\
|
||||||
|
? dst_unwrap_integer(op1) op dst_unwrap_integer(op2)\
|
||||||
|
: (double)dst_unwrap_integer(op1) op dst_unwrap_real(op2))\
|
||||||
|
: (dst_checktype(op2, DST_INTEGER)\
|
||||||
|
? dst_unwrap_real(op1) op (double)dst_unwrap_integer(op2)\
|
||||||
|
: dst_unwrap_real(op1) op dst_unwrap_real(op2)));\
|
||||||
|
pc++;\
|
||||||
|
vm_next();\
|
||||||
|
}
|
||||||
|
|
||||||
/* Main interpreter loop. Semantically is a switch on
|
/* Main interpreter loop. Semantically is a switch on
|
||||||
* (*pc & 0xFF) inside of an infinte loop. */
|
* (*pc & 0xFF) inside of an infinte loop. */
|
||||||
VM_START();
|
VM_START();
|
||||||
@ -325,6 +347,21 @@ static void *op_lookup[255] = {
|
|||||||
VM_OP(DOP_MULTIPLY)
|
VM_OP(DOP_MULTIPLY)
|
||||||
vm_binop(*);
|
vm_binop(*);
|
||||||
|
|
||||||
|
VM_OP(DOP_NUMERIC_LESS_THAN)
|
||||||
|
vm_numcomp(<);
|
||||||
|
|
||||||
|
VM_OP(DOP_NUMERIC_LESS_THAN_EQUAL)
|
||||||
|
vm_numcomp(<=);
|
||||||
|
|
||||||
|
VM_OP(DOP_NUMERIC_GREATER_THAN)
|
||||||
|
vm_numcomp(>);
|
||||||
|
|
||||||
|
VM_OP(DOP_NUMERIC_GREATER_THAN_EQUAL)
|
||||||
|
vm_numcomp(>=);
|
||||||
|
|
||||||
|
VM_OP(DOP_NUMERIC_EQUAL)
|
||||||
|
vm_numcomp(==);
|
||||||
|
|
||||||
VM_OP(DOP_DIVIDE_INTEGER)
|
VM_OP(DOP_DIVIDE_INTEGER)
|
||||||
vm_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide error");
|
vm_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide error");
|
||||||
vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 &&
|
vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 &&
|
||||||
|
@ -811,6 +811,11 @@ enum DstOpCode {
|
|||||||
DOP_MAKE_STRUCT,
|
DOP_MAKE_STRUCT,
|
||||||
DOP_MAKE_TABLE,
|
DOP_MAKE_TABLE,
|
||||||
DOP_MAKE_TUPLE,
|
DOP_MAKE_TUPLE,
|
||||||
|
DOP_NUMERIC_LESS_THAN,
|
||||||
|
DOP_NUMERIC_LESS_THAN_EQUAL,
|
||||||
|
DOP_NUMERIC_GREATER_THAN,
|
||||||
|
DOP_NUMERIC_GREATER_THAN_EQUAL,
|
||||||
|
DOP_NUMERIC_EQUAL,
|
||||||
DOP_INSTRUCTION_COUNT
|
DOP_INSTRUCTION_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user