improve JIT impersonator property predicate/accessor fast path
Faster for the case that an impersonator has a small number of impersonator properties. To enable hand-coded search, a small number of properties are now kept in a vector instead of a hash tree.
This commit is contained in:
parent
fe1d9ee517
commit
36d563d7ce
|
@ -281,7 +281,23 @@
|
|||
(err/rt-test (get1 v7) handler)
|
||||
(err/rt-test (get1 v8) handler)
|
||||
(err/rt-test (get1 v9) handler)
|
||||
(err/rt-test (get1 v10) handler)))
|
||||
(err/rt-test (get1 v10) handler)
|
||||
|
||||
;; Make sure it works to have lots of impersontaors:
|
||||
(let loop ([v v1] [i 100] [preds null] [sels null] [vals null])
|
||||
(unless (zero? i)
|
||||
(for ([pred (in-list preds)]
|
||||
[sel (in-list sels)]
|
||||
[val (in-list vals)])
|
||||
(test #t pred v)
|
||||
(test val sel v)
|
||||
(test val sel v 'no))
|
||||
(define-values (p has get) (make-impersonator-property 'p))
|
||||
(loop (chaperone-vector v #f #f p i)
|
||||
(sub1 i)
|
||||
(cons has preds)
|
||||
(cons get sels)
|
||||
(cons i vals))))))
|
||||
|
||||
|
||||
;; check property-only chaperones
|
||||
|
|
|
@ -3535,7 +3535,7 @@ static Scheme_Object *do_chaperone_procedure(const char *name, const char *whati
|
|||
{
|
||||
Scheme_Chaperone *px, *px2;
|
||||
Scheme_Object *val = argv[0], *orig, *naya, *r, *app_mark;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
val = SCHEME_CHAPERONE_VAL(val);
|
||||
|
@ -3569,13 +3569,10 @@ static Scheme_Object *do_chaperone_procedure(const char *name, const char *whati
|
|||
|
||||
props = scheme_parse_chaperone_props(name, 2, argc, argv);
|
||||
if (props) {
|
||||
app_mark = scheme_hash_tree_get(props, scheme_app_mark_impersonator_property);
|
||||
app_mark = scheme_chaperone_props_get(props, scheme_app_mark_impersonator_property);
|
||||
if (app_mark) {
|
||||
/* don't need to keep the property */
|
||||
if (props->count == 1)
|
||||
props = NULL;
|
||||
else
|
||||
props = scheme_hash_tree_set(props, scheme_app_mark_impersonator_property, NULL);
|
||||
props = scheme_chaperone_props_remove(props, scheme_app_mark_impersonator_property);
|
||||
} else
|
||||
app_mark = scheme_false;
|
||||
} else
|
||||
|
@ -4555,7 +4552,7 @@ Scheme_Object *do_chaperone_continuation_mark_key (const char *name, int is_impe
|
|||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val = argv[0];
|
||||
Scheme_Object *redirects;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
val = SCHEME_CHAPERONE_VAL(val);
|
||||
|
@ -6495,7 +6492,7 @@ Scheme_Object *do_chaperone_prompt_tag (const char *name, int is_impersonator, i
|
|||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val = argv[0];
|
||||
Scheme_Object *redirects;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
int ppos;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
|
|
|
@ -2072,7 +2072,7 @@ static int common4b(mz_jit_state *jitter, void *_data)
|
|||
for (i = 0; i < 3; i++) {
|
||||
for (ii = 0; ii < 3; ii++) { /* single, multi, or tail */
|
||||
void *code;
|
||||
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *ref4, *refno, *refslow, *refloop;
|
||||
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *ref4, *ref5, *refno, *refslow, *refloop, *refchap;
|
||||
int prim_other_type;
|
||||
|
||||
code = jit_get_ip();
|
||||
|
@ -2158,13 +2158,15 @@ static int common4b(mz_jit_state *jitter, void *_data)
|
|||
jit_ldr_p(JIT_V1, JIT_RUNSTACK);
|
||||
/* If the failure argument is not a procedure, we can
|
||||
return it directly, otherwise take slow path. */
|
||||
jit_ldxi_s(JIT_R2, JIT_V1, &((Scheme_Object *)0x0)->type);
|
||||
__START_INNER_TINY__(1);
|
||||
ref5 = jit_bmsi_ul(jit_forward(), JIT_V1, 0x1);
|
||||
jit_ldxi_s(JIT_R2, JIT_V1, &((Scheme_Object *)0x0)->type);
|
||||
ref4 = jit_blti_i(jit_forward(), JIT_R2, scheme_prim_type);
|
||||
__END_INNER_TINY__(1);
|
||||
(void)jit_blei_i(refslow, JIT_R2, scheme_proc_chaperone_type);
|
||||
__START_INNER_TINY__(1);
|
||||
mz_patch_branch(ref4);
|
||||
mz_patch_branch(ref5);
|
||||
__END_INNER_TINY__(1);
|
||||
jit_movr_p(JIT_R0, JIT_V1);
|
||||
jit_addi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(1));
|
||||
|
@ -2173,6 +2175,58 @@ static int common4b(mz_jit_state *jitter, void *_data)
|
|||
} else
|
||||
refno = refslow;
|
||||
|
||||
{
|
||||
/* Chaperone case: if we're looking for an impersonator property,
|
||||
maybe we can find it here; otherwise, take the slow path. */
|
||||
refchap = jit_get_ip();
|
||||
|
||||
jit_ldxi_p(JIT_V1, JIT_R0, &((Scheme_Primitive_Closure *)0x0)->val);
|
||||
(void)mz_bnei_t(refslow, JIT_V1, scheme_chaperone_property_type, JIT_R2); /* slow path if not impersonator property */
|
||||
jit_ldxi_p(JIT_R2, JIT_R1, &((Scheme_Chaperone *)0x0)->props); /* check chaperone's props */
|
||||
(void)jit_beqi_p(refslow, JIT_R2, NULL);
|
||||
(void)mz_bnei_t(refslow, JIT_R2, scheme_vector_type, JIT_V1); /* slow path if not represented a vector */
|
||||
CHECK_LIMIT();
|
||||
|
||||
/* Search a vector for the property: */
|
||||
(void)jit_ldxi_l(JIT_V1, JIT_R2, &SCHEME_VEC_SIZE(0x0)); /* get vector size */
|
||||
jit_lshi_ul(JIT_V1, JIT_V1, JIT_LOG_WORD_SIZE); /* convert to bytes */
|
||||
jit_addi_l(JIT_V1, JIT_V1, (int)&SCHEME_VEC_ELS(0x0)); /* bytes at offset */
|
||||
|
||||
refloop = jit_get_ip();
|
||||
(void)jit_beqi_l(refslow, JIT_V1, (int)&SCHEME_VEC_ELS(0x0)); /* index at 0 => not found, so slow path */
|
||||
|
||||
jit_subi_l(JIT_V1, JIT_V1, (2 * JIT_WORD_SIZE)); /* step back by two words for key & value */
|
||||
mz_set_local_p(JIT_V1, JIT_LOCAL3); /* save current index, because we need the register */
|
||||
jit_ldxi_p(JIT_R2, JIT_R1, &((Scheme_Chaperone *)0x0)->props); /* get vector again */
|
||||
jit_ldxr_p(JIT_R2, JIT_R2, JIT_V1); /* load a key from the vector */
|
||||
jit_ldxi_p(JIT_V1, JIT_R0, &((Scheme_Primitive_Closure *)0x0)->val); /* get the property again */
|
||||
CHECK_LIMIT();
|
||||
__START_INNER_TINY__(1);
|
||||
ref5 = jit_beqr_p(jit_forward(), JIT_R2, JIT_V1); /* key matches property? */
|
||||
__END_INNER_TINY__(1);
|
||||
CHECK_LIMIT();
|
||||
|
||||
mz_get_local_p(JIT_V1, JIT_LOCAL3); /* no match, so reload index and recur */
|
||||
(void)jit_jmpi(refloop);
|
||||
|
||||
__START_INNER_TINY__(1);
|
||||
mz_patch_branch(ref5);
|
||||
__END_INNER_TINY__(1);
|
||||
/* found match, so return #t or extract and return the value */
|
||||
if (i == 2) {
|
||||
(void)jit_movi_p(JIT_R0, scheme_true);
|
||||
} else {
|
||||
mz_get_local_p(JIT_V1, JIT_LOCAL3); /* reload matching index */
|
||||
jit_addi_l(JIT_V1, JIT_V1, JIT_WORD_SIZE); /* up by one word, to get value insteda of key */
|
||||
jit_ldxi_p(JIT_R2, JIT_R1, &((Scheme_Chaperone *)0x0)->props); /* get vector again */
|
||||
jit_ldxr_p(JIT_R0, JIT_R2, JIT_V1); /* extract value */
|
||||
}
|
||||
if (i == 1)
|
||||
jit_addi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(1));
|
||||
mz_epilog(JIT_V1); /* return */
|
||||
CHECK_LIMIT();
|
||||
}
|
||||
|
||||
/* Continue trying fast path: check proc */
|
||||
mz_patch_branch(ref);
|
||||
(void)mz_bnei_t(refslow, JIT_R0, scheme_prim_type, JIT_R2);
|
||||
|
@ -2187,9 +2241,9 @@ static int common4b(mz_jit_state *jitter, void *_data)
|
|||
__START_INNER_TINY__(1);
|
||||
ref2 = jit_beqi_i(jit_forward(), JIT_R2, scheme_structure_type);
|
||||
__END_INNER_TINY__(1);
|
||||
(void)jit_beqi_i(refchap, JIT_R2, scheme_proc_chaperone_type);
|
||||
(void)jit_beqi_i(refchap, JIT_R2, scheme_chaperone_type);
|
||||
if (i != 0) { /* for i == 0 mode, `refno` is already `refslow` */
|
||||
(void)jit_beqi_i(refslow, JIT_R2, scheme_proc_chaperone_type);
|
||||
(void)jit_beqi_i(refslow, JIT_R2, scheme_chaperone_type);
|
||||
(void)jit_beqi_i(refslow, JIT_R2, scheme_struct_type_type);
|
||||
}
|
||||
(void)jit_bnei_i(refno, JIT_R2, scheme_proc_struct_type);
|
||||
|
|
|
@ -1966,7 +1966,7 @@ static Scheme_Object *do_chaperone_box(const char *name, int is_impersonator, in
|
|||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val = argv[0];
|
||||
Scheme_Object *redirects;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
val = SCHEME_CHAPERONE_VAL(val);
|
||||
|
@ -3177,7 +3177,7 @@ static Scheme_Object *do_chaperone_hash(const char *name, int is_impersonator, i
|
|||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val = argv[0];
|
||||
Scheme_Object *redirects, *clear, *equal_key_wrap;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
int start_props = 5;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
|
|
|
@ -1159,7 +1159,7 @@ typedef struct Scheme_Chaperone {
|
|||
Scheme_Inclhash_Object iso; /* 0x1 => impersonator, rather than a checking chaperone */
|
||||
Scheme_Object *val; /* root object */
|
||||
Scheme_Object *prev; /* immediately chaperoned object */
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props; /* NULL, a vector, or a hash tree */
|
||||
Scheme_Object *redirects; /* specific to the type of chaperone and root object */
|
||||
} Scheme_Chaperone;
|
||||
|
||||
|
@ -1218,7 +1218,9 @@ void scheme_chaperone_vector_set(Scheme_Object *o, int i, Scheme_Object *v);
|
|||
Scheme_Object *scheme_apply_chaperone(Scheme_Object *o, int argc, Scheme_Object **argv,
|
||||
Scheme_Object *auto_val, int checks);
|
||||
|
||||
Scheme_Hash_Tree *scheme_parse_chaperone_props(const char *who, int start_at, int argc, Scheme_Object **argv);
|
||||
Scheme_Object *scheme_parse_chaperone_props(const char *who, int start_at, int argc, Scheme_Object **argv);
|
||||
Scheme_Object *scheme_chaperone_props_get(Scheme_Object *props, Scheme_Object *prop);
|
||||
Scheme_Object *scheme_chaperone_props_remove(Scheme_Object *props, Scheme_Object *prop);
|
||||
|
||||
Scheme_Object *scheme_chaperone_hash_get(Scheme_Object *table, Scheme_Object *key);
|
||||
Scheme_Object *scheme_chaperone_hash_traversal_get(Scheme_Object *table, Scheme_Object *key, Scheme_Object **alt_key);
|
||||
|
|
|
@ -1202,7 +1202,7 @@ Scheme_Object *do_chaperone_channel(const char *name, int is_impersonator, int a
|
|||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val = argv[0];
|
||||
Scheme_Object *evt;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
val = SCHEME_CHAPERONE_VAL(val);
|
||||
|
|
|
@ -1059,6 +1059,43 @@ static Scheme_Object *current_code_inspector(int argc, Scheme_Object *argv[])
|
|||
/* properties */
|
||||
/*========================================================================*/
|
||||
|
||||
Scheme_Object *scheme_chaperone_props_get(Scheme_Object *props, Scheme_Object *prop)
|
||||
{
|
||||
if (!props)
|
||||
return NULL;
|
||||
else if (SCHEME_VECTORP(props)) {
|
||||
int i;
|
||||
for (i = SCHEME_VEC_SIZE(props); i > 0; ) {
|
||||
i -= 2;
|
||||
if (SAME_OBJ(SCHEME_VEC_ELS(props)[i], prop))
|
||||
return SCHEME_VEC_ELS(props)[i+1];
|
||||
}
|
||||
return NULL;
|
||||
} else
|
||||
return (Scheme_Object *)scheme_hash_tree_get((Scheme_Hash_Tree *)props, prop);
|
||||
}
|
||||
|
||||
Scheme_Object *scheme_chaperone_props_remove(Scheme_Object *props, Scheme_Object *prop)
|
||||
/* assumes that `prop` is currently set in `props` */
|
||||
{
|
||||
if (SCHEME_VECTORP(props)) {
|
||||
Scheme_Object *vec;
|
||||
int i, j;
|
||||
j = SCHEME_VEC_SIZE(props);
|
||||
if (j == 2) return NULL;
|
||||
vec = scheme_make_vector(j - 2, NULL);
|
||||
for (i = SCHEME_VEC_SIZE(props), j = 0; i > 0; ) {
|
||||
i -= 2;
|
||||
if (!SAME_OBJ(SCHEME_VEC_ELS(props)[i], prop)) {
|
||||
SCHEME_VEC_ELS(vec)[j++] = SCHEME_VEC_ELS(props)[i];
|
||||
SCHEME_VEC_ELS(vec)[j++] = SCHEME_VEC_ELS(props)[i+1];
|
||||
}
|
||||
}
|
||||
return vec;
|
||||
} else
|
||||
return (Scheme_Object *)scheme_hash_tree_set((Scheme_Hash_Tree *)props, prop, NULL);
|
||||
}
|
||||
|
||||
static Scheme_Object *prop_pred(int argc, Scheme_Object **args, Scheme_Object *prim)
|
||||
{
|
||||
Scheme_Struct_Type *stype;
|
||||
|
@ -1071,10 +1108,7 @@ static Scheme_Object *prop_pred(int argc, Scheme_Object **args, Scheme_Object *p
|
|||
if (SCHEME_CHAPERONEP(v)) {
|
||||
/* Check for property at chaperone level: */
|
||||
px = (Scheme_Chaperone *)v;
|
||||
if (px->props)
|
||||
v = scheme_hash_tree_get(px->props, prop);
|
||||
else
|
||||
v = NULL;
|
||||
v = scheme_chaperone_props_get(px->props, prop);
|
||||
if (v)
|
||||
return scheme_true;
|
||||
v = px->val;
|
||||
|
@ -1187,11 +1221,9 @@ static Scheme_Object *do_chaperone_prop_accessor(const char *who, Scheme_Object
|
|||
Scheme_Object *v;
|
||||
Scheme_Hash_Tree *ht;
|
||||
|
||||
if (px->props) {
|
||||
v = scheme_hash_tree_get(px->props, prop);
|
||||
if (v)
|
||||
return v;
|
||||
}
|
||||
v = scheme_chaperone_props_get(px->props, prop);
|
||||
if (v)
|
||||
return v;
|
||||
|
||||
if (!SCHEME_REDIRECTS_STRUCTP(px->redirects)
|
||||
|| SCHEME_FALSEP(SCHEME_VEC_ELS(px->redirects)[0]))
|
||||
|
@ -4056,7 +4088,7 @@ Scheme_Object *scheme_do_chaperone_evt(const char *name, int is_impersonator, in
|
|||
{
|
||||
Scheme_Chaperone *px;
|
||||
Scheme_Object *o, *val, *a[1];
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
|
||||
val = argv[0];
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
|
@ -6212,12 +6244,12 @@ static Scheme_Object *do_chaperone_struct(const char *name, int is_impersonator,
|
|||
{
|
||||
Scheme_Chaperone *px;
|
||||
Scheme_Struct_Type *stype, *st;
|
||||
Scheme_Object *val = argv[0], *proc;
|
||||
Scheme_Object *val = argv[0], *proc, *props = NULL;
|
||||
Scheme_Object *redirects, *prop, *si_chaperone = scheme_false;
|
||||
Scheme_Object *a[1], *inspector, *getter_positions = scheme_null;
|
||||
int i, offset, arity, non_applicable_op, repeat_op;
|
||||
const char *kind;
|
||||
Scheme_Hash_Tree *props = NULL, *red_props = NULL, *empty_red_props = NULL, *setter_positions = NULL;
|
||||
Scheme_Hash_Tree *red_props = NULL, *empty_red_props = NULL, *setter_positions = NULL;
|
||||
intptr_t field_pos;
|
||||
int empty_si_chaperone = 0, *empty_redirects = NULL, has_redirect = 0, witnessed = 0;
|
||||
|
||||
|
@ -6555,7 +6587,7 @@ Scheme_Object *scheme_chaperone_not_undefined (Scheme_Object *orig_val)
|
|||
{
|
||||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val, *redirects;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
|
||||
val = orig_val;
|
||||
|
||||
|
@ -6589,7 +6621,7 @@ static Scheme_Object *do_chaperone_struct_type(const char *name, int is_imperson
|
|||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val = argv[0];
|
||||
Scheme_Object *redirects;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
int arity;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val))
|
||||
|
@ -6635,35 +6667,99 @@ static Scheme_Object *chaperone_struct_type(int argc, Scheme_Object **argv)
|
|||
return do_chaperone_struct_type("chaperone-struct-type", 0, argc, argv);
|
||||
}
|
||||
|
||||
Scheme_Hash_Tree *scheme_parse_chaperone_props(const char *who, int start_at, int argc, Scheme_Object **argv)
|
||||
#define PROPS_MAX_VECTOR_SIZE 5
|
||||
|
||||
Scheme_Object *scheme_parse_chaperone_props(const char *who, int start_at, int argc, Scheme_Object **argv)
|
||||
{
|
||||
Scheme_Hash_Tree *ht;
|
||||
Scheme_Object *v;
|
||||
Scheme_Object *v, *props;
|
||||
int pos;
|
||||
|
||||
if (SCHEME_CHAPERONEP(argv[0]))
|
||||
ht = ((Scheme_Chaperone *)argv[0])->props;
|
||||
props = ((Scheme_Chaperone *)argv[0])->props;
|
||||
else
|
||||
ht = NULL;
|
||||
props = NULL;
|
||||
|
||||
while (start_at < argc) {
|
||||
v = argv[start_at];
|
||||
if (!SAME_TYPE(SCHEME_TYPE(v), scheme_chaperone_property_type))
|
||||
scheme_wrong_contract(who, "impersonator-property?", start_at, argc, argv);
|
||||
if (start_at < argc) {
|
||||
/* Check */
|
||||
for (pos = start_at; pos < argc; pos += 2) {
|
||||
v = argv[pos];
|
||||
if (!SAME_TYPE(SCHEME_TYPE(v), scheme_chaperone_property_type))
|
||||
scheme_wrong_contract(who, "impersonator-property?", pos, argc, argv);
|
||||
|
||||
if (start_at + 1 >= argc)
|
||||
scheme_contract_error(who,
|
||||
"missing value after chaperone property",
|
||||
"chaperone property", 1, v,
|
||||
NULL);
|
||||
if (pos + 1 >= argc)
|
||||
scheme_contract_error(who,
|
||||
"missing value after chaperone property",
|
||||
"chaperone property", 1, v,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (!ht)
|
||||
/* Prepare to add */
|
||||
if (props && SCHEME_VECTORP(props)
|
||||
&& (((argc - start_at) + SCHEME_VEC_SIZE(props)) > (2 * PROPS_MAX_VECTOR_SIZE))) {
|
||||
/* Convert vector to a hash tree */
|
||||
Scheme_Hash_Tree *ht;
|
||||
int i;
|
||||
ht = scheme_make_hash_tree(SCHEME_hashtr_eq);
|
||||
ht = scheme_hash_tree_set(ht, v, argv[start_at + 1]);
|
||||
for (i = SCHEME_VEC_SIZE(props); i > 0; ) {
|
||||
i -= 2;
|
||||
ht = scheme_hash_tree_set(ht, SCHEME_VEC_ELS(props)[i], SCHEME_VEC_ELS(props)[i+1]);
|
||||
}
|
||||
props = (Scheme_Object *)ht;
|
||||
}
|
||||
|
||||
start_at += 2;
|
||||
if (!props || SCHEME_VECTORP(props)) {
|
||||
/* Keep as vector, and start by counting new distinct entries */
|
||||
int count = 0, i, len = (props ? SCHEME_VEC_SIZE(props) : 0);
|
||||
|
||||
for (pos = start_at; pos < argc; pos += 2) {
|
||||
v = argv[pos];
|
||||
if (props) {
|
||||
for (i = 0; i < len; i += 2) {
|
||||
if (SAME_OBJ(v, SCHEME_VEC_ELS(props)[i]))
|
||||
break;
|
||||
}
|
||||
} else
|
||||
i = 0;
|
||||
if (i >= len) {
|
||||
for (i = start_at; i < pos; i += 2) {
|
||||
if (SAME_OBJ(v, argv[i]))
|
||||
break;
|
||||
}
|
||||
if (i >= pos)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (props) {
|
||||
/* Copy vector, possibly making it larger */
|
||||
Scheme_Object *old_props = props;
|
||||
props = scheme_make_vector(SCHEME_VEC_SIZE(old_props) + 2 * count, NULL);
|
||||
memcpy(SCHEME_VEC_ELS(props), SCHEME_VEC_ELS(old_props), sizeof(Scheme_Object *)*SCHEME_VEC_SIZE(old_props));
|
||||
} else {
|
||||
props = scheme_make_vector(2 * count, NULL);
|
||||
}
|
||||
len = SCHEME_VEC_SIZE(props);
|
||||
|
||||
/* Fill in vector */
|
||||
for (pos = start_at; pos < argc; pos += 2) {
|
||||
v = argv[pos];
|
||||
for (i = 0; i < len; i += 2) {
|
||||
if (!SCHEME_VEC_ELS(props)[i] || SAME_OBJ(v, SCHEME_VEC_ELS(props)[i])) {
|
||||
SCHEME_VEC_ELS(props)[i] = v;
|
||||
SCHEME_VEC_ELS(props)[i+1] = argv[pos+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Add to hash tree */
|
||||
for (pos = start_at; pos < argc; pos += 2) {
|
||||
props = (Scheme_Object *)scheme_hash_tree_set((Scheme_Hash_Tree *)props, argv[pos], argv[pos+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ht;
|
||||
return props;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
|
|
@ -964,7 +964,7 @@ static Scheme_Object *do_chaperone_vector(const char *name, int is_impersonator,
|
|||
Scheme_Chaperone *px;
|
||||
Scheme_Object *val = argv[0];
|
||||
Scheme_Object *redirects;
|
||||
Scheme_Hash_Tree *props;
|
||||
Scheme_Object *props;
|
||||
|
||||
if (SCHEME_CHAPERONEP(val)) {
|
||||
val = SCHEME_CHAPERONE_VAL(val);
|
||||
|
|
Loading…
Reference in New Issue
Block a user