Skip to content

Commit

Permalink
fixing a dispatch bug involving the specialization heuristic for
Browse files Browse the repository at this point in the history
  tuples. adding test.
tweaking specialization heuristic for tuple arguments not to
  specialize slots declared as (Any,Any) and so on. the method cache
  for map() on tuples was getting way too big.
renaming unittests to quicktests, to reflect what it's for
  • Loading branch information
JeffBezanson committed Sep 30, 2011
1 parent 4ac7784 commit e5288fa
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -5,7 +5,7 @@ include ./Make.inc
default: release

debug release: %: julia-% sys.ji
make -C test unittests
make -C test quicktests

julia-debug julia-release:
$(MAKE) -C external
Expand Down
49 changes: 41 additions & 8 deletions src/gf.c
Expand Up @@ -379,18 +379,32 @@ void jl_type_infer(jl_lambda_info_t *li, jl_tuple_t *argtypes,
jl_in_inference = last_ii;
}

static int tuple_all_Any(jl_tuple_t *t)
{
int i;
for(i=0; i < t->length; i++) {
if (jl_tupleref(t,i) != (jl_value_t*)jl_any_type)
return 0;
}
return 1;
}

static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type,
jl_function_t *method, jl_tuple_t *decl,
jl_tuple_t *sparams)
{
size_t i;
int need_dummy_entries = 0;
jl_value_t *temp=NULL;
jl_function_t *newmeth=NULL;
JL_GC_PUSH(&type, &temp, &newmeth);

for (i=0; i < type->length; i++) {
jl_value_t *elt = jl_tupleref(type,i);
int set_to_any = 0;
if (nth_slot_type(decl,i) == jl_ANY_flag) {
// don't specialize on slots marked ANY
jl_value_t *orig = jl_tupleref(type, i);
temp = jl_tupleref(type, i);
jl_tupleset(type, i, (jl_value_t*)jl_any_type);
int nintr=0;
jl_methlist_t *curr = mt->defs;
Expand All @@ -408,7 +422,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type,
if (nintr) {
// TODO: even if different specializations of this slot need
// separate cache entries, have them share code.
jl_tupleset(type, i, orig);
jl_tupleset(type, i, temp);
}
else {
set_to_any = 1;
Expand All @@ -423,6 +437,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type,
specific. determined with a type intersection.
*/
int might_need_dummy=0;
temp = jl_tupleref(type, i);
if (i < decl->length) {
jl_value_t *declt = jl_tupleref(decl,i);
// for T..., intersect with T
Expand All @@ -434,17 +449,37 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type,
jl_tupleset(type, i, (jl_value_t*)jl_tuple_type);
might_need_dummy = 1;
}
else if (((jl_tuple_t*)elt)->length > 3) {
else {
declt = jl_type_intersection(declt,
(jl_value_t*)jl_tuple_type);
jl_tupleset(type, i, declt);
if (((jl_tuple_t*)elt)->length > 3 ||
tuple_all_Any((jl_tuple_t*)declt)) {
jl_tupleset(type, i, declt);
might_need_dummy = 1;
}
}
}
else {
jl_tupleset(type, i, (jl_value_t*)jl_tuple_type);
might_need_dummy = 1;
}
assert(jl_tupleref(type,i) != (jl_value_t*)jl_bottom_type);
if (might_need_dummy) {
jl_methlist_t *curr = mt->defs;
// can't generalize type if there's an overlapping definition
// with typevars
while (curr != NULL && curr->func!=method) {
if (curr->has_tvars &&
jl_type_intersection((jl_value_t*)curr->sig,
(jl_value_t*)type) !=
(jl_value_t*)jl_bottom_type) {
jl_tupleset(type, i, temp);
might_need_dummy = 0;
break;
}
curr = curr->next;
}
}
if (might_need_dummy) {
jl_methlist_t *curr = mt->defs;
while (curr != NULL && curr->func!=method) {
Expand Down Expand Up @@ -508,9 +543,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type,
}
}
}
jl_value_t *temp=NULL;
jl_function_t *newmeth=NULL;
JL_GC_PUSH(&type, &temp, &newmeth);

// for varargs methods, only specialize up to max_args.
// in general, here we want to find the biggest type that's not a
// supertype of any other method signatures. so far we are conservative
Expand Down Expand Up @@ -1323,7 +1356,7 @@ static jl_tuple_t *match_method(jl_value_t *type, jl_function_t *func,
jl_value_t *ti=NULL;
JL_GC_PUSH(&env, &ti, &temp);

ti = jl_type_intersection_matching((jl_value_t*)sig, type, &env, tvars);
ti = jl_type_intersection_matching(type, (jl_value_t*)sig, &env, tvars);
jl_tuple_t *result = NULL;
if (ti != (jl_value_t*)jl_bottom_type) {
if (func->linfo == NULL) {
Expand Down
4 changes: 2 additions & 2 deletions test/Makefile
@@ -1,7 +1,7 @@
testall: test test-utf8 test-perf

unittests:
../julia unittests.j
quicktests:
../julia quicktests.j

test:
../julia tests.j
Expand Down
File renamed without changes.
8 changes: 7 additions & 1 deletion test/tests.j
Expand Up @@ -718,11 +718,17 @@ glotest()
# dispatch
begin
local foo
local foo, bar
foo(x::(Any...))=0
foo(x::(Int...))=1
@assert foo((:a,))==0
@assert foo(( 2,))==1
bar{T}(x::(T,T,T,T))=1
bar(x::(Any,Any,Any,Any))=2
@assert bar((1,1,1,1)) == 1
@assert bar((1,1,1,"a")) == 2
@assert bar((:a,:a,:a,:a)) == 1
end
# ranges
Expand Down

0 comments on commit e5288fa

Please sign in to comment.