We assumed in Example 15.4 and Figure 15.4 that a, b, c,

We assumed in Example 15.4 and Figure 15.4 that a, b, c, and s were all among the first few local variables of the current method, and could be pushed onto or popped from the operand stack with a single one byte instruction. Suppose that this is not the case: that is, that the push and pop instructions require three bytes each. How many bytes will now be required for the code on the left side of Figure 15.4? Most stack-based languages, Java bytecode and CIL among them, provide a swap instruction that reverses the order of the top two values on the stack, and a duplicate instruction that pushes a second copy of the value currently at top of stack. Show how to use swap and duplicate to eliminate the pop and the pushes of s in the left side of Figure 15.4. Feel free to exploit the associativity of multiplication. How many instructions is your new sequence? How many bytes?

Figure 15.4:

Perhaps the most common form of run-time instrumentation counts the number of

Perhaps the most common form of run-time instrumentation counts the number of times that each basic block is executed. Since basic blocks are short, adding a load-increment-store instruction sequence to each block can have a significant impact on run time.

We can improve performance by noting that certain blocks imply the execution of other blocks. In an if. . . then . . . else construct, for example, execution of either the then part or the else part implies execution of the conditional test. If we’re smart, we won’t actually have to instrument the test.

Describe a general technique to minimize the number of blocks that must be instrumented to allow a post-processor to obtain an accurate count for each block.

Design a “test harness” system based on Java annotations. The user should

Design a “test harness” system based on Java annotations. The user should be able to attach to a method an annotation that specifies parameters to be passed to a test run of the method, and values expected to be returned. For simplicity, you may assume that parameters and return values will all be strings or instances of built-in types. Using the annotation processing facility of Java 6, you should automatically generate a new method, test() in any class that has methods with @Test annotations. This method should call the an notated methods with the specified parameters, test the return values, and report any discrepancies. It should also call the test methods of any nested classes. Be sure to include a mechanism to invoke the test method of every top-level class. For an extra challenge, devise a way to specify multiple tests of a single method, and a way to test exceptions thrown, in addition to values returned.

C++ provides a typeid operator that can be used to query the

C++ provides a typeid operator that can be used to query the concrete type of a pointer or reference variable:

if (typeid(*p) == typeid(my_derived_type)) …

Values returned by typeid can be compared for equality but not assigned. They also support a name() method that returns an (implementation dependent) character string name for the type. Give an example of a program fragment in which these mechanisms might reasonably be used.

Unlike more extensive reflection mechanisms, typeid can be applied only to (instances of) classes with at least one virtual method. Give a plausible explanation for this restriction.

Modify the XSLT of Figure C 14.24 to do one or more

Modify the XSLT of Figure C 14.24 to do one or more of the following:

(a) Alter the titles of conference papers so that only first words, words that follow a dash or colon (and thus begin a subtitle), and proper nouns are capitalized. You will need to adopt a convention by which the creator of the document can identify proper nouns.

(b) Sort entries by the last name of the first author or editor. You will need to adopt a convention by which the creator of the document can identify compound last names (“von Neumann,” for example, should be alphabetized under ‘v’).

(c) Allow bibliographic entries to contain an abstract element, which when formatted appears as an indented block of text in a smaller font.

(d) In addition to the book, article, and inproceedings elements, add support for other kinds of entries, such as manuals, technical reports, theses, newspaper articles, web sites, and so on. You may want to draw inspiration from the categories supported by BibTEX.

(e) Format entries according to some standard style convention (e.g., that of the Chicago Manual of Style.

Suppose bibliographic entries in Figure C 14.23 contain a mandatory key element,

Suppose bibliographic entries in Figure C 14.23 contain a mandatory key element, and that other documents can contain matching cite elements. Create an XSLT script that imitates the work of BibTEX. Your script should

(a) Read an XML document, find all the cite elements, collect the keys they contain, and replace them with bibref elements that contain small integers instead.

(b) Read a separate XML bibliography document, extract the entries with matching keys, and write them, in sorted order, to a new (and probably smaller) bibliography.

The small numbers in the bibref elements of the new document from (a) should match the corresponding numbered entries in the new bibliography from (b).

The grammar of Figure 15.6 assumes that all variables are global. In

The grammar of Figure 15.6 assumes that all variables are global. In the presence of subroutines, we should need to generate different code (with fp-relative displacement mode addressing) to access local variables and parameters. In a language with nested scopes we should need to dereference the static chain (or index into the display) to access objects that are neither local nor global. Suppose that we are compiling a language with nested subroutines, and are using a static chain. Modify the grammar of Figure 15.6 to generate code to access objects correctly, regardless of scope. You may find it useful to define a to register subroutine that generates the code to load a given object. Be sure to consider both l-values and r-values, and parameters passed by both value and result.

Figure 15.6:

We noted in Section 13.3.2 that several processors, including the ARM, MIPS,

We noted in Section 13.3.2 that several processors, including the ARM, MIPS, and Power, provide an alternative to compare_and_swap (CAS) known as load_linked/store_conditional (LL/SC). A load_linked instruction loads a memory location into a register and stores certain bookkeeping information into hidden processor registers. A store_ conditional instruction stores the register back into the memory location, but only if the location has not been modified by any other processor since the load_linked was executed. Like compare_and_swap, store_ conditional returns an indication of whether it succeeded or not.

(a) Rewrite the code sequence of Example 13.29 using LL/SC.

(b) On most machines, an SC instruction can fail for any of several “spurious” reasons, including a page fault, a cache miss, or the occurrence of an interrupt in the time since the matching LL. What stepsmust a programmer take to make sure that algorithms work correctly in the face of such failures?

(c) Discuss the relative advantages of LL/SC and CAS. Consider how they might be implemented on a cache-coherent multiprocessor. Are there situations in which one would work but the other would not?

Consider the implementation of software transactional memory in Figure 13.19.(a) How would

Consider the implementation of software transactional memory in Figure 13.19.

(a) How would you implement the read set, write map, and lock map data structures? You will want to minimize the cost not only of insert and lookup operations but also of (1) “zeroing out” the table at the end of a transaction, so it can be used again; and (2) extending the table if it becomes too full.

(b) The validate routine is called in two different places. Expand these calls in-line and customize them to the calling context. What optimizations can you achieve?

(c) Optimize the commit routine to exploit the fact that a final validation is unnecessary if no other transaction has committed since valid time.

(d) Further optimize commit by observing that the for loop in the finally clause really needs to iterate over orecs, not over addresses (there may be a difference, if more than one address hashes to the same orec). What data, ideally, should lock map hold?

Figure 13.9

The dining philosophers problem is a classic exercise in synchronization (Figure 13.20).

The dining philosophers problem is a classic exercise in synchronization (Figure 13.20). Five philosophers sit around a circular table. In the center is a large communal plate of spaghetti. Each philosopher repeatedly thinks for a while and then eats for a while, at intervals of his or her own choosing. On the table between each pair of adjacent philosophers is a single fork. To eat, a philosopher requires both adjacent forks: the one on the left and the one on the right. Because they share a fork, adjacent philosophers cannot eat simultaneously.

Write a solution to the dining philosophers problem in which each philosopher is represented by a process and the forks are represented by shared data. Synchronize access to the forks using semaphores, monitors, or conditional critical regions. Try to maximize concurrency.

Figure 13.20: