[vmkit-commits] [vmkit] r180486 - Optimization in the method to find unreachable code. I am doing some assumptions but it work for Kotlin and Scala compilers. javac does not present this issue.

Peter Senna Tschudin peter.senna at gmail.com
Thu Apr 25 10:17:37 PDT 2013


Author: peter.senna
Date: Thu Apr 25 12:15:38 2013
New Revision: 180486

URL: http://llvm.org/viewvc/llvm-project?rev=180486&view=rev
Log:
Optimization in the method to find unreachable code. I am doing some assumptions but it work for Kotlin and Scala compilers. javac does not present this issue.
(cherry picked from commit 154b540e5bd73c113ce067c957bb0d2da815eee7)

Modified:
    vmkit/trunk/lib/j3/Compiler/JavaJIT.cpp
    vmkit/trunk/lib/j3/Compiler/JavaJITOpcodes.cpp

Modified: vmkit/trunk/lib/j3/Compiler/JavaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/Compiler/JavaJIT.cpp?rev=180486&r1=180485&r2=180486&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/Compiler/JavaJIT.cpp (original)
+++ vmkit/trunk/lib/j3/Compiler/JavaJIT.cpp Thu Apr 25 12:15:38 2013
@@ -1178,9 +1178,6 @@ llvm::Function* JavaJIT::javaCompile() {
   }
 
   reader.cursor = start;
-  findUnreachableCode(reader, codeLen);
-
-  reader.cursor = start;
   compileOpcodes(reader, codeLen);
 
   // This isn't a real requirement, although javac-produced bytcode does

Modified: vmkit/trunk/lib/j3/Compiler/JavaJITOpcodes.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/j3/Compiler/JavaJITOpcodes.cpp?rev=180486&r1=180485&r2=180486&view=diff
==============================================================================
--- vmkit/trunk/lib/j3/Compiler/JavaJITOpcodes.cpp (original)
+++ vmkit/trunk/lib/j3/Compiler/JavaJITOpcodes.cpp Thu Apr 25 12:15:38 2013
@@ -98,13 +98,286 @@ static inline uint32 WCALC(uint32 n, boo
   }
 }
 
