1 21 22 package org.apache.derby.impl.services.bytecode; 23 import org.apache.derby.iapi.services.classfile.VMOpcode; 24 import org.apache.derby.iapi.services.sanity.SanityManager; 25 26 114 class Conditional { 115 116 125 private static final int BRANCH16LIMIT = 32767; 126 127 128 private final Conditional parent; 129 132 private final int if_pc; 133 134 private Type[] stack; 135 136 141 private int thenGoto_pc; 142 143 150 Conditional(Conditional parent, CodeChunk chunk, short ifOpcode, Type[] entryStack) { 151 this.parent = parent; 152 if_pc = chunk.getPC(); 153 this.stack = entryStack; 154 155 chunk.addInstrU2(ifOpcode, 0); 158 } 159 160 166 Type[] startElse(BCMethod mb, CodeChunk chunk, Type[] thenStack) { 167 168 chunk.addInstrU2(VMOpcode.GOTO, 0); 170 171 fillIn(mb, chunk, if_pc, chunk.getPC()); 174 175 thenGoto_pc = chunk.getPC() - 3; 180 181 Type[] entryStack = stack; 182 stack = thenStack; 183 184 return entryStack; 185 } 186 187 188 195 Conditional end(BCMethod mb, CodeChunk chunk, Type[] elseStack, int stackNumber) { 196 int branch_pc; 197 if (thenGoto_pc == 0) { 198 branch_pc = if_pc; 200 } else { 201 branch_pc = thenGoto_pc; 203 } 204 205 fillIn(mb, chunk, branch_pc, chunk.getPC()); 206 207 if (SanityManager.DEBUG) 208 { 209 if (stackNumber != stack.length) 210 SanityManager.THROWASSERT("ByteCode Conditional then/else stack depths differ then:" 211 + stack.length + " else: " + stackNumber); 212 213 for (int i = 0; i < stackNumber; i++) 214 { 215 if (!stack[i].vmName().equals(elseStack[i].vmName())) 216 SanityManager.THROWASSERT("ByteCode Conditional then/else stack mismatch: then: " 217 + stack[i].vmName() + 218 " else: " + elseStack[i].vmName()); 219 } 220 } 221 222 return parent; 223 } 224 225 239 private void fillIn(BCMethod mb, CodeChunk chunk, 240 int branch_pc, int target_pc) { 241 242 int offset = target_pc - branch_pc; 243 244 if (SanityManager.DEBUG) 248 { 249 if (offset <= 0) 250 SanityManager.THROWASSERT("Conditional branch zero or negative " + offset); 251 } 252 253 short branchOpcode = chunk.getOpcode(branch_pc); 255 256 if (offset <= BRANCH16LIMIT) 258 { 259 CodeChunk mod = chunk.insertCodeSpace(branch_pc, 0); 263 mod.addInstrU2(branchOpcode, offset); 264 return; 265 } 266 267 if (branchOpcode == VMOpcode.GOTO) 268 { 269 270 278 CodeChunk mod = chunk.insertCodeSpace(branch_pc, 2); 281 282 offset += 2; 284 285 mod.addInstrU4(VMOpcode.GOTO_W, offset); 287 288 int startElse_pc = mod.getPC(); 298 299 int branchOffset = startElse_pc - if_pc; 300 301 if (branchOffset <= BRANCH16LIMIT + 2) 302 { 303 308 fillIn(mb, chunk, if_pc, mod.getPC()); 310 return; 311 312 } 313 314 318 mod = chunk.insertCodeSpace(if_pc + 3, 0); 321 322 branchOffset -= 3; 326 327 mod.addInstrU4(VMOpcode.GOTO_W, branchOffset); 328 return; 329 330 } 331 else 332 { 333 if ((target_pc + 5) >= VMOpcode.MAX_CODE_LENGTH) 337 { 338 mb.cb.addLimitExceeded(mb, 339 "branch_target", VMOpcode.MAX_CODE_LENGTH, target_pc + 5); 340 } 343 344 363 switch (branchOpcode) 365 { 366 case VMOpcode.IFNONNULL: 367 branchOpcode = VMOpcode.IFNULL; 368 break; 369 case VMOpcode.IFEQ: 370 branchOpcode = VMOpcode.IFNE; 371 break; 372 default: 373 if (SanityManager.DEBUG) 374 SanityManager.THROWASSERT("Conditional does not handle opcode " + branchOpcode); 375 376 } 377 378 CodeChunk mod = chunk.insertCodeSpace(branch_pc, 5); 381 382 mod.addInstrU2(branchOpcode, 8); 384 385 offset += 2; 392 393 mod.addInstrU4(VMOpcode.GOTO_W, offset); 394 395 return; 396 } 397 } 398 399 400 } 401 | Popular Tags |