001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.compilers.opt.ssa; 014 015 import static org.jikesrvm.compilers.opt.ir.Operators.FENCE; 016 import static org.jikesrvm.compilers.opt.ir.Operators.READ_CEILING; 017 import static org.jikesrvm.compilers.opt.ir.Operators.WRITE_FLOOR; 018 019 import java.util.Enumeration; 020 021 import org.jikesrvm.classloader.TypeReference; 022 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 023 import org.jikesrvm.compilers.opt.dfsolver.DF_Equation; 024 import org.jikesrvm.compilers.opt.dfsolver.DF_LatticeCell; 025 import org.jikesrvm.compilers.opt.dfsolver.DF_Operator; 026 import org.jikesrvm.compilers.opt.dfsolver.DF_System; 027 import org.jikesrvm.compilers.opt.ir.ALoad; 028 import org.jikesrvm.compilers.opt.ir.AStore; 029 import org.jikesrvm.compilers.opt.ir.Attempt; 030 import org.jikesrvm.compilers.opt.ir.BasicBlock; 031 import org.jikesrvm.compilers.opt.ir.CacheOp; 032 import org.jikesrvm.compilers.opt.ir.Call; 033 import org.jikesrvm.compilers.opt.ir.GetField; 034 import org.jikesrvm.compilers.opt.ir.GetStatic; 035 import org.jikesrvm.compilers.opt.ir.IR; 036 import org.jikesrvm.compilers.opt.ir.IRTools; 037 import org.jikesrvm.compilers.opt.ir.Instruction; 038 import org.jikesrvm.compilers.opt.ir.MonitorOp; 039 import org.jikesrvm.compilers.opt.ir.New; 040 import org.jikesrvm.compilers.opt.ir.NewArray; 041 import org.jikesrvm.compilers.opt.ir.Phi; 042 import org.jikesrvm.compilers.opt.ir.Prepare; 043 import org.jikesrvm.compilers.opt.ir.PutField; 044 import org.jikesrvm.compilers.opt.ir.PutStatic; 045 import org.jikesrvm.compilers.opt.ir.operand.HeapOperand; 046 import org.jikesrvm.compilers.opt.ir.operand.Operand; 047 import org.jikesrvm.compilers.opt.ssa.IndexPropagation.ArrayCell; 048 import org.jikesrvm.compilers.opt.ssa.IndexPropagation.ObjectCell; 049 050 /** 051 * Represents a set of dataflow equations used to solve the 052 * index propagation problem. 053 */ 054 class IndexPropagationSystem extends DF_System { 055 056 /** 057 * The governing IR. 058 */ 059 private final IR ir; 060 /** 061 * Heap Array SSA lookaside information for the IR. 062 */ 063 private final SSADictionary ssa; 064 /** 065 * Results of global value numbering 066 */ 067 private final GlobalValueNumberState valueNumbers; 068 /** 069 * object representing the MEET operator 070 */ 071 private static final MeetOperator MEET = new MeetOperator(); 072 073 /** 074 * Set up the system of dataflow equations. 075 * @param _ir the IR 076 */ 077 public IndexPropagationSystem(IR _ir) { 078 ir = _ir; 079 ssa = ir.HIRInfo.dictionary; 080 valueNumbers = ir.HIRInfo.valueNumbers; 081 setupEquations(); 082 } 083 084 /** 085 * Create an DF_LatticeCell corresponding to an HeapVariable 086 * @param o the heap variable 087 * @return a new lattice cell corresponding to this heap variable 088 */ 089 @Override 090 protected DF_LatticeCell makeCell(Object o) { 091 if (!(o instanceof HeapVariable)) { 092 throw new OptimizingCompilerException("IndexPropagation:makeCell"); 093 } 094 DF_LatticeCell result = null; 095 Object heapType = ((HeapVariable<?>) o).getHeapType(); 096 if (heapType instanceof TypeReference) { 097 result = new ArrayCell((HeapVariable<?>) o); 098 } else { 099 result = new ObjectCell((HeapVariable<?>) o); 100 } 101 return result; 102 } 103 104 /** 105 * Initialize the lattice variables. 106 */ 107 @Override 108 protected void initializeLatticeCells() { 109 // initially all lattice cells are set to TOP 110 // set the lattice cells that are exposed on entry to BOTTOM 111 for (DF_LatticeCell c : cells.values()) { 112 if (c instanceof ObjectCell) { 113 ObjectCell c1 = (ObjectCell) c; 114 HeapVariable<?> key = c1.getKey(); 115 if (key.isExposedOnEntry()) { 116 c1.setBOTTOM(); 117 } 118 } else { 119 ArrayCell c1 = (ArrayCell) c; 120 HeapVariable<?> key = c1.getKey(); 121 if (key.isExposedOnEntry()) { 122 c1.setBOTTOM(); 123 } 124 } 125 } 126 } 127 128 /** 129 * Initialize the work list for the dataflow equation system. 130 */ 131 @Override 132 protected void initializeWorkList() { 133 // add all equations to the work list that contain a non-TOP 134 // variable 135 for (Enumeration<DF_Equation> e = getEquations(); e.hasMoreElements();) { 136 DF_Equation eq = e.nextElement(); 137 for (DF_LatticeCell operand : eq.getOperands()) { 138 if (operand instanceof ObjectCell) { 139 if (!((ObjectCell) operand).isTOP()) { 140 addToWorkList(eq); 141 break; 142 } 143 } else { 144 if (!((ArrayCell) operand).isTOP()) { 145 addToWorkList(eq); 146 break; 147 } 148 } 149 } 150 } 151 } 152 153 /** 154 * Walk through the IR and add dataflow equations for each instruction 155 * that affects the values of Array SSA variables. 156 */ 157 void setupEquations() { 158 for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) { 159 BasicBlock bb = e.nextElement(); 160 for (SSADictionary.AllInstructionEnumeration e2 = ssa.getAllInstructions(bb); e2.hasMoreElements();) { 161 Instruction s = e2.nextElement(); 162 // only consider instructions which use/def Array SSA variables 163 if (!ssa.usesHeapVariable(s) && !ssa.defsHeapVariable(s)) { 164 continue; 165 } 166 if (s.isDynamicLinkingPoint()) { 167 processCall(s); 168 } else if (GetStatic.conforms(s)) { 169 processLoad(s); 170 } else if (GetField.conforms(s)) { 171 processLoad(s); 172 } else if (PutStatic.conforms(s)) { 173 processStore(s); 174 } else if (PutField.conforms(s)) { 175 processStore(s); 176 } else if (New.conforms(s)) { 177 processNew(s); 178 } else if (NewArray.conforms(s)) { 179 processNew(s); 180 } else if (ALoad.conforms(s)) { 181 processALoad(s); 182 } else if (AStore.conforms(s)) { 183 processAStore(s); 184 } else if (Call.conforms(s)) { 185 processCall(s); 186 } else if (MonitorOp.conforms(s)) { 187 processCall(s); 188 } else if (Prepare.conforms(s)) { 189 processCall(s); 190 } else if (Attempt.conforms(s)) { 191 processCall(s); 192 } else if (CacheOp.conforms(s)) { 193 processCall(s); 194 } else if (Phi.conforms(s)) { 195 processPhi(s); 196 } else if (s.operator == READ_CEILING) { 197 processCall(s); 198 } else if (s.operator == WRITE_FLOOR) { 199 processCall(s); 200 } else if (s.operator == FENCE) { 201 processCall(s); 202 } 203 } 204 } 205 } 206 207 /** 208 * Update the set of dataflow equations to account for the actions 209 * of a Load instruction 210 * 211 * <p> The load is of the form x = A[k]. let A_1 be the array SSA 212 * variable before the load, and A_2 the array SSA variable after 213 * the store. Then we add the dataflow equation 214 * L(A_2) = updateUse(L(A_1), VALNUM(k)) 215 * 216 * <p> Intuitively, this equation represents the fact that A[k] is available 217 * after the store 218 * 219 * @param s the Load instruction 220 */ 221 void processLoad(Instruction s) { 222 HeapOperand<?>[] A1 = ssa.getHeapUses(s); 223 HeapOperand<?>[] A2 = ssa.getHeapDefs(s); 224 if ((A1.length != 1) || (A2.length != 1)) { 225 throw new OptimizingCompilerException( 226 "IndexPropagation.processLoad: load instruction defs or uses multiple heap variables?"); 227 } 228 int valueNumber = -1; 229 if (GetField.conforms(s)) { 230 Object address = GetField.getRef(s); 231 valueNumber = valueNumbers.getValueNumber(address); 232 } else { // GetStatic.conforms(s) 233 valueNumber = 0; 234 } 235 if (IRTools.mayBeVolatileFieldLoad(s) || ir.options.READS_KILL) { 236 // to obey JMM strictly, we must treat every load as a 237 // DEF 238 addUpdateObjectDefEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), valueNumber); 239 } else { 240 // otherwise, don't have to treat every load as a DEF 241 addUpdateObjectUseEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), valueNumber); 242 } 243 } 244 245 /** 246 * Update the set of dataflow equations to account for the actions 247 * of a Store instruction. 248 * 249 * <p> The store is of the form A[k] = val. let A_1 be the array SSA 250 * variable before the store, and A_2 the array SSA variable after 251 * the store. Then we add the dataflow equation 252 * L(A_2) = updateDef(L(A_1), VALNUM(k)) 253 * 254 * <p> Intuitively, this equation represents the fact that A[k] is available 255 * after the store 256 * 257 * @param s the Store instruction 258 */ 259 void processStore(Instruction s) { 260 HeapOperand<?>[] A1 = ssa.getHeapUses(s); 261 HeapOperand<?>[] A2 = ssa.getHeapDefs(s); 262 if ((A1.length != 1) || (A2.length != 1)) { 263 throw new OptimizingCompilerException( 264 "IndexPropagation.processStore: store instruction defs or uses multiple heap variables?"); 265 } 266 int valueNumber = -1; 267 if (PutField.conforms(s)) { 268 Object address = PutField.getRef(s); 269 valueNumber = valueNumbers.getValueNumber(address); 270 } else { // PutStatic.conforms(s) 271 valueNumber = 0; 272 } 273 addUpdateObjectDefEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), valueNumber); 274 } 275 276 /** 277 * Update the set of dataflow equations to account for the actions 278 * of ALoad instruction s 279 * 280 * <p> The load is of the form x = A[k]. let A_1 be the array SSA 281 * variable before the load, and A_2 the array SSA variable after 282 * the load. Then we add the dataflow equation 283 * L(A_2) = updateUse(L(A_1), VALNUM(k)) 284 * 285 * <p> Intuitively, this equation represents the fact that A[k] is available 286 * after the store 287 * 288 * @param s the Aload instruction 289 */ 290 void processALoad(Instruction s) { 291 HeapOperand<?>[] A1 = ssa.getHeapUses(s); 292 HeapOperand<?>[] A2 = ssa.getHeapDefs(s); 293 if ((A1.length != 1) || (A2.length != 1)) { 294 throw new OptimizingCompilerException( 295 "IndexPropagation.processALoad: aload instruction defs or uses multiple heap variables?"); 296 } 297 Operand array = ALoad.getArray(s); 298 Operand index = ALoad.getIndex(s); 299 if (IRTools.mayBeVolatileFieldLoad(s) || ir.options.READS_KILL) { 300 // to obey JMM strictly, we must treat every load as a 301 // DEF 302 addUpdateArrayDefEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), array, index); 303 } else { 304 // otherwise, don't have to treat every load as a DEF 305 addUpdateArrayUseEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), array, index); 306 } 307 } 308 309 /** 310 * Update the set of dataflow equations to account for the actions 311 * of AStore instruction s 312 * 313 * <p> The store is of the form A[k] = val. let A_1 be the array SSA 314 * variable before the store, and A_2 the array SSA variable after 315 * the store. Then we add the dataflow equation 316 * L(A_2) = update(L(A_1), VALNUM(k)) 317 * 318 * <p> Intuitively, this equation represents the fact that A[k] is available 319 * after the store 320 * 321 * @param s the Astore instruction 322 */ 323 void processAStore(Instruction s) { 324 HeapOperand<?>[] A1 = ssa.getHeapUses(s); 325 HeapOperand<?>[] A2 = ssa.getHeapDefs(s); 326 if ((A1.length != 1) || (A2.length != 1)) { 327 throw new OptimizingCompilerException( 328 "IndexPropagation.processAStore: astore instruction defs or uses multiple heap variables?"); 329 } 330 Operand array = AStore.getArray(s); 331 Operand index = AStore.getIndex(s); 332 addUpdateArrayDefEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), array, index); 333 } 334 335 /** 336 * Update the set of dataflow equations to account for the actions 337 * of allocation instruction s 338 * 339 * @param s the New instruction 340 */ 341 void processNew(Instruction s) { 342 /** Assume nothing is a available after a new. So, set 343 * each lattice cell defined by the NEW as BOTTOM. 344 * TODO: add logic that understands that after a 345 * NEW, all fields have their default values. 346 */ 347 for (HeapOperand<?> def : ssa.getHeapDefs(s)) { 348 DF_LatticeCell c = findOrCreateCell(def.getHeapVariable()); 349 if (c instanceof ObjectCell) { 350 ((ObjectCell) c).setBOTTOM(); 351 } else { 352 ((ArrayCell) c).setBOTTOM(); 353 } 354 } 355 } 356 357 /** 358 * Update the set of dataflow equations to account for the actions 359 * of CALL instruction. 360 * 361 * @param s the Call instruction 362 */ 363 void processCall(Instruction s) { 364 365 /** set all lattice cells def'ed by the call to bottom */ 366 for (HeapOperand<?> operand : ssa.getHeapDefs(s)) { 367 DF_LatticeCell c = findOrCreateCell(operand.getHeapVariable()); 368 if (c instanceof ObjectCell) { 369 ((ObjectCell) c).setBOTTOM(); 370 } else { 371 ((ArrayCell) c).setBOTTOM(); 372 } 373 } 374 } 375 376 /** 377 * Update the set of dataflow equations to account for the actions 378 * of Phi instruction. 379 * 380 * <p> The instruction has the form A1 = PHI (A2, A3, A4); 381 * We add the dataflow equation 382 * L(A1) = MEET(L(A2), L(A3), L(A4)) 383 * 384 * @param s the Phi instruction 385 */ 386 void processPhi(Instruction s) { 387 Operand result = Phi.getResult(s); 388 if (!(result instanceof HeapOperand)) { 389 return; 390 } 391 HeapVariable<?> lhs = ((HeapOperand<?>) result).value; 392 DF_LatticeCell A1 = findOrCreateCell(lhs); 393 DF_LatticeCell[] rhs = new DF_LatticeCell[Phi.getNumberOfValues(s)]; 394 for (int i = 0; i < rhs.length; i++) { 395 HeapOperand<?> op = (HeapOperand<?>) Phi.getValue(s, i); 396 rhs[i] = findOrCreateCell(op.value); 397 } 398 newEquation(A1, MEET, rhs); 399 } 400 401 /** 402 * Add an equation to the system of the form 403 * L(A1) = updateDef(L(A2), VALNUM(address)) 404 * 405 * @param A1 variable in the equation 406 * @param A2 variable in the equation 407 * @param valueNumber value number of the address 408 */ 409 void addUpdateObjectDefEquation(HeapVariable<?> A1, HeapVariable<?> A2, int valueNumber) { 410 DF_LatticeCell cell1 = findOrCreateCell(A1); 411 DF_LatticeCell cell2 = findOrCreateCell(A2); 412 UpdateDefObjectOperator op = new UpdateDefObjectOperator(valueNumber); 413 newEquation(cell1, op, cell2); 414 } 415 416 /** 417 * Add an equation to the system of the form 418 * <pre> 419 * L(A1) = updateUse(L(A2), VALNUM(address)) 420 * </pre> 421 * 422 * @param A1 variable in the equation 423 * @param A2 variable in the equation 424 * @param valueNumber value number of address 425 */ 426 void addUpdateObjectUseEquation(HeapVariable<?> A1, HeapVariable<?> A2, int valueNumber) { 427 DF_LatticeCell cell1 = findOrCreateCell(A1); 428 DF_LatticeCell cell2 = findOrCreateCell(A2); 429 UpdateUseObjectOperator op = new UpdateUseObjectOperator(valueNumber); 430 newEquation(cell1, op, cell2); 431 } 432 433 /** 434 * Add an equation to the system of the form 435 * <pre> 436 * L(A1) = updateDef(L(A2), <VALNUM(array),VALNUM(index)>) 437 * </pre> 438 * 439 * @param A1 variable in the equation 440 * @param A2 variable in the equation 441 * @param array variable in the equation 442 * @param index variable in the equation 443 */ 444 void addUpdateArrayDefEquation(HeapVariable<?> A1, HeapVariable<?> A2, Object array, Object index) { 445 DF_LatticeCell cell1 = findOrCreateCell(A1); 446 DF_LatticeCell cell2 = findOrCreateCell(A2); 447 int arrayNumber = valueNumbers.getValueNumber(array); 448 int indexNumber = valueNumbers.getValueNumber(index); 449 UpdateDefArrayOperator op = new UpdateDefArrayOperator(arrayNumber, indexNumber); 450 newEquation(cell1, op, cell2); 451 } 452 453 /** 454 * Add an equation to the system of the form 455 * <pre> 456 * L(A1) = updateUse(L(A2), <VALNUM(array),VALNUM(index)>) 457 * </pre> 458 * 459 * @param A1 variable in the equation 460 * @param A2 variable in the equation 461 * @param array variable in the equation 462 * @param index variable in the equation 463 */ 464 void addUpdateArrayUseEquation(HeapVariable<?> A1, HeapVariable<?> A2, Object array, Object index) { 465 DF_LatticeCell cell1 = findOrCreateCell(A1); 466 DF_LatticeCell cell2 = findOrCreateCell(A2); 467 int arrayNumber = valueNumbers.getValueNumber(array); 468 int indexNumber = valueNumbers.getValueNumber(index); 469 UpdateUseArrayOperator op = new UpdateUseArrayOperator(arrayNumber, indexNumber); 470 newEquation(cell1, op, cell2); 471 } 472 473 /** 474 * Represents a MEET function (intersection) over Cells. 475 */ 476 static class MeetOperator extends DF_Operator { 477 478 /** 479 * @return "MEET" 480 */ 481 @Override 482 public String toString() { return "MEET"; } 483 484 /** 485 * Evaluate a dataflow equation with the MEET operator 486 * @param operands the operands of the dataflow equation 487 * @return true iff the value of the lhs changes 488 */ 489 @Override 490 public boolean evaluate(DF_LatticeCell[] operands) { 491 DF_LatticeCell lhs = operands[0]; 492 if (lhs instanceof ObjectCell) { 493 return evaluateObjectMeet(operands); 494 } else { 495 return evaluateArrayMeet(operands); 496 } 497 } 498 499 /** 500 * Evaluate a dataflow equation with the MEET operator 501 * for lattice cells representing field heap variables. 502 * @param operands the operands of the dataflow equation 503 * @return true iff the value of the lhs changes 504 */ 505 boolean evaluateObjectMeet(DF_LatticeCell[] operands) { 506 ObjectCell lhs = (ObjectCell) operands[0]; 507 508 // short-circuit if lhs is already bottom 509 if (lhs.isBOTTOM()) { 510 return false; 511 } 512 513 // short-circuit if any rhs is bottom 514 for (int j = 1; j < operands.length; j++) { 515 ObjectCell r = (ObjectCell) operands[j]; 516 if (r.isBOTTOM()) { 517 // from the previous short-circuit, we know lhs was not already bottom, so ... 518 lhs.setBOTTOM(); 519 return true; 520 } 521 } 522 523 boolean lhsWasTOP = lhs.isTOP(); 524 int[] oldNumbers = null; 525 526 if (!lhsWasTOP) oldNumbers = lhs.copyValueNumbers(); 527 528 lhs.clear(); 529 // perform the intersections 530 if (operands.length > 1) { 531 int firstNonTopRHS = -1; 532 // find the first RHS lattice cell that is not TOP 533 for (int j = 1; j < operands.length; j++) { 534 ObjectCell r = (ObjectCell) operands[j]; 535 if (!r.isTOP()) { 536 firstNonTopRHS = j; 537 break; 538 } 539 } 540 // if we did not find ANY non-top cell, then simply set 541 // lhs to top and return 542 if (firstNonTopRHS == -1) { 543 lhs.setTOP(true); 544 return false; 545 } 546 // if we get here, we found a non-top cell. Start merging 547 // here 548 int[] rhsNumbers = ((ObjectCell) operands[firstNonTopRHS]).copyValueNumbers(); 549 550 if (rhsNumbers != null) { 551 for (int v : rhsNumbers) { 552 lhs.add(v); 553 for (int j = firstNonTopRHS + 1; j < operands.length; j++) { 554 ObjectCell r = (ObjectCell) operands[j]; 555 if (!r.contains(v)) { 556 lhs.remove(v); 557 break; 558 } 559 } 560 } 561 } 562 } 563 // check if anything has changed 564 if (lhsWasTOP) return true; 565 int[] newNumbers = lhs.copyValueNumbers(); 566 567 return ObjectCell.setsDiffer(oldNumbers, newNumbers); 568 } 569 570 /** 571 * Evaluate a dataflow equation with the MEET operator 572 * for lattice cells representing array heap variables. 573 * @param operands the operands of the dataflow equation 574 * @return true iff the value of the lhs changes 575 */ 576 boolean evaluateArrayMeet(DF_LatticeCell[] operands) { 577 ArrayCell lhs = (ArrayCell) operands[0]; 578 579 // short-circuit if lhs is already bottom 580 if (lhs.isBOTTOM()) { 581 return false; 582 } 583 584 // short-circuit if any rhs is bottom 585 for (int j = 1; j < operands.length; j++) { 586 ArrayCell r = (ArrayCell) operands[j]; 587 if (r.isBOTTOM()) { 588 // from the previous short-circuit, we know lhs was not already bottom, so ... 589 lhs.setBOTTOM(); 590 return true; 591 } 592 } 593 594 boolean lhsWasTOP = lhs.isTOP(); 595 ValueNumberPair[] oldNumbers = null; 596 if (!lhsWasTOP) oldNumbers = lhs.copyValueNumbers(); 597 598 lhs.clear(); 599 // perform the intersections 600 if (operands.length > 1) { 601 int firstNonTopRHS = -1; 602 // find the first RHS lattice cell that is not TOP 603 for (int j = 1; j < operands.length; j++) { 604 ArrayCell r = (ArrayCell) operands[j]; 605 if (!r.isTOP()) { 606 firstNonTopRHS = j; 607 break; 608 } 609 } 610 // if we did not find ANY non-top cell, then simply set 611 // lhs to top and return 612 if (firstNonTopRHS == -1) { 613 lhs.setTOP(true); 614 return false; 615 } 616 // if we get here, we found a non-top cell. Start merging 617 // here 618 ValueNumberPair[] rhsNumbers = ((ArrayCell) operands[firstNonTopRHS]).copyValueNumbers(); 619 if (rhsNumbers != null) { 620 for (ValueNumberPair pair : rhsNumbers) { 621 int v1 = pair.v1; 622 int v2 = pair.v2; 623 lhs.add(v1, v2); 624 for (int j = firstNonTopRHS + 1; j < operands.length; j++) { 625 ArrayCell r = (ArrayCell) operands[j]; 626 if (!r.contains(v1, v2)) { 627 lhs.remove(v1, v2); 628 break; 629 } 630 } 631 } 632 } 633 } 634 // check if anything has changed 635 if (lhsWasTOP) return true; 636 ValueNumberPair[] newNumbers = lhs.copyValueNumbers(); 637 638 return ArrayCell.setsDiffer(oldNumbers, newNumbers); 639 } 640 } 641 642 /** 643 * Represents an UPDATE_DEF function over two ObjectCells. 644 * <p> Given a value number v, this function updates a heap variable 645 * lattice cell to indicate that element at address v is 646 * available, but kills any available indices that are not DD from v 647 */ 648 class UpdateDefObjectOperator extends DF_Operator { 649 /** 650 * The value number used in the dataflow equation. 651 */ 652 private final int valueNumber; 653 654 /** 655 * @return a String representation 656 */ 657 @Override 658 public String toString() { return "UPDATE-DEF<" + valueNumber + ">"; } 659 660 /** 661 * Create an operator with a given value number 662 * @param valueNumber 663 */ 664 UpdateDefObjectOperator(int valueNumber) { 665 this.valueNumber = valueNumber; 666 } 667 668 /** 669 * Evaluate the dataflow equation with this operator. 670 * @param operands operands in the dataflow equation 671 * @return true iff the lhs changes from this evaluation 672 */ 673 @Override 674 public boolean evaluate(DF_LatticeCell[] operands) { 675 ObjectCell lhs = (ObjectCell) operands[0]; 676 677 if (lhs.isBOTTOM()) { 678 return false; 679 } 680 681 ObjectCell rhs = (ObjectCell) operands[1]; 682 boolean lhsWasTOP = lhs.isTOP(); 683 int[] oldNumbers = null; 684 if (!lhsWasTOP) oldNumbers = lhs.copyValueNumbers(); 685 lhs.clear(); 686 if (rhs.isTOP()) { 687 throw new OptimizingCompilerException("Unexpected lattice operation"); 688 } 689 int[] numbers = rhs.copyValueNumbers(); 690 // add all rhs numbers that are DD from valueNumber 691 if (numbers != null) { 692 for (int number : numbers) { 693 if (valueNumbers.DD(number, valueNumber)) { 694 lhs.add(number); 695 } 696 } 697 } 698 // add value number generated by this update 699 lhs.add(valueNumber); 700 // check if anything has changed 701 if (lhsWasTOP) return true; 702 int[] newNumbers = lhs.copyValueNumbers(); 703 704 return ObjectCell.setsDiffer(oldNumbers, newNumbers); 705 } 706 } 707 708 /** 709 * Represents an UPDATE_USE function over two ObjectCells. 710 * 711 * <p> Given a value number v, this function updates a heap variable 712 * lattice cell to indicate that element at address v is 713 * available, and doesn't kill any available indices 714 */ 715 static class UpdateUseObjectOperator extends DF_Operator { 716 /** 717 * The value number used in the dataflow equation. 718 */ 719 private final int valueNumber; 720 721 /** 722 * @return "UPDATE-USE" 723 */ 724 @Override 725 public String toString() { return "UPDATE-USE<" + valueNumber + ">"; } 726 727 /** 728 * Create an operator with a given value number 729 * @param valueNumber 730 */ 731 UpdateUseObjectOperator(int valueNumber) { 732 this.valueNumber = valueNumber; 733 } 734 735 /** 736 * Evaluate the dataflow equation with this operator. 737 * @param operands operands in the dataflow equation 738 * @return true iff the lhs changes from this evaluation 739 */ 740 @Override 741 public boolean evaluate(DF_LatticeCell[] operands) { 742 ObjectCell lhs = (ObjectCell) operands[0]; 743 744 if (lhs.isBOTTOM()) { 745 return false; 746 } 747 748 ObjectCell rhs = (ObjectCell) operands[1]; 749 int[] oldNumbers = null; 750 boolean lhsWasTOP = lhs.isTOP(); 751 if (!lhsWasTOP) oldNumbers = lhs.copyValueNumbers(); 752 lhs.clear(); 753 if (rhs.isTOP()) { 754 throw new OptimizingCompilerException("Unexpected lattice operation"); 755 } 756 int[] numbers = rhs.copyValueNumbers(); 757 // add all rhs numbers 758 if (numbers != null) { 759 for (int number : numbers) { 760 lhs.add(number); 761 } 762 } 763 // add value number generated by this update 764 lhs.add(valueNumber); 765 // check if anything has changed 766 if (lhsWasTOP) return true; 767 int[] newNumbers = lhs.copyValueNumbers(); 768 769 return ObjectCell.setsDiffer(oldNumbers, newNumbers); 770 } 771 } 772 773 /** 774 * Represents an UPDATE_DEF function over two ArrayCells. 775 * Given two value numbers v1, v2, this function updates a heap variable 776 * lattice cell to indicate that element for array v1 at address v2 is 777 * available, but kills any available indices that are not DD from <v1,v2> 778 */ 779 class UpdateDefArrayOperator extends DF_Operator { 780 /** 781 * The value number pair used in the dataflow equation. 782 */ 783 private final ValueNumberPair v; 784 785 /** 786 * @return "UPDATE-DEF" 787 */ 788 @Override 789 public String toString() { return "UPDATE-DEF<" + v + ">"; } 790 791 /** 792 * Create an operator with a given value number pair 793 * @param v1 first value number in the pari 794 * @param v2 first value number in the pari 795 */ 796 UpdateDefArrayOperator(int v1, int v2) { 797 v = new ValueNumberPair(v1, v2); 798 } 799 800 /** 801 * Evaluate the dataflow equation with this operator. 802 * @param operands operands in the dataflow equation 803 * @return true iff the lhs changes from this evaluation 804 */ 805 @Override 806 public boolean evaluate(DF_LatticeCell[] operands) { 807 ArrayCell lhs = (ArrayCell) operands[0]; 808 809 if (lhs.isBOTTOM()) { 810 return false; 811 } 812 ArrayCell rhs = (ArrayCell) operands[1]; 813 ValueNumberPair[] oldNumbers = null; 814 boolean lhsWasTOP = lhs.isTOP(); 815 if (!lhsWasTOP) oldNumbers = lhs.copyValueNumbers(); 816 lhs.clear(); 817 if (rhs.isTOP()) { 818 throw new OptimizingCompilerException("Unexpected lattice operation"); 819 } 820 ValueNumberPair[] numbers = rhs.copyValueNumbers(); 821 // add all rhs pairs that are DD from either v.v1 or v.v2 822 if (numbers != null) { 823 for (ValueNumberPair number : numbers) { 824 if (valueNumbers.DD(number.v1, v.v1)) { 825 lhs.add(number.v1, number.v2); 826 } else if (valueNumbers.DD(number.v2, v.v2)) { 827 lhs.add(number.v1, number.v2); 828 } 829 } 830 } 831 // add the value number pair generated by this update 832 lhs.add(v.v1, v.v2); 833 // check if anything has changed 834 if (lhsWasTOP) { 835 return true; 836 } 837 ValueNumberPair[] newNumbers = lhs.copyValueNumbers(); 838 839 return ArrayCell.setsDiffer(oldNumbers, newNumbers); 840 } 841 } 842 843 /** 844 * Represents an UPDATE_USE function over two ArrayCells. 845 * 846 * <p> Given two value numbers v1, v2, this function updates a heap variable 847 * lattice cell to indicate that element at array v1 index v2 is 848 * available, and doesn't kill any available indices 849 */ 850 static class UpdateUseArrayOperator extends DF_Operator { 851 /** 852 * The value number pair used in the dataflow equation. 853 */ 854 private final ValueNumberPair v; 855 856 /** 857 * @return "UPDATE-USE" 858 */ 859 @Override 860 public String toString() { return "UPDATE-USE<" + v + ">"; } 861 862 /** 863 * Create an operator with a given value number pair 864 * @param v1 first value number in the pair 865 * @param v2 second value number in the pair 866 */ 867 UpdateUseArrayOperator(int v1, int v2) { 868 v = new ValueNumberPair(v1, v2); 869 } 870 871 /** 872 * Evaluate the dataflow equation with this operator. 873 * @param operands operands in the dataflow equation 874 * @return true iff the lhs changes from this evaluation 875 */ 876 @Override 877 public boolean evaluate(DF_LatticeCell[] operands) { 878 ArrayCell lhs = (ArrayCell) operands[0]; 879 880 if (lhs.isBOTTOM()) { 881 return false; 882 } 883 884 ArrayCell rhs = (ArrayCell) operands[1]; 885 ValueNumberPair[] oldNumbers = null; 886 boolean lhsWasTOP = lhs.isTOP(); 887 if (!lhsWasTOP) oldNumbers = lhs.copyValueNumbers(); 888 lhs.clear(); 889 if (rhs.isTOP()) { 890 throw new OptimizingCompilerException("Unexpected lattice operation"); 891 } 892 ValueNumberPair[] numbers = rhs.copyValueNumbers(); 893 // add all rhs numbers 894 if (numbers != null) { 895 for (ValueNumberPair number : numbers) { 896 lhs.add(number.v1, number.v2); 897 } 898 } 899 // add value number generated by this update 900 lhs.add(v.v1, v.v2); 901 // check if anything has changed 902 if (lhsWasTOP) { 903 return true; 904 } 905 ValueNumberPair[] newNumbers = lhs.copyValueNumbers(); 906 907 return ArrayCell.setsDiffer(oldNumbers, newNumbers); 908 } 909 } 910 }