MLton.size bug

Matthew Fluet Matthew Fluet <fluet@CS.Cornell.EDU>
Fri, 27 Apr 2001 10:57:27 -0400 (EDT)


> One thing we have to do is to figure why the hash table size is zero in the
> compiler -v3 output.  I'm not sure whether it's for the same reason as your
> example above or some other funny interaction with the useless analysis.  If the 
> former, then we may need to rethink size altogether.

I believe that it because of the remove-useless pass.  I tried the
following program:

val table = HashSet.new {hash = Word.fromInt}

fun fill 0 = ()
  | fill n = let
	       val _ = HashSet.lookupOrInsert(table, 
					      Word.fromInt n, 
					      fn _ => false, 
					      fn () => n)
	     in
	       fill (n - 1)
	     end

val _ = fill 1000

val table_size = HashSet.size table
val _ = print (concat ["table_size: ", Int.toString table_size, "\n"])

val table_fold = HashSet.fold (table, 0, op +)
val _ = print (concat ["table_fold: ", Int.toString table_fold, "\n"])

val _ = HashSet.remove(table, fn i => i mod 2 = 0)

val table_forall = HashSet.forall(table, fn i => i mod 2 = 1)
val _ = print (concat ["table_forall: ", Bool.toString table_forall, "\n"])

val r = ref (0: Int.int)
val _ = HashSet.foreach(table, fn i => r := !r + i)
val _ = print (concat ["!r: ", Int.toString (!r), "\n"])

val table_layout = HashSet.layout Int.layout table
val _ = Layout.output(table_layout, TextIO.stdOut)
val _ = print "\n"

val table_stats = HashSet.stats ()
val _ = Layout.output(table_stats, TextIO.stdOut)
val _ = print "\n"

val table_peek = HashSet.peek(table, Word.fromInt 123, fn _ => true)
val _ = print (concat ["table_peek: ", 
		       case table_peek
			 of NONE => "NONE"
			  | SOME i => concat ["SOME ", Int.toString i], "\n"])

val s = MLton.size table
val _ = print (concat ["s: ", Int.toString s, "\n"])


The important part is that I call every HashSet function and print the
resulting values -- so that should maximize the usefull and used values. 
Looking at the cps after each simplification pass, I see that before the
first remove-unused, we have: 

t_380 = T_59 of ((list_7 array ref * lambdas_85 * word ref * int ref))
val x_71316: int = MLton_size(t_380) (x_71315)

and after the first remove-unused, we have:

t_380 = dummy_62
val x_71316: int = MLton_size(t_380) (x_71315)

So, by the time the useless analysis is run, we've already forced the
MLton_size call to return 0.