Due April 15, 2008

Do exercise 14.1 on pages 269-270. What follows are some hints:

Sometimes when modifying
existing code, it is helpful first to "refactor" it, that is, to
modify it in ways that don't affect its behavior, but that put it into
a more-easily-modifiable structure. Then, after testing that it still
behaves as before, you can make the more substantive changes.

Changing the first-fit code to best-fit might be a case in point. The
current allocate method (in first-fit) is a big method which does a
lot. In particular, it has a big chunk that is devoted to finding the
block to allocate and another big chunk that is devoted to the problem
of removing the allocated space from the free list. Because they are
both in the same method, the interface between the two is relatively
implicit.

A reasonable refactoring would be to break this one big
method into two or more smaller methods, each of which has a more
tightly focused purpose and with an explicit interface between them.
Then you might be in a better position to replace the block-finding
code (to use best-fit) while not screwing up the connection to the
remove-from-feelist code.

In designing the sequences of allocations and deallocations
that will show the difference between first-fit and best-fit, you need
to be careful about what "first" means in "first-fit." You presumably
understand that the first block found that is big enough is used. But
in what order are the blocks examined? Without getting that right,
the "first" is not well defined.

A parenthetical note in the exercise says that you should use the coalescing
version of deallocate. That is necessary for the book's two hints
about code sequences to work. If you'd rather not use the coalescing
version of deallocate, then interchange the last two lines of each of the
two code sequences so that they are

mm.deallocate(c);
mm.deallocate(a);

Deallocating in this order (c before a, rather than a before c) will
make the hints valid whether or not you use the coalescing version of deallocate.

Exercise 14.x1: Consider the following two nearly identical Java programs,
each of which uses an array of Integers, s, as a stack,
with sp serving the role of stack pointer. Each program
repeats 100 times the following two stages:
(1) push the Integers 0 up to 100000, (2) pop them all back off.

Why might Baz be faster than Bar? (Hint: What chapter is this
problem associated with?)

By guessing which of these effects is larger, which of the two
programs do you expect to be faster?

Which one actually is faster? How many times faster? To time
a java program, you can use the shell command time, as in

time java Bar

Exercise 15.x1: One can show the subtype relation on Java types by
drawing a diagram with arrows, where each arrow points from a subtype
to one of its supertypes. Arrows can be omitted that are implied by transitivity. As a simple example, if
the types under consideration are Integer, Number, and Object,
one would draw an arrow pointing from Integer to
Number and a second arrow pointing from
Number to Object, but there would be no
need to show an arrow from Integer directly to
Object. Using this diagramming convention, show the
subtyping relation on List<?>,
ArrayList<?>,
List<Number>, ArrayList<Number>,
List<Integer>, and ArrayList<Integer>.