<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-15131134</id><updated>2011-12-14T18:56:51.568-08:00</updated><category term='C++'/><category term='malloc'/><category term='Compilers'/><category term='JIT'/><category term='pointer analysis'/><category term='Interpreters'/><category term='C'/><category term='Thunks'/><category term='free'/><category term='stack allocation'/><category term='Hashing'/><category term='SSA'/><category term='Lazy Evaluation'/><category term='Java'/><category term='alloca'/><title type='text'>Zhava !</title><subtitle type='html'>Zhava, Azhgo, Compizherzh and muzh mhore</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-15131134.post-6838821576537063080</id><published>2008-08-17T17:36:00.000-07:00</published><updated>2008-08-17T17:41:46.003-07:00</updated><title type='text'>OpenMp for parallelism</title><content type='html'>Using OpenMp is one way to exploit multi-cores using shared memory parallelism (as against Message Passing Interface which is more suitable for distributed shared memory across different nodes of a tightly coupled cluster, where each node is an individual processor (uni/multi)).  OpenMp is usually used to exploit &lt;span style="font-weight: bold; font-style: italic;"&gt;loop level parallelism&lt;/span&gt;, where threads are spawned just before a time consuming loop and each thread operates on different iterations of the loop and all the threads (this is the usual case, there are ways to allow completed threads to continue) then join at the end of the loop. This is in contrast to pthreads which is usually suitable to expressing parallelism at at a much higher level like a function/whole program (ie, using pthreads a process can be used to spawn off multiple threads at the start of the execution, since the starting point of each pthread corresponds to function entry point). Some features of OpenMp:&lt;br /&gt;&lt;br /&gt;- Parallelism is expressed using compiler preprocessor directives inserted before structured blocks of code which are to be parallelized (usually loops). In particular, it uses the #pragma directive (a short form for "pragmatic" which was initially used to support compiler and platform specific features in the compiler) to specify various aspects of parallelism like the number of threads, insertion of barriers, variables to be privatized by each thread, synchronization methods, various of kinds of reductions (sum etc) etc. There are many consequences of this:&lt;br /&gt;&lt;br /&gt; Firstly, to get performance using parallelism, the compiler has to have support for recognizing these OpenMp directives. However, if the compiler does not have support for OpenMp-specific directives, the program will still compile and run as a single thread (as against pthreads which will need the program to be strewn with #ifdef directives which depending on how one looks at it may be worse or similiar to the #pragmas of OpenMp, mantainance-wise). That way, &lt;i&gt;&lt;b&gt;sequential equivalence&lt;/b&gt;&lt;/i&gt; is preserved.&lt;br /&gt;&lt;br /&gt; Secondly, when the number of threads is left unspecified, the compiler is free to choose the optimal/best number of threads for a given architecture. This way, the goal of &lt;i&gt;&lt;b&gt;incremental/scalable parallelism&lt;/b&gt;&lt;/i&gt; is also achieved to a certain extent (scaling a program to newer architectures with higher number of cores without changing much of the source code).&lt;br /&gt;&lt;br /&gt; Thirdly, the compiler is free to experiment with various loop parallelization techniques like DOALL (individual iterations of a loop executed on separate cores) or other forms of pipelined parallelism like DSWP etc. This is a good reason for many optimizing compilers (vendors) to openly adopt OpenMp as a parallelism technology for future many-cores (see &lt;a href="http://softwarecommunity.intel.com/Wiki/Multi-threadappsforMulti-core/469.htm"&gt;here&lt;/a&gt;). Support for auto-parallelization techniques wrt OpenMp is (was?) planned in &lt;a href="http://www.airs.com/dnovillo/Papers/gcc2006.pdf"&gt;gcc&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;- OpenMp supports mainly fork-join kind of parallelism, where there is a single master thread which spawns off many worker threads, and finally all the worker threads join at a barrier once they complete and the master thread continues. Also, it possible to make this &lt;i&gt;&lt;b&gt;worksharing&lt;/b&gt;&lt;/i&gt; paradigm dynamic using the schedule clause in the openmp directive (ie, prefer a more runtime-directed dynamic scheduling for mapping the iteration space of a loop to the underlying threads rather than have a static partitioning of the iterations to threads). This permits experiments with different kind of scheduling algorithms to be tried out in the OpenMp runtime library (that way various workstealing algorithms used by systems like &lt;a href="http://publications.csail.mit.edu/lcs/pubs/pdf/MIT-LCS-TM-548.pdf"&gt;Cilk&lt;/a&gt; can be implemented, although Cilk is more geared toward task-parallelism as against loop/data parallelism exposed in OpenMp programs))&lt;br /&gt;&lt;br /&gt;- A limitation of OpenMp loops is that needs to have structured blocks of code for amenable parallelism and no branches (only program exits are permitted) out of the block are permitted. Not sure if these restrictions still exist.&lt;br /&gt;&lt;br /&gt;- It is quite possible to use pthreads, OpenMp and MPI together in a single program to express parallelism at various levels (and also provide a nightmarish test case for all static analysis tools that are devised specifically to find concurrency related bugs :-)). MPI can be used at the highest level to express cluster level parallelism,  pthreads to express task/thread-level parallelism while OpenMp used to provide loop-level parallelism. It may well turn out that the overhead of using the parallel constructs (creating threads, communication and synchronization) may far outweigh the benefits and one experiences the not too uncommon case of a slowdown instead of a speedup.&lt;br /&gt;&lt;br /&gt;[Ref] Patterns for Parallel Programming&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-6838821576537063080?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/6838821576537063080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=6838821576537063080' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6838821576537063080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6838821576537063080'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/08/openmp-for-parallelism.html' title='OpenMp for parallelism'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-6953977689580183503</id><published>2008-08-02T14:44:00.001-07:00</published><updated>2008-08-02T15:32:05.900-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++'/><category scheme='http://www.blogger.com/atom/ns#' term='Hashing'/><title type='text'>Resolving Hash Collisions</title><content type='html'>Two main techniques for resolving hash collisions:&lt;br /&gt;&lt;br /&gt;[1] &lt;b&gt;Direct Chaining&lt;/b&gt;: When a hashed location is already occupied, the new key and its data are put into a linked list (chain) which is pointed to from the hash table's location. In case there are a large number of collisions, chaining can result in a linear access time to get to the data key that we want to get to. Variants of this technique use a balanced search tree instead of a linked list, thereby reducing the search time to O(log n).&lt;br /&gt;&lt;br /&gt;[2] &lt;b&gt;Open Addressing&lt;/b&gt;: Instead of having a dynamic data structure (and thereby reducing memory allocation calls and being more cache friendly), this technique&lt;br /&gt;uses the other slots in the hash table (presumably an cache friendly array) to resolve collisions.&lt;br /&gt;&lt;br /&gt;There are various ways to resolve hash collisions, using open addressing, which have different behavior in terms of reducing probability of collisions (and thereby having closer to constant time while searching for entries in the hash table) and also in terms of cache friendliness (spatial locality). Some common techniques to resolve hash collisions are:&lt;br /&gt;&lt;br /&gt;(1) &lt;b&gt;Double Hashing&lt;/b&gt;: It applies two hash functions to resolve collisions. Initially a key is searched using a single hash function. If there is a collision, another hash function is used in conjunction with the first hash function. Initially to search for key k, apply h1(k) and in case Key(entry(h1(k)) != k, then for every subsequent search (say it is denoted by i) try the entry given by : &lt;i&gt;&lt;b&gt;h(i,k) = (h1(k) + i*h2(k)) (mod m)&lt;/b&gt;&lt;/i&gt; where m is the size of the hash table.&lt;br /&gt;&lt;br /&gt;(2) &lt;b&gt;Linear Probing&lt;/b&gt;: It uses a single hash function and to resolve collisions, uses consecutive slots in the hash table. Given that we have had i-1 collisions, on the ith probe (search for a free entry while insertion and for the key's satellite data while querying the table), it examines the entry given by:&lt;br /&gt;&lt;i&gt;&lt;b&gt;h(i,k) = (h(k) + c*i) (mod m)&lt;/b&gt;&lt;/i&gt;, where m is the size of the table and c is a constant.&lt;br /&gt;&lt;br /&gt;(3) &lt;b&gt;Quadratic Probing&lt;/b&gt;: It again uses a single hash function, but every time a collision occurs, unlike linear probing, it uses a quadratic function of the (number of collisions occurred so far) to find the next slot. Given that we have had i-1 collisions, on the ith probe (search for a free entry while insertion and for the key's satellite data while querying the table), it examines the entry given by: &lt;i&gt;&lt;b&gt;h(i,k) = (h(k) + c1*i + c2*i*i)(mod m)&lt;/b&gt;&lt;/i&gt;, where c1 and c2 are constants while m is the size of the hash table.&lt;br /&gt;&lt;br /&gt;Double hashing spreads data more uniformly (depending of course on the choice of h2(k)) around in the hash table than linear probing which , when it encounters a collision, uses the immediate next entry (consecutive locations are used for resolving collisions) to fill in the key and its satellite data. This means that linear probing is likely to cause more collisions (since the keys which are genuinely hashed to a particular hash table entry may get offset by some number of slots due to a long chain of entries corresponding to keys that collided earlier. This phenomenon is called &lt;i&gt;&lt;b&gt;clustering&lt;/b&gt;&lt;/i&gt;). But if the first hash function is really good (in terms of spreading data uniformly randomly across the table) and the load factor is sufficiently small, then linear probing is likely to be more cache friendly than double hashing. Quadratic probing spreads data (ie, all the keys that collided) more uniformly through out the table than linear probing, although linear is the most cache friendly of the three hash collision resolution techniques (however, note that this may be offset by the increased likelihood of collisions). Double hashing also may be computationally more expensive since it requires the use of two hash functions.&lt;br /&gt;&lt;br /&gt;Open Addressing (double hashing in particular, why ?) generally poses problems while &lt;b&gt;&lt;i&gt;deletion&lt;/i&gt;&lt;/b&gt;, since the deleted slot occupies some an unwanted spot (tombstone) which can be filled in only by a subsequent insert. Imagine a situation where there are a lot of deletes in the hash table. Now search for an entry may not be constant time since there are a lot of empty slots that one may have to go through before finding the right entry. In contrast, in case of direct chaining the deleted entries do not consume any space in the table per se (only the chain which is a linked list/tree is resized, which as a consequence of being a dynamic data structure is more space efficient).&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Question&lt;/b&gt;&lt;/i&gt;: What technique is commonly used to resolve hash collisions in many (known) C++ projects ?&lt;br /&gt;&lt;br /&gt;* LLVM (a powerful compiler system for C, C++ and many other languages) uses quadratically probed hash table in implementing StringMap (a map from C++ strings to objects) and in DenseMap (a map usually used to hold pairs of values which are small in size, like for eg, pointer to a pointer  which is space efficient)  as described &lt;a href="http://llvm.org/docs/ProgrammersManual.html#ds_map"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;* SGI's hash_map (distributed in Linux as __gnu_cxx::hash_map) uses chaining to resolve hash collisions (linked list ?)&lt;br /&gt;&lt;br /&gt;* Google Sparse hash (a couple of dense and sparse hash maps/sets from Google) uses quadratic probing as described &lt;a href="http://google-sparsehash.googlecode.com/svn/trunk/doc/implementation.html"&gt;here&lt;/a&gt; (as triangular numbers)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-6953977689580183503?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/6953977689580183503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=6953977689580183503' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6953977689580183503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6953977689580183503'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/08/resolving-hash-collisions.html' title='Resolving Hash Collisions'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-3642859794007477052</id><published>2008-06-13T17:14:00.000-07:00</published><updated>2008-06-13T22:17:53.397-07:00</updated><title type='text'>Use of setjmp/longjmp</title><content type='html'>Basically these were calls that are used to recover from exceptional situations for a C program running on UNIX. It works as follows:&lt;br /&gt;&lt;br /&gt;Suppose you have a long call sequence and when some exceptional condition is detected deep in the call chain you want to handle the situation somewhere high up in the call chain (ignoring all the intermediate call sites and the stack frames). It can be done as follows:&lt;br /&gt;&lt;br /&gt;(1) First, call setjmp at the place in the higher position in the call chain with a global environment variable. It saves the program state (pc, sp, gen. purpose regs etc) onto the environment and returns to the current program point (returning a 0). Execution continues&lt;br /&gt;&lt;br /&gt;(2) When a exceptional situation occurs deep in the call chain , call longjmp with the environment variable. This just restores the values of the registers from the environment and returns from the point where setjmp was called originally (with a 1 now).&lt;br /&gt;&lt;br /&gt;Update from Chaitu: As can be seen from above, jumping from somwhere deep down the call chain to some point way higher up can be a recipe for memory leaks, since it is no way to deallocate any heap objects that create in the intermediate functions, unless a custom memory manager is used and some hack (or technique ?) is put in place to identify all the objects created by functions that were called by the handling function.&lt;br /&gt;[&lt;a href="http://www.cs.utk.edu/%7Ehuangj/cs360/360/notes/Setjmp/lecture.html"&gt;Reference&lt;/a&gt;]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-3642859794007477052?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/3642859794007477052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=3642859794007477052' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/3642859794007477052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/3642859794007477052'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/use-of-setjmplongjmp.html' title='Use of setjmp/longjmp'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-8964290812240767192</id><published>2008-06-10T19:36:00.000-07:00</published><updated>2008-06-10T19:37:35.707-07:00</updated><title type='text'>C++: Buffer Growth and STL vector</title><content type='html'>&lt;span style="font-weight: bold; font-style: italic;"&gt;What's the best strategy for managing Buffer Growth ?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For example, in STL vector class, initially the vector may be allocated some space, when there its run out of space and you want to add new elements, it has to do a *realloc* and then copy all the existing elements over from the old space into the newly allocated space. If at every addition , the vector is just grown by 1, then on an average for a eventual vector of size N, there would have been O(N) reallocs/allocation and each element on an average would have been copied O(N) [Why?]. The same holds whenever the buffer grows by a fixed amount ( say 64 bytes or so ) with some small constant factor advantage. However, if on the other hand, when you run out of space, you realloc (X + X/2) elements, where X is the current size of vector, then it turns out that in the long run, on an average O(logN) reallocs happen and each element is copied on an average twice, where N is the final size of the vector.&lt;br /&gt;&lt;br /&gt;n = S(k) = (3/2)* S(k-1). Solve this recurrence to figure out k.&lt;br /&gt;&lt;br /&gt;k is the number of iterations/reallocs to reach the size of n&lt;br /&gt;&lt;br /&gt;[Reference: More Exceptional C++, Herb Sutter]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-8964290812240767192?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/8964290812240767192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=8964290812240767192' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/8964290812240767192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/8964290812240767192'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/c-buffer-growth-and-stl-vector.html' title='C++: Buffer Growth and STL vector'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-6619563545637377977</id><published>2008-06-10T17:32:00.000-07:00</published><updated>2008-06-10T17:33:38.861-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lazy Evaluation'/><category scheme='http://www.blogger.com/atom/ns#' term='Thunks'/><title type='text'>Thunks</title><content type='html'>* A thunk is a small subroutine used for a variety of purposes like :&lt;br /&gt;    - Implementing call by name in Algol&lt;br /&gt;    -  Providing a way of matching actual parameters with formal parameters ( especially useful when calling conventions are different for incomptabile modules ).&lt;br /&gt;    &lt;br /&gt;* As a side effect of the above two, thunks provide a way of lazy evaluation, ie, if you are passing some parameters (which are expressions themselves ), to functions, eager evaluation usually evaluates the whole expression/parameter list and then passes it onto the called function irrespective of whether it is used at all ( at runtime ). In case of a thunk , the first time a parameter is used, the thunk translates/evaluates the expression into an address/value at that address depending on whether the parameter is used as a lvalue/rvalue and then returns it. This evaluation takes place only once and every subsequent time, the thunk has the evaluated expression.&lt;br /&gt;&lt;br /&gt;* This is especially useful in functional programming, where the parameters passed are functions themselves, and evaluation of functions are done only when necessary. This also helps in dealing with infinite data/ handling termination of recursive functions passed as parameters [ Call by need ]&lt;br /&gt;&lt;br /&gt;* A thunk is implemented as a list of three items :&lt;br /&gt;    - Thunk Evaluator&lt;br /&gt;    - Expression ( denoting the actual parameter)&lt;br /&gt;    - Environment ( in which the thunk is evaluated ).&lt;br /&gt;&lt;br /&gt;Once the thunk evaluates the expression in the environment, it replaces the 'Thunk Evaluator' with the value so that subsequent calls will give the value directly. In some sense, thunks are closures specifically for parameter passing.&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://compilers.iecc.com/comparch/article/98-02-103"&gt;Reference 1&lt;/a&gt;] &lt;a href="http://compilers.iecc.com/comparch/article/98-02-103"&gt;&lt;/a&gt;&lt;br /&gt;[&lt;a href="http://portal.acm.org/citation.cfm?id=366084&amp;amp;CFID=15460642&amp;amp;CFTOKEN=81546454&amp;amp;qualifier=LU1007252"&gt;Reference 2&lt;/a&gt;] &lt;a href="http://portal.acm.org/citation.cfm?id=366084&amp;amp;CFID=15460642&amp;amp;CFTOKEN=81546454&amp;amp;qualifier=LU1007252"&gt;&lt;/a&gt;&lt;br /&gt;[&lt;a href="http://portal.acm.org/citation.cfm?id=366084&amp;amp;CFID=15460642&amp;amp;CFTOKEN=81546454&amp;amp;qualifier=LU1007252"&gt;Reference 3&lt;/a&gt;] &lt;a href="http://www.cs.uiuc.edu/class/fa05/cs421/current/lectures/25-scott-InfiniteData.ppt"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-6619563545637377977?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/6619563545637377977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=6619563545637377977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6619563545637377977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6619563545637377977'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/thunks.html' title='Thunks'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-784188919514812197</id><published>2008-06-10T17:30:00.000-07:00</published><updated>2008-06-10T17:31:21.312-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='malloc'/><category scheme='http://www.blogger.com/atom/ns#' term='free'/><title type='text'>Behind malloc() and free()</title><content type='html'>* Whenever we use malloc(), if it finds that memory is not available within the data segment of the process, (as a last step ) it internally calls brk() system call . This system call increases the data segment address (virtual) space of the current process by the requested amount. Actually it is quite possible that although brk() returns sucessfully, physical memory might not be quite available.&lt;br /&gt;&lt;br /&gt;* When we use free(), it returns the specific chunk of memory to allocation library ( not to the OS ). Next time you call malloc(), the allocation library may return the freed space without calling the brk() system call. Thus the OS just increases the virtual address space of the Data Segment (by brk()), but the management of the memory that is returned is up to the allocation library . Also, i dont see a system call to explicitly reduce the virtual address space of a process ( a kind of reverse brk() ). So once VA increases, it is upto the allocation library to manage this memory. Update: You did not look around enough ! In fact, calling brk() with a negative argument would reduce the VM address space of the process by that amount, only thing is that the allocation library can't do this unless it is sure that last contigous portion of VM (that is requested to be returned to the OS) is not used by the process.&lt;br /&gt;&lt;br /&gt;* All the memory management policies like first fit, best fit and maintaining a free list, storing the size within a header of allocated block and so on goes on in the allocation library with the memory got by brk(). Only when there is no memory available, is malloc() going to go to the OS.&lt;br /&gt;&lt;br /&gt;* Some of the popular allocators are Doug Lea Malloc, BSD Malloc and Hoard&lt;br /&gt;&lt;br /&gt;* Also, memory management can be split between the program and the memory management by using reference counts ( for data which is read-only in some cases or even for shared data ) and then use garbage collection ( no explicit free - helps in the fact that we dont need to keep track of pointers that point to a data chunk and worry about freeing pointers twice/ using a freed pointer ).&lt;br /&gt;&lt;br /&gt;* Another memory management technique is memory pools. For eg, the Apache web server has different memory pools, one that lasts a request, one that lasts a connection, one that lasts a thread and so on. GNU's &lt;i&gt;&lt;b&gt;obstack &lt;/b&gt;&lt;/i&gt;implementation is one way of using allocation pools [ provides reuse of similar sized data chunks ].&lt;br /&gt;&lt;br /&gt;[&lt;a href="http://www-128.ibm.com/developerworks/linux/library/l-memory/"&gt;Reference&lt;/a&gt;]&lt;a href="http://www-128.ibm.com/developerworks/linux/library/l-memory/"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-784188919514812197?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/784188919514812197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=784188919514812197' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/784188919514812197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/784188919514812197'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/behind-malloc-and-free.html' title='Behind malloc() and free()'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-8493564315201809557</id><published>2008-06-10T17:24:00.000-07:00</published><updated>2008-06-10T17:27:14.819-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSA'/><category scheme='http://www.blogger.com/atom/ns#' term='Compilers'/><title type='text'>Worst case Number of Phi Nodes in a SSA graph</title><content type='html'>&lt;span style="font-weight: bold; font-style: italic;"&gt;Q. What is the worst case number of phi functions in a SSA graph ?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It could be O(N^2).  Consider this program:&lt;br /&gt;&lt;br /&gt;while (...)&lt;br /&gt;{&lt;br /&gt;      while (...)&lt;br /&gt;      {&lt;br /&gt;             while (...)&lt;br /&gt;            {&lt;br /&gt;                   i = ...&lt;br /&gt;            }&lt;br /&gt;           i = ...&lt;br /&gt;      }&lt;br /&gt;      i = ...&lt;br /&gt;}&lt;br /&gt;... = i&lt;br /&gt;&lt;br /&gt;A minimal phi insertion (confirm this !) has 5 phi nodes. This is around (N/2). For V variables, number of phi functions would be (N/2)*V or around O(N^2) phi functions.&lt;br /&gt;&lt;br /&gt;i0 = ...&lt;br /&gt;while (...)&lt;br /&gt;{&lt;br /&gt;      i1 = phi(i0, i7)&lt;br /&gt;  while (...)&lt;br /&gt;     {&lt;br /&gt;             i2 = phi(i1, i5)&lt;br /&gt;      while (...)&lt;br /&gt;            {&lt;br /&gt;                   i3 = i2;&lt;br /&gt;            }&lt;br /&gt;            i4 = phi(i3,i2)&lt;br /&gt;            i5 = i4&lt;br /&gt;     }&lt;br /&gt;      i6 = phi(i4, i1)&lt;br /&gt;      i7 = i6&lt;br /&gt;}&lt;br /&gt;i8 = phi(i7, i0)&lt;br /&gt;&lt;br /&gt;There is some interesting discussion on this in comp.compilers &lt;a href="http://compilers.iecc.com/comparch/article/05-03-095"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-8493564315201809557?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/8493564315201809557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=8493564315201809557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/8493564315201809557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/8493564315201809557'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/worst-case-number-of-phi-nodes-in-ssa.html' title='Worst case Number of Phi Nodes in a SSA graph'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-5522729056633446923</id><published>2008-06-10T17:22:00.000-07:00</published><updated>2008-06-10T17:23:51.380-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='stack allocation'/><category scheme='http://www.blogger.com/atom/ns#' term='alloca'/><title type='text'>The alloca routine: Stack allocation</title><content type='html'>The &lt;span style="font-weight: bold; font-style: italic;"&gt;alloca&lt;/span&gt; routine allows a C program to allocate memory on the stack instead of the heap. The advantage is that this memory is cleaned up once the allocating routine exits and does not need to explicitly do a ' free'. So probably you would not need to worry about memory leaks (but you are obviously restricting the life time of the object to the method boundary -- an escape analysis could use this method to convert all malloc calls to alloca calls for captured objects).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;How could this be implemented ?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It is just a manipulation of the stack pointer (esp) using the size passed as an argument to the alloca routine (in a register). Since the base pointer (ebp) holds the base of the current function's stack frame, when the function returns, the stack is unwound using ebp and the de-allocation is automatically taken care of. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;What could be the potential disadvantages ? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Size is obviously a restriction as the stack space grows linearly and upto a limit.  There are other disadvantages mentioned in &lt;a href="http://www.winehq.org/pipermail/wine-devel/2001-February/000149.html"&gt;this &lt;/a&gt;Wine mailing list thread.&lt;br /&gt;&lt;br /&gt;A long list of pros and cons are discussed in the gdb developer's mailing list. See &lt;a href="http://www.ecos.sourceware.org/ml/gdb/2000-11/msg00053.html"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-5522729056633446923?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/5522729056633446923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=5522729056633446923' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/5522729056633446923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/5522729056633446923'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/alloca-routine-stack-allocation.html' title='The alloca routine: Stack allocation'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-6766412132936204366</id><published>2008-06-10T17:06:00.000-07:00</published><updated>2008-06-10T17:20:03.588-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='pointer analysis'/><title type='text'>Pointer Analysis: C vs Java</title><content type='html'>* &lt;span style="font-style: italic; font-weight: bold;"&gt;Stack variables and Heap&lt;/span&gt; : In case of C/C++, objects are allocated on the stack (not just scalar locals/pointer variables). So, we can make use of this property to eliminate any points-to edges from the heap objects  to objects on the stack once a function returns. This can be done only when we are sure that the given program either is well-written and has no dangling references (which itself would require another analysis i guess) and pointer references in the program respect the lifetime of the pointed-to objects. Alternately, we can track this points-to edge (from heap to stack object) and if there is a de-reference of this pointer, you can flag an error/warning in the compiler. In case of Java, objects are not allocated on the stack and hence there can't be any reference to an object on the stack from a field of a heap object at all (since you can't take the address of a local scalar variable and an assignment always assigns a 'reference' to another heap object and not the stack variable). So, aliasing between heap and stack objects/variables never arises in Java. Also the same applies to pointers from Global Variables to Stack Variables&lt;br /&gt;&lt;br /&gt;* &lt;span style="font-weight: bold; font-style: italic;"&gt;Direct Manipulation of Pointers&lt;/span&gt;: In C/C++, it is possible to take the address of a variable (using &amp;amp; operator), add, subtract values (offsets) to it, and then indirectly access the variable at the new address (using *), which makes it possible for a pointer to directly point to the middle of a (logical) data structure. So, things like alignment, byte-level reasoning in the analysis become more important to safely infer points-to sets. It is also possible to arbitrarily cast pointers from one type to another. This means declared types are usually useless from the analysis perspective. A lot of this could be solved by representing such operations by special cast instructions in the IR, specifying the alignments (for things like unions) explicitly in the IR. All these are done in the LLVM IR. Java, on the other hand, is strongly typed and permits only indirect manipulation of pointers which are type safe (or explicit exception is thrown as in the case of casts). This means the declared types not only can safely be used in the analysis but also can be used to make the analysis more precise (scalars of two different classes which are not related in anyway by the inheritance hierarchy can't point to the same object) .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-6766412132936204366?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/6766412132936204366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=6766412132936204366' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6766412132936204366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/6766412132936204366'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/pointer-analysis-c-vs-java.html' title='Pointer Analysis: C vs Java'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-2107112419633762887</id><published>2008-06-10T16:41:00.000-07:00</published><updated>2008-06-10T17:01:41.243-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JIT'/><category scheme='http://www.blogger.com/atom/ns#' term='Compilers'/><category scheme='http://www.blogger.com/atom/ns#' term='Interpreters'/><title type='text'>Just In Time Compilation</title><content type='html'>A Just in time compiler is one which is somewhat mid-way between an interpreter and a static compiler. Historically, JITs were design to overcome the slow performance of interpreters by caching native code of frequently interpreted source statements. But nowadays, with the advent of multicore, JITs are playing an interesting role in leveraging the extra cores for a variety of tasks like (data, target cpu) specialized generation of code, much beyond the realm of traditional static compilers. Some comparisons with other models of compilation/execution:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;JIT vs Interpretation&lt;/span&gt;: Both usually operate on same low level IR (bytecode), translation to native code is done at runtime. However, an interpreter translates one instruction at a time and usually does not cache the generated native code to prevent re-translation. On the other hand, a JIT compiler translates a much coarser level entity like a function/module at a time and also the translated native code is cached to speed up execution.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;JIT vs Static Compilation&lt;/span&gt;: Static compilers translate high level code like C source code to low level IR and low level IR in turn to machine code at the same (compile) time. However in a JIT, this is broken down into two steps: Translation from C source code to Low Level IR  is done at compile time while the translation from Low Level IR to Machine Code is done at runtime (just before execution). Some of the potential advantages of JIT over static compilation are: Target CPU specialization (where at runtime, it is determined whether the CPU supports certain type of instructions, like for eg, vector instructions, and emitting code using those instructions), Whole program dynamic optimization (inlining dynamic library calls) and Runtime data specialization (where a JIT can generate different versions of a function depending upon the certain variable values, known only at runtime, which may in turn lead to optimizations like memoization)&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;JIT vs Dynamic Binary Compilation&lt;/span&gt;: A  JIT usually has more semantic information (eg, low level IR with types, basic block information etc) and recompilation is usually done from the low level IR (usually called bytecode). A dynamic binary translator, on the other hand, does re-translation of machine code to machine code by going through byte-code, ie,  Machine Code → ByteCode → Machine Code or even directly re-translates Machine Code  → Machine Code. Because machine code has very little semantic information, re-translation is usually done for smaller compilation units, like a basic block and unlike a JIT, whole program optimization is usually not possible.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-2107112419633762887?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/2107112419633762887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=2107112419633762887' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/2107112419633762887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/2107112419633762887'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2008/06/just-in-time-compilation.html' title='Just In Time Compilation'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-116227187885165597</id><published>2006-10-30T21:16:00.000-08:00</published><updated>2006-10-30T21:18:28.196-08:00</updated><title type='text'>Questions and more questions</title><content type='html'>&lt;span style="font-weight: bold;"&gt;1.&lt;/span&gt; Which one of the following  order would result in a better code generation :&lt;br /&gt;   (a) Instruction Scheduling and then Register Allocation&lt;br /&gt;   (b) Register Allocation and then Instruction Scheduling&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-116227187885165597?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/116227187885165597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=116227187885165597' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/116227187885165597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/116227187885165597'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2006/10/questions-and-more-questions.html' title='Questions and more questions'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112845235261502831</id><published>2005-10-04T11:44:00.000-07:00</published><updated>2005-10-04T11:59:12.623-07:00</updated><title type='text'>GCJ, StringBuilder &amp; Escape Analysis</title><content type='html'>Sun has recently introduced the 'StringBuilder' class which is meant to be&lt;br /&gt;an unsynchronized version of the StringBuffer class in JDK 1.5. Whenever there are strings which are going to be used by single thread, you use a StringBuilder rather than a StringBuffer. They claim that &lt;a href="http://java.sun.com/j2se/1.5.0/docs/guide/performance/speed.html"&gt;StringBuilder is almost always faster than StringBuffer.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Consider this problem : You have lots of code in a Java application ( possibly a ERP web application ) which has uses of StringBuffers one every 10 lines of code ( we know that, don't we with Application Frameworks appending URLs etc , javascript targets ) and what with Threads being a absolute taboo in web applications , would'nt there be a lot to gain if we used StringBuilders instead of StringBuffers ?&lt;br /&gt;&lt;br /&gt;Now how exactly do we find StringBuffers that are used which are local to a thread/method and replace them with StringBuilders ? Just think of the millions of lines of code that we need to check to make sure only a single thread/method accesses a StringBuffer.&lt;br /&gt;&lt;br /&gt;Here is where Escape Analysis could help. And this is what the GCJ guys are discussing &lt;a href="http://gcc.gnu.org/ml/java/2005-10/msg00006.html"&gt;here.  &lt;/a&gt;&lt;span class="" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;/span&gt;&lt;br /&gt;But the one point at which I am not clear is that why should inheritance pose a (big) problem ? Can't we first do a Class Heirarchy Analysis (CHA) / Rapid Type Analysis (RTA) to constrain the list of methods that could be possibly called ?&lt;br /&gt;&lt;span class="" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112845235261502831?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112845235261502831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112845235261502831' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112845235261502831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112845235261502831'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/10/gcj-stringbuilder-escape-analysis.html' title='GCJ, StringBuilder &amp; Escape Analysis'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112689069562482174</id><published>2005-09-16T09:54:00.000-07:00</published><updated>2005-09-16T10:19:34.860-07:00</updated><title type='text'>Computing Square Root,  Fixed Point Iteration  &amp; Lisp</title><content type='html'>A function is said to have reached a &lt;span style="font-weight: bold;"&gt;fixed point&lt;/span&gt; when f(y) = y.&lt;br /&gt;We can use this to find the square root of a function.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;   &lt;li&gt; Guess a value for the square root , say y&lt;/li&gt;   &lt;li&gt; Find the value of &lt;span style="font-weight: bold;"&gt;Avg(y, x/y )&lt;/span&gt;. If it is same as y, then we are done.&lt;/li&gt;   &lt;li&gt; Else assign Avg(x/y, y ) to y ( the new improved value ). Go back to Step 2.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;Note that when y = Avg(x/y, y) the value of y that is possible is sqrt(x).So when the fixed point for the above function is reached, the value y is the square root.&lt;br /&gt;&lt;br /&gt;So, if we have a black box which computes the fixed point of any function, then&lt;br /&gt;we can pass to this black box , the function Avg(x/y, y ) &amp; find it's fixed point.&lt;br /&gt;&lt;br /&gt;Thus, in terms of a functional language , if we have a function for computing the fixed point, we can pass any function ( Avg in this case ) to it to be able to get the desired value. In terms of LISP, this would imply we write a &lt;span style="font-style: italic; font-weight: bold;"&gt;higher-order procedure &lt;/span&gt;which&lt;span style="font-style: italic;"&gt; &lt;/span&gt;takes in another procedure as input [ function here being a first class value ] and returns the fixed point.&lt;br /&gt;&lt;br /&gt;Note that fixed point iteration that we use here is exactly the same as that used for data flow analysis in any control flow graph [ lattice of functions ? ]&lt;br /&gt;&lt;br /&gt;As an aside , the kinds of abstraction that LISP supports : &lt;span style="font-style: italic; font-weight: bold;"&gt;Black Box Abstraction&lt;/span&gt; (Higher order procedures ), &lt;span style="font-style: italic; font-weight: bold;"&gt;Conventional Interfaces&lt;/span&gt; ( Generics, OOPs ), &lt;span style="font-style: italic; font-weight: bold;"&gt;Meta-linguistic Abstraction&lt;/span&gt; ( being able to write other programming languages in LISP ,eg logic programming language, register machines )&lt;br /&gt;&lt;a href="http://swiss.csail.mit.edu/classes/6.001/abelson-sussman-lectures/videos-divx/Lecture-1a.avi"&gt;&lt;br /&gt;[Reference]&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112689069562482174?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112689069562482174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112689069562482174' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112689069562482174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112689069562482174'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/09/computing-square-root-fixed-point.html' title='Computing Square Root,  Fixed Point Iteration  &amp; Lisp'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112611053182786033</id><published>2005-09-07T09:21:00.000-07:00</published><updated>2005-09-07T09:39:03.433-07:00</updated><title type='text'>Radix Exchange Sort , Straight Radix Sort &amp; Induction</title><content type='html'>&lt;span style="font-weight: bold; font-style: italic;"&gt;Radix Exchange Sort :&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; Sorts beginning from the most significant digit and then for each list, inductively sort the remaining digits by forming lists within each list . For eg, to sort : 12 45 67 22 14 6 23 90 11&lt;br /&gt;&lt;br /&gt;  First form lists from 0 to 9 for the 10's place :&lt;br /&gt;   0 : 06&lt;br /&gt;   1 : 12 14 11&lt;br /&gt;   2 : 22 23&lt;br /&gt;   3 :&lt;br /&gt;   4 : 45&lt;br /&gt;   5 :&lt;br /&gt;   6 : 67&lt;br /&gt;   7 :&lt;br /&gt;   8 :&lt;br /&gt;   9 : 90&lt;br /&gt;&lt;br /&gt;  Then for each list, form lists within for the unit's place&lt;br /&gt;   For eg, for list 1 : ( lists based on unit's place )&lt;br /&gt;                    0 :&lt;br /&gt;                    1 :  11&lt;br /&gt;                    2 :  12&lt;br /&gt;                    3 :&lt;br /&gt;                    4 :  14&lt;br /&gt;                    5 :       &lt;br /&gt;  Now read off all numbers in order : 06 11 12 14 22 23 45 67 90&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;Straight Radix Sort :&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    This is the traditional sorting taught in class based on sorting beginning at the least significant digit. The point here to note is that you need to form a list of numbers one for each kind of digit ( 10 lists for the decimal system ) only once and then you need one more queue for holding the numbers at the end of each pass.&lt;br /&gt;&lt;br /&gt;     This sorting is based on induction in the sense : Assume you have sorted the least i digits and now you have two numbers starting at the (i + 1)th digit as  u = a[i digits] and v = b[i digits] with a = b . Now since u and v are sorted in the least i digits , if  [ i digit - u] &lt; [ i digit - v ] then u would precede v in the queue already and the current sort phase would not disturb the order in this pass and hence it would remain sorted.&lt;br /&gt;&lt;br /&gt;    For eg if u = 6789 and v = 6098 , then in the queue v would precede u ( as 098 &lt; 789 ) and in this phase first v would be put in list 6 followed by u. Hence the numbers would remain sorted.&lt;br /&gt;&lt;br /&gt;     Its complexity is &lt;span style="font-style: italic; font-weight: bold;"&gt;O(kn)&lt;/span&gt; where k is the max # of digits in any input number and n is the total size of input ( k passes, at every pass , all numbers are relocated )&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112611053182786033?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112611053182786033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112611053182786033' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112611053182786033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112611053182786033'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/09/radix-exchange-sort-straight-radix.html' title='Radix Exchange Sort , Straight Radix Sort &amp; Induction'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112516458447852738</id><published>2005-08-27T10:24:00.000-07:00</published><updated>2005-08-27T10:48:47.043-07:00</updated><title type='text'>Functional Programming and Quicksort</title><content type='html'>Just stumbled upon the &lt;a href="http://www.haskell.org/aboutHaskell.html"&gt;Haskell&lt;/a&gt; page.&lt;br /&gt;&lt;br /&gt;&lt;span class="" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;/span&gt;Looks like Functional Programming really has some points :&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;In functional programs, most of the times, &lt;span style="font-weight: bold; font-style: italic;"&gt;the specification is THE code&lt;/span&gt; . Take for eg, the quicksort example in Haskell :&lt;br /&gt;&lt;/li&gt; &lt;/ul&gt; &lt;pre&gt;        &lt;span style="font-size:130%;"&gt; &lt;span style="font-size:85%;"&gt;qsort []     = []&lt;br /&gt;       qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x&lt;br /&gt;                      where&lt;br /&gt;                         elts_lt_x   = [y | y &lt;- xs, y &lt; x]            &lt;br /&gt;                         elts_greq_x = [y | y &lt;- xs, y &gt;= x]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; &lt;ul&gt;   &lt;li&gt;You specify &lt;span style="font-weight: bold; font-style: italic;"&gt;what you want and not how you want it to be done&lt;/span&gt;. In the above example, you are just specifying the property ( invariant ) that is to be obeyed at every step of the algorithm. In case of imperative programming languages, you have to "mentally execute the programs to be able to write programs".&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;The most important feature of a functional programming language is that &lt;span style="font-style: italic; font-weight: bold;"&gt;functions are treated as first class objects&lt;/span&gt;, in the sense you can define functions at runtime, compose functions just like you would assign values to variables , use them to construct expressions in imperative functions.&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;One more thing to be noted is the&lt;span style="font-style: italic; font-weight: bold;"&gt; polymorphic nature&lt;/span&gt; of the above program. The quicksort program above can be used to sort chars, ints, list of chars, list of list of chars and so on. In case of C, you would need separate programs for 1-D, 2-D and 3-D arrays.&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;Other features of FPs include &lt;span style="font-style: italic; font-weight: bold;"&gt;automatic garbage collection, lazy evaluation&lt;/span&gt; and so on.&lt;br /&gt;&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;&lt;span style="font-weight: bold;"&gt;Pitfalls&lt;/span&gt; : The quicksort program is from the view of the specifier ( mathematician ? ). It has no references whatsoever to any code for memory management, so the Haskell system ends up using a &lt;span style="font-style: italic; font-weight: bold;"&gt;lot of space behind the scenes&lt;/span&gt;, whereas in C, Hoare's method sorts the array &lt;span style="font-style: italic;"&gt;in place.&lt;/span&gt;&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;Functional Programming languages are more suited in those environments where users are willing to take a dip in performance while trading it with ease-of-program writing, fewer bugs and more often that not using programs which have been proven to be working correct !&lt;br /&gt;&lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112516458447852738?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112516458447852738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112516458447852738' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112516458447852738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112516458447852738'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/08/functional-programming-and-quicksort.html' title='Functional Programming and Quicksort'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112401120868145014</id><published>2005-08-14T02:06:00.000-07:00</published><updated>2005-08-14T02:20:08.686-07:00</updated><title type='text'>Turing Complete Languages</title><content type='html'>&lt;ul&gt;   &lt;li&gt;A programming language is said to be Turing complete if it has computational power equivalent to a &lt;span style="font-weight: bold;"&gt;Universal Turing machine (UTM)&lt;/span&gt; - &lt;blockquote style="font-style: italic;"&gt;"It can be shown that a single special machine of that type can be made to do the work of all. It could in fact be made to work as a model of any other machine. The special machine may be called the universal machine"&lt;/blockquote&gt;&lt;/li&gt;   &lt;li&gt;Physically any such programming language is impossible to achieve since it requires unlimited storage  &lt;span style="font-weight: bold;"&gt;( Why ? )&lt;/span&gt; . So , the term Turing complete languages applies to all those programming languages that would emulate a UTM &lt;span style="font-style: italic;"&gt;if &lt;/span&gt;provided with unlimited storage.&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;All general purpose programming languages are Turing complete ( C, Java, LISP, Haskell, Prolog etc ) . The non-Turing complete PLs are rare to find, for eg, machines that always halt, those languages in which it would be impossible to form loops. Also, not all programs solved by Turing complete languages can't be solved by programming languages with finite looping capabilities.&lt;/li&gt; &lt;/ul&gt;                                                                                                          &lt;a href="http://en.wikipedia.org/wiki/Turing-complete"&gt;[Reference]&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112401120868145014?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112401120868145014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112401120868145014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112401120868145014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112401120868145014'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/08/turing-complete-languages.html' title='Turing Complete Languages'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112333819284960855</id><published>2005-08-06T07:06:00.000-07:00</published><updated>2005-08-06T07:23:12.856-07:00</updated><title type='text'>On Searches</title><content type='html'>&lt;ul&gt;   &lt;li&gt; Find whether an user-given element  exists in a &lt;span style="font-style: italic;"&gt;cyclically sorted&lt;/span&gt; array  [ For eg, say find whether 108 exists in a &lt;span style="font-style: italic;"&gt;cyclically sorted&lt;/span&gt; array 67,89,109,4,26,33,45,55 with indices from 1 to 8 ] .&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt; Suppose you have an infinite sequence of integers ( lets say some kind of streaming data ) all of which arrive in sorted order in a buffer area ( in the form of an array ) . How do you find a particular element ? Note that you can't use a binary search since the size of the array is not known&lt;br /&gt;  &lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt; Suppose you know beforehand that an array has sorted integers in such a way that they are almost      uniformly distributed. How do you find the existence of a particular element ?&lt;/li&gt; &lt;/ul&gt;        &lt;span style="font-weight: bold;"&gt;Answers(?)&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;   &lt;li&gt; Two binary searches , one to find the smallest element and hence start of the sorted array and another to find the required element&lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;Use the &lt;span style="font-style: italic;"&gt;doubling search &lt;/span&gt;. Search elements at positions 2,4,8,16,32, etc .Once the range is found, binary search within the range . O(log i) + O(log j) where 'i' is the index at which you stop doubling search and 'j' is the number of elements within the range&lt;br /&gt;  &lt;/li&gt; &lt;/ul&gt; &lt;ul&gt;   &lt;li&gt;Use the &lt;span style="font-style: italic;"&gt;interpolation search . &lt;/span&gt;Rather than dividing the interval by half everytime, try to guess the neighbourhood of the element of interest by finding out the interval of separation between successive elements ( works well with uniformly distributed elements ). &lt;a href="http://www.auto.tuwien.ac.at/%7Eblieb/woop/inter.html"&gt;[Reference].&lt;span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;/span&gt;&lt;/a&gt;Supposed be of O(loglogn) on an average ( Proof ? )    &lt;br /&gt;  &lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112333819284960855?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112333819284960855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112333819284960855' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112333819284960855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112333819284960855'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/08/on-searches.html' title='On Searches'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112331675788167851</id><published>2005-08-06T01:11:00.000-07:00</published><updated>2005-08-06T01:31:33.976-07:00</updated><title type='text'>Programmer Defined Overloading : Syntatic Heroin ?</title><content type='html'>An ACM Queue article : http://acmqueue.com/modules.php?name=Content&amp;pa=showpage&amp;amp;pid=315&lt;br /&gt;&lt;br /&gt;Author's Arguments :&lt;br /&gt;&lt;br /&gt;Things with different meanings are made to look the same, hampers readability, complicates compiler writing ( resolution of the function call to the right function definition), any inadvertant mistakes by the programmer in making a function call coupled with conversion rules lands us in soup.&lt;br /&gt;&lt;br /&gt;Note that all these arguments are being made for programmer defined overloading and the author sees no problems with built-overloading ( for eg, of operators )&lt;br /&gt;&lt;br /&gt;Can the same arguments be made for generics/templates ? Tradeoffs between developer( code writer) friendliness, maintainer ( debugger ) friendliness and compiler writer friendliness ? Are the lack of proper typing rules really to blame rather than overloading ?&lt;br /&gt;&lt;br /&gt;Interestingly this article has a reference to the JLS :-) . Overloading &amp;amp; Java ?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112331675788167851?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112331675788167851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112331675788167851' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112331675788167851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112331675788167851'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/08/programmer-defined-overloading.html' title='Programmer Defined Overloading : Syntatic Heroin ?'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15131134.post-112322356120141848</id><published>2005-08-04T23:27:00.000-07:00</published><updated>2005-08-04T23:32:41.206-07:00</updated><title type='text'>Why SSA is good for Java compilation</title><content type='html'>"The strong typing in Java simplifies much of the compiler analysis. In particular, Java semantics ensure that a local variable can only be modified by explicit&lt;br /&gt;assignment to the variable. In contrast, the creation of a pointer to a local variable in C allows a local variable to be modified at any time by any routine. Similarly, a field of a Java object can never be modified by an assignment to a different field. Because of these properties that make most data&lt;br /&gt;dependences explicit in Java programs, we believe that static&lt;br /&gt;single assignment (SSA) form is highly appropriate as an intermediate&lt;br /&gt;representation for Java. SSA graphs make most or all of the dependences in a method explicit, but provide great freedom in optimizing and scheduling the resulting code."&lt;br /&gt;                    - The Swift Java Compiler: Design and Implementation&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15131134-112322356120141848?l=zhava.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zhava.blogspot.com/feeds/112322356120141848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15131134&amp;postID=112322356120141848' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112322356120141848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15131134/posts/default/112322356120141848'/><link rel='alternate' type='text/html' href='http://zhava.blogspot.com/2005/08/why-ssa-is-good-for-java-compilation.html' title='Why SSA is good for Java compilation'/><author><name>Prakash</name><uri>http://www.blogger.com/profile/06008932623463651524</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