+#include <queue>
+
+static uint8 sum [] = {
+		2,
+		3,
+		2,
+		3,
+		3,
+		2,
+		2,
+		2,
+		2,
+		2
+};
+
+static uint8 sum2 [] = {
+		3,
+		3,
+		3,
+		3,
+		3,
+		3,
+		3,
+		5,
+		5,
+		3,
+		2,
+		3,
+		1,
+		1,
+		3,
+		3,
+		1,
+		1
+};
+
+void JavaJIT::findUnreachableCode(Reader& reader, uint32 codeLen) {
+	std::queue<uint32> queue;
+	queue.push(0);
+	opcodeInfos[0].isReachable = true;
+
+	for (int i = 0; i < codeLen; ++i) {
+		if (opcodeInfos[i].isReachable)
+			queue.push(i);
+	}
+
+	uint32 start = reader.cursor;
+	while (queue.size()) {
+		// pick one index from the queue
+		uint32 i_opcode = queue.front();
+		queue.pop();
+		// read the opcode at this position
+		reader.cursor = start + i_opcode;
+		uint8 bytecode = reader.readU1();
+		// if the opcode is a section which has a handle other than the endBlockHandler then we must add the initial instruction of that handler to the queue
+		if (opcodeInfos[i_opcode].handlerPC) {
+			uint16 pc = opcodeInfos[i_opcode].handlerPC;
+			if (pc < codeLen && !opcodeInfos[pc].isReachable) {
+				opcodeInfos[pc].isReachable = true;
+				queue.push(pc);
+			}
+		}
+		//
+		// if the opcode does not involve a branch then mark the next instruction as reachable (DONE)
+		// if the opcode is an unconditional branch then mark the target as reachable (DONE)
+		// if the opcode is a conditional branch then mark the target and the next instruction as reachable (DONE)
+		// if it is a ret instruction then I don't know what to do.
+		// if it is a jsr instruction then mark the target as reachable (DONE)
+		// if it is tableswitch instruction then mark all cases as reachable (DONE)
+		// if it is lookupswitch instruction then mark all cases as reachable (DONE)
+		// wide instruction (DONE)
+		if (bytecode < IFEQ) {
+			uint32 next_index = 1;
+			if (bytecode >= BIPUSH && bytecode <= ALOAD)
+				next_index = sum[bytecode - BIPUSH];
+			else if (bytecode >= ISTORE && bytecode <= ASTORE)
+				next_index = 2;
+			else if (bytecode == IINC)
+				next_index = 3;
+			next_index += i_opcode;
+			if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+				opcodeInfos[next_index].isReachable = true;
+				queue.push(next_index);
+			}
+		}
+		else if (bytecode >= IFEQ && bytecode <= IF_ACMPNE) {
+			uint32 next_index = 3 + i_opcode;
+			if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+				opcodeInfos[next_index].isReachable = true;
+				queue.push(next_index);
+			}
+			uint16 b1 = reader.readU1();
+			uint8 b2 = reader.readU1();
+			sint16 step = (b1 << 8) | b2;
+			next_index = i_opcode + step;
+			if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+				opcodeInfos[next_index].isReachable = true;
+				queue.push(next_index);
+			}
+		}
+		else if (bytecode >= GETSTATIC && bytecode <= MONITOREXIT && bytecode != ATHROW) {
+			uint32 next_index = sum2[bytecode - GETSTATIC] + i_opcode;
+			if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+				opcodeInfos[next_index].isReachable = true;
+				queue.push(next_index);
+			}
+		}
+		else {
+			uint32 x;
+			sint32 defaultIndex,lowIndex, highIndex;
+			uint32 next_index = codeLen;
+			sint16 step;
+			sint32 step32;
+			uint16 b1;
+			uint8 b2,b3,b4;
+			switch (bytecode) {
+				case GOTO:
+					b1 = reader.readU1();
+					b2 = reader.readU1();
+					step = (b1 << 8) | b2;
+					next_index = i_opcode + step;
+					break;
+				case GOTO_W:
+					next_index = reader.readU1();
+					b2 = reader.readU1();
+					b3 = reader.readU1();
+					b4 = reader.readU1();
+					step32 =  (next_index << 24) | (b2 << 16) | (b3 << 8) | b4;
+					next_index = step32 + i_opcode;
+					break;
+				case MULTIANEWARRAY:
+					next_index = i_opcode + 4;
+					break;
+				case IFNULL:
+				case IFNONNULL:
+				case JSR:
+					next_index = i_opcode + 3;
+					if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+						opcodeInfos[next_index].isReachable = true;
+						queue.push(next_index);
+					}
+					b1 = reader.readU1();
+					b2 = reader.readU1();
+					step = (b1 << 8) | b2;
+					next_index = i_opcode + step;
+					break;
+				case JSR_W:
+					next_index = i_opcode + 5;
+					if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+						opcodeInfos[next_index].isReachable = true;
+						queue.push(next_index);
+					}
+					next_index = reader.readU1();
+					b2 = reader.readU1();
+					b3 = reader.readU1();
+					b4 = reader.readU1();
+					step32 =  (next_index << 24) | (b2 << 16) | (b3 << 8) | b4;
+					next_index = step32 + i_opcode;
+					break;
+				case WIDE:
+					if (i_opcode + 1 < codeLen && !opcodeInfos[i_opcode + 1].isReachable) {
+						opcodeInfos[i_opcode + 1].isReachable = true;
+						queue.push(i_opcode + 1);
+					}
+					b2 = reader.readU1();
+					next_index = i_opcode + ((b2 == IINC)?6:4);
+					break;
+				case TABLESWITCH:
+					//break;
+					x = i_opcode & 0x03; // remainder of division by 4
+					reader.cursor = start + 4 - x + i_opcode;
+					// default
+					defaultIndex = reader.readU1();
+					b2 = reader.readU1();
+					b3 = reader.readU1();
+					b4 = reader.readU1();
+					step32 =  (defaultIndex << 24) | (b2 << 16) | (b3 << 8) | b4;
+					defaultIndex = step32 + i_opcode;
+					if (defaultIndex < codeLen && !opcodeInfos[defaultIndex].isReachable) {
+						opcodeInfos[defaultIndex].isReachable = true;
+						queue.push(defaultIndex);
+					}
+					// low
+					lowIndex = reader.readU1();
+					b2 = reader.readU1();
+					b3 = reader.readU1();
+					b4 = reader.readU1();
+					step32 =  (lowIndex << 24) | (b2 << 16) | (b3 << 8) | b4;
+					lowIndex = step32 + i_opcode;
+					// high
+					highIndex = reader.readU1();
+					b2 = reader.readU1();
+					b3 = reader.readU1();
+					b4 = reader.readU1();
+					step32 =  (highIndex << 24) | (b2 << 16) | (b3 << 8) | b4;
+					highIndex = step32 + i_opcode;
+					// all options
+					for (int i = 0 ; i < highIndex - lowIndex + 1 ; i++) {
+						next_index = reader.readU1();
+						b2 = reader.readU1();
+						b3 = reader.readU1();
+						b4 = reader.readU1();
+						step32 =  (next_index << 24) | (b2 << 16) | (b3 << 8) | b4;
+						next_index = step32 + i_opcode;
+						if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+							opcodeInfos[next_index].isReachable = true;
+							queue.push(next_index);
+						}
+					}
+					next_index = codeLen;
+					break;
+				case LOOKUPSWITCH:
+					//break;
+					x = i_opcode & 0x03; // remainder of division by 4
+					reader.cursor = start + 4 - x + i_opcode;
+					// default
+					defaultIndex = reader.readU1();
+					b2 = reader.readU1();
+					b3 = reader.readU1();
+					b4 = reader.readU1();
+					step32 =  (defaultIndex << 24) | (b2 << 16) | (b3 << 8) | b4;
+					defaultIndex = step32 + i_opcode;
+					if (defaultIndex < codeLen && !opcodeInfos[defaultIndex].isReachable) {
+						opcodeInfos[defaultIndex].isReachable = true;
+						queue.push(defaultIndex);
+					}
+					// npairs
+					lowIndex = reader.readU1();
+					b2 = reader.readU1();
+					b3 = reader.readU1();
+					b4 = reader.readU1();
+					step32 =  (lowIndex << 24) | (b2 << 16) | (b3 << 8) | b4;
+					lowIndex = step32 + i_opcode;
+					// all options
+					for (int i = 0 ; i < lowIndex ; i++) {
+						reader.cursor += 4; // skipping match
+						// offset
+						next_index = reader.readU1();
+						b2 = reader.readU1();
+						b3 = reader.readU1();
+						b4 = reader.readU1();
+						step32 =  (next_index << 24) | (b2 << 16) | (b3 << 8) | b4;
+						next_index = step32 + i_opcode;
+						if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+							opcodeInfos[next_index].isReachable = true;
+							queue.push(next_index);
+						}
+					}
+					next_index = codeLen;
+					break;
+				default:
+					break;
+			}
+			if (next_index < codeLen && !opcodeInfos[next_index].isReachable) {
+				opcodeInfos[next_index].isReachable = true;
+				queue.push(next_index);
+			}
+		}
+	} // end while
+}
+
 void JavaJIT::compileOpcodes(Reader& reader, uint32 codeLength) {
   bool wide = false;
   uint32 jsrIndex = 0;
   uint32 start = reader.cursor;
+  // Some compilers like Scala and Kotlin produce unreachable code.
+  // However, it looks as this only occur when exception handlers are presented
+  // I assume this is true, so I only check unreachable code if the method has exception handlers
+  // nbHandlers
+  if (nbHandlers && !opcodeInfos[0].isReachable) {
+	  findUnreachableCode(reader, codeLength);
+	  reader.cursor = start;
+  }
+
   vmkit::ThreadAllocator allocator;
   for(uint32 i = 0; i < codeLength; ++i) {
-    reader.cursor = start + i;
+	if (nbHandlers && !opcodeInfos[i].isReachable && !opcodeInfos[i].handler) {
+		continue;
+	}
+	reader.cursor = start + i;
     uint8 bytecode = reader.readU1();
     
     PRINT_DEBUG(JNJVM_COMPILE, 1, DARK_BLUE, "\t[at %5d] %-5d ", i,





More information about the vmkit-commits mailing list