( nug | 2010. 11. 18., cs – 07:33 )

Dead Code Elimination in JavaScript
One of the changes we made to the IE9 JavaScript Engine, codenamed Chakra, to improve performance on real world web sites involves dead code elimination. Yesterday afternoon, someone posted a question (“What sorts of code does the analysis work on, other than the exact [math-cordic test] function included in SunSpider,”) on the Microsoft Connect feedback site. Given some recent interest in this question, this blog answers that question.

Briefly, the IE9 JavaScript engine includes many different changes to improve the performance of real-world Web sites and applications. You can see this in action by visiting www.ietestdrive.com and trying the samples there with IE9 and other browsers. The behavior of the IE9 JavaScript engine is not a “special case optimization” for any benchmark and not a bug.

Some of the optimizations we’ve made to the JavaScript interpreter/compiler in IE9 are of a type known in the compiler world as dead code elimination. Dead code elimination optimizations look for code that has no effect on a running program, and removes the code from the program. This has a benefit of both reducing the size of the compiled program in memory and running the program faster.

Here is a very simple example of JavaScript code that is a candidate for dead code elimination. Because the conditional will always evaluate to false, the JavaScript engine can eliminate this code altogether.

function func() {
var x = 1;
var y = 3;
var w = x + y;

if (w != 4) {
// dead code
}Dead code elimination is especially effective when code would be executed many times, as in a loop. In the following example, the code in the loop repeatedly overwrites the same variable (what is known in computer science as a dead store), so it can be reduced to only one call.

function func(a, b) {
var x;
var i = 300;
while (i--) {
x = a + b; // dead store
}In the example below, the code executed in the loop is not used anywhere in the program outside the loop, so the entire loop can be safely removed.

function sum() {
var a = [1, 2, 3, 4, 5];
var sum = 0.0;

// dead loop elimination
for (var i = 0; i < 5; i++) {
sum += a[i];
}Developers often write dead code without knowing it and can rely on compilers to optimize the code. Most modern compilers today run an extensive set of dead code elimination optimizations.

So, why does this affect the math-cordic benchmark in the Webkit SunSpider suite? Let’s take a look at the inner function in the test.

function cordicsincos() {
var X;
var Y;
var TargetAngle;
var CurrAngle;
var Step;
X = FIXED(AG_CONST); /* AG_CONST * cos(0) */
Y = 0; /* AG_CONST * sin(0) */

TargetAngle = FIXED(28.027);
CurrAngle = 0;
for (Step = 0; Step < 12; Step++) {
var NewX;
if (TargetAngle > CurrAngle) {
NewX = X - (Y >> Step);
Y = (X >> Step) + Y;
X = NewX;
CurrAngle += Angles[Step];
} else {
NewX = X + (Y >> Step);
Y = -(X >> Step) + Y;
X = NewX;
CurrAngle -= Angles[Step];
} The benchmark runs an expensive loop, and then does nothing with the results; the benchmark is written exactly in a way that triggers this general optimization.

Of course, the benchmark could be rewritten to avoid triggering this optimization, which would bring our performance on this specific benchmark in line with other browsers.

The interest in this issue is a great example of why these microbenchmarks fail to represent the real world web. Webkit Sunspider uses an expensive JavaScript loop to approximate sine and cosine. Real world sites would actually use the much faster and CPU-optimized functions already available in JavaScript engines.

These optimizations are relatively new to the world of JavaScript runtimes even though there are many examples of dead code in real-world JavaScript on the Web. These optimizations often require significant flow analysis of the code, and in a real world site, spending too much time analyzing code can reduce the responsiveness of the page. The Chakra engine picks the right balance between code quality and analysis time, and only performs a small set of dead code optimizations. We continue to tune this for IE9, and bugs reported via Microsoft Connect are examples of where the optimization could do more. We continue to tune these and other optimizations for the final release.

This kind of dead code elimination is one of many optimizations that Chakra makes to reduce unnecessary work. Over the next few days we’ll post about some of the other techniques Chakra uses to deliver great performance.