mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +00:00 
			
		
		
		
	Inlining for all built in comparators.
This commit is contained in:
		| @@ -76,6 +76,7 @@ static const DstInstructionDef dst_ops[] = { | ||||
|     {"eq", DOP_EQUALS}, | ||||
|     {"eqi", DOP_EQUALS_INTEGER}, | ||||
|     {"eqim", DOP_EQUALS_IMMEDIATE}, | ||||
|     {"eqn", DOP_NUMERIC_EQUAL}, | ||||
|     {"eqr", DOP_EQUALS_REAL}, | ||||
|     {"err", DOP_ERROR}, | ||||
|     {"get", DOP_GET}, | ||||
| @@ -83,7 +84,9 @@ static const DstInstructionDef dst_ops[] = { | ||||
|     {"gt", DOP_GREATER_THAN}, | ||||
|     {"gti", DOP_GREATER_THAN_INTEGER}, | ||||
|     {"gtim", DOP_GREATER_THAN_IMMEDIATE}, | ||||
|     {"gtn", DOP_NUMERIC_GREATER_THAN}, | ||||
|     {"gtr", DOP_GREATER_THAN_REAL}, | ||||
|     {"gten", DOP_NUMERIC_GREATER_THAN_EQUAL}, | ||||
|     {"gter", DOP_GREATER_THAN_EQUAL_REAL}, | ||||
|     {"jmp", DOP_JUMP}, | ||||
|     {"jmpif", DOP_JUMP_IF}, | ||||
| @@ -99,7 +102,9 @@ static const DstInstructionDef dst_ops[] = { | ||||
|     {"lt", DOP_LESS_THAN}, | ||||
|     {"lti", DOP_LESS_THAN_INTEGER}, | ||||
|     {"ltim", DOP_LESS_THAN_IMMEDIATE}, | ||||
|     {"ltn", DOP_NUMERIC_LESS_THAN}, | ||||
|     {"ltr", DOP_LESS_THAN_REAL}, | ||||
|     {"lten", DOP_NUMERIC_LESS_THAN_EQUAL}, | ||||
|     {"lter", DOP_LESS_THAN_EQUAL_REAL}, | ||||
|     {"mkarr", DOP_MAKE_ARRAY}, | ||||
|     {"mkbuf", DOP_MAKE_BUFFER}, | ||||
|   | ||||
| @@ -102,7 +102,12 @@ enum DstInstructionType dst_instructions[DOP_INSTRUCTION_COUNT] = { | ||||
|     DIT_S, /* DOP_MAKE_TUPLE */ | ||||
|     DIT_S, /* DOP_MAKE_STRUCT */ | ||||
|     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 */ | ||||
|   | ||||
							
								
								
									
										100
									
								
								src/core/cfuns.c
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/core/cfuns.c
									
									
									
									
									
								
							| @@ -118,7 +118,7 @@ static DstSlot do_apply1(DstFopts opts, DstSlot *args) { | ||||
|     return target; | ||||
| } | ||||
|  | ||||
| /* Varidadic operatros specialization */ | ||||
| /* Varidadic operators specialization */ | ||||
|  | ||||
| static DstSlot do_add(DstFopts opts, DstSlot *args) { | ||||
|     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]); | ||||
| } | ||||
|  | ||||
| /* 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 */ | ||||
| static const DstFunOptimizer optimizers[] = { | ||||
|     {fixarity0, do_debug}, | ||||
| @@ -174,14 +250,28 @@ static const DstFunOptimizer optimizers[] = { | ||||
|     {NULL, do_lshift}, | ||||
|     {NULL, do_rshift}, | ||||
|     {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) { | ||||
|     uint32_t tag = flags & DST_FUNCDEF_FLAG_TAG; | ||||
|     if (tag == 0 || tag >= | ||||
|             ((sizeof(optimizers)/sizeof(uint32_t) - 1))) | ||||
|     if (tag == 0) | ||||
|         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_RSHIFTU 18 | ||||
| #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 */ | ||||
| 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); | ||||
|  | ||||
|     /* Variadic comparators */ | ||||
|     templatize_comparator(env, 0, "order>", 0, DOP_GREATER_THAN); | ||||
|     templatize_comparator(env, 0, "order<", 0, DOP_LESS_THAN); | ||||
|     templatize_comparator(env, 0, "order>=", 1, DOP_LESS_THAN); | ||||
|     templatize_comparator(env, 0, "order<=", 1, DOP_GREATER_THAN); | ||||
|     templatize_comparator(env, 0, "=", 0, DOP_EQUALS); | ||||
|     templatize_comparator(env, 0, "not=", 1, DOP_EQUALS); | ||||
|     templatize_comparator(env, DST_FUN_ORDER_GT, "order>", 0, DOP_GREATER_THAN); | ||||
|     templatize_comparator(env, DST_FUN_ORDER_LT, "order<", 0, DOP_LESS_THAN); | ||||
|     templatize_comparator(env, DST_FUN_ORDER_GTE, "order>=", 1, DOP_LESS_THAN); | ||||
|     templatize_comparator(env, DST_FUN_ORDER_LTE, "order<=", 1, DOP_GREATER_THAN); | ||||
|     templatize_comparator(env, DST_FUN_ORDER_EQ, "=", 0, 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)); | ||||
|  | ||||
|   | ||||
| @@ -129,35 +129,8 @@ static int dst_not(DstArgs args) { | ||||
|     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[] = { | ||||
|     {"%", dst_remainder}, | ||||
|     {"==", dst_numeric_eq}, | ||||
|     {"not==", dst_numeric_neq}, | ||||
|     {"<", dst_numeric_lt}, | ||||
|     {">", dst_numeric_gt}, | ||||
|     {"<=", dst_numeric_lte}, | ||||
|     {">=", dst_numeric_gte}, | ||||
|     {"not", dst_not}, | ||||
|     {"int", dst_int}, | ||||
|     {"real", dst_real}, | ||||
|   | ||||
| @@ -190,6 +190,11 @@ static void *op_lookup[255] = { | ||||
|     &&label_DOP_MAKE_STRUCT, | ||||
|     &&label_DOP_MAKE_TABLE, | ||||
|     &&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 | ||||
| }; | ||||
| #else | ||||
| @@ -257,6 +262,23 @@ static void *op_lookup[255] = { | ||||
|         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 | ||||
|      * (*pc & 0xFF) inside of an infinte loop. */ | ||||
|     VM_START(); | ||||
| @@ -325,6 +347,21 @@ static void *op_lookup[255] = { | ||||
|     VM_OP(DOP_MULTIPLY) | ||||
|     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_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide error"); | ||||
|     vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 && | ||||
|   | ||||
| @@ -811,6 +811,11 @@ enum DstOpCode { | ||||
|     DOP_MAKE_STRUCT, | ||||
|     DOP_MAKE_TABLE, | ||||
|     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 | ||||
| }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose