1959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle/*
2959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Copyright (C) 2014 The Android Open Source Project
3959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *
4959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Licensed under the Apache License, Version 2.0 (the "License");
5959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * you may not use this file except in compliance with the License.
6959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * You may obtain a copy of the License at
7959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *
8959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *      http://www.apache.org/licenses/LICENSE-2.0
9959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle *
10959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * Unless required by applicable law or agreed to in writing, software
11959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * distributed under the License is distributed on an "AS IS" BASIS,
12959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * See the License for the specific language governing permissions and
14959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle * limitations under the License.
15959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle */
16959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
17959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepackage dexfuzz.program.mutators;
18959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
19959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.Log;
20959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.MutationStats;
21959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.program.MInsn;
22959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.program.MTryBlock;
23959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.program.MutatableCode;
24959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport dexfuzz.program.Mutation;
25959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
26959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.List;
27959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyleimport java.util.Random;
28959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
29959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kylepublic class TryBlockShifter extends CodeMutator {
30959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  /**
31959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * Every CodeMutator has an AssociatedMutation, representing the
32959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * mutation that this CodeMutator can perform, to allow separate
33959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   * generateMutation() and applyMutation() phases, allowing serialization.
34959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle   */
35959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public static class AssociatedMutation extends Mutation {
36959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public int tryIdx;
37959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public boolean shiftingTryBlock; // false => shifting handler
38959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public boolean shiftingStart; // false => shifting end (try block only)
39959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public boolean shiftingHandlerCatchall;
40959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public int shiftingHandlerIdx;
41959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public int newShiftedInsnIdx;
42959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
43959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    @Override
44959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public String getString() {
45959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      String result = String.format("%d %s %s %s %d %d",
46959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          tryIdx,
47959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          (shiftingTryBlock ? "T" : "F"),
48959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          (shiftingStart ? "T" : "F"),
49959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          (shiftingHandlerCatchall ? "T" : "F"),
50959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          shiftingHandlerIdx,
51959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          newShiftedInsnIdx
52959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          );
53959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return result;
54959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
55959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
56959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    @Override
57959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    public void parseString(String[] elements) {
58959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      tryIdx = Integer.parseInt(elements[2]);
59959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      shiftingTryBlock = elements[3].equals("T");
60959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      shiftingStart = elements[4].equals("T");
61959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      shiftingHandlerCatchall = elements[5].equals("T");
62959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      shiftingHandlerIdx = Integer.parseInt(elements[6]);
63959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      newShiftedInsnIdx = Integer.parseInt(elements[7]);
64959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
65959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
66959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
67959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // The following two methods are here for the benefit of MutationSerializer,
68959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // so it can create a CodeMutator and get the correct associated Mutation, as it
69959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  // reads in mutations from a dump of mutations.
70959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
71959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public Mutation getNewMutation() {
72959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return new AssociatedMutation();
73959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
74959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
75959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public TryBlockShifter() { }
76959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
77959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  public TryBlockShifter(Random rng, MutationStats stats, List<Mutation> mutations) {
78959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    super(rng, stats, mutations);
79959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    likelihood = 40;
80959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
81959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
82959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
83959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected boolean canMutate(MutatableCode mutatableCode) {
84959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (mutatableCode.triesSize > 0) {
85959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      return true;
86959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
87959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
88959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    Log.debug("Method contains no tries.");
89959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return false;
90959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
91959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
92959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
93959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected Mutation generateMutation(MutatableCode mutatableCode) {
94959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Pick a random try.
95959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    int tryIdx = rng.nextInt(mutatableCode.triesSize);
96959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MTryBlock tryBlock = mutatableCode.mutatableTries.get(tryIdx);
97959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
98959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    boolean shiftingTryBlock = rng.nextBoolean();
99959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    boolean shiftingStart = false;
100959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    boolean shiftingHandlerCatchall = false;
101959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    int shiftingHandlerIdx = -1;
102959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (shiftingTryBlock) {
103959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // We're shifting the boundaries of the try block
104959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // determine if we shift the start or the end.
105959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      shiftingStart = rng.nextBoolean();
106959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else {
107959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // We're shifting the start of a handler of the try block.
108959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      if (tryBlock.handlers.isEmpty()) {
109959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        // No handlers, so we MUST mutate the catchall
110959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        shiftingHandlerCatchall = true;
111959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      } else if (tryBlock.catchAllHandler != null) {
112959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        // There is a catchall handler, so potentially mutate it.
113959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        shiftingHandlerCatchall = rng.nextBoolean();
114959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      }
115959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // If we're not going to shift the catchall handler, then
116959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // pick an explicit handler to shift.
117959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      if (!shiftingHandlerCatchall) {
118959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        shiftingHandlerIdx = rng.nextInt(tryBlock.handlers.size());
119959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      }
120959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
121959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
122959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Get the original instruction wherever we're shifting.
123959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MInsn oldInsn = null;
124959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (shiftingTryBlock && shiftingStart) {
125959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      oldInsn = tryBlock.startInsn;
126959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else if (shiftingTryBlock && !(shiftingStart)) {
127959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      oldInsn = tryBlock.endInsn;
128959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else if (!(shiftingTryBlock) && shiftingHandlerCatchall) {
129959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      oldInsn = tryBlock.catchAllHandler;
130959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else if (!(shiftingTryBlock) && !(shiftingHandlerCatchall)
131959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        && (shiftingHandlerIdx != -1)) {
132959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      oldInsn = tryBlock.handlers.get(shiftingHandlerIdx);
133959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else {
134959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.errorAndQuit("Faulty logic in TryBlockShifter!");
135959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
136959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
137959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Find the index of this instruction.
138959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    int oldInsnIdx = mutatableCode.getInstructionIndex(oldInsn);
139959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
140959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    int newInsnIdx = oldInsnIdx;
141959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
142959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    int delta = 0;
143959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
144959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Keep searching for a new index.
145959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    while (newInsnIdx == oldInsnIdx) {
146959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // Vary by +/- 2 instructions.
147959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      delta = 0;
148959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      while (delta == 0) {
149959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        delta = (rng.nextInt(5) - 2);
150959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      }
151959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
152959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      newInsnIdx = oldInsnIdx + delta;
153959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
154959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      // Check the new index is legal.
155959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      if (newInsnIdx < 0) {
156959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        newInsnIdx = 0;
157959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      } else if (newInsnIdx >= mutatableCode.getInstructionCount()) {
158959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        newInsnIdx = mutatableCode.getInstructionCount() - 1;
159959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      }
160959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
161959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
162959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    AssociatedMutation mutation = new AssociatedMutation();
163959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.setup(this.getClass(), mutatableCode);
164959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.tryIdx = tryIdx;
165959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.shiftingTryBlock = shiftingTryBlock;
166959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.shiftingStart = shiftingStart;
167959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.shiftingHandlerCatchall = shiftingHandlerCatchall;
168959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.shiftingHandlerIdx = shiftingHandlerIdx;
169959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    mutation.newShiftedInsnIdx = newInsnIdx;
170959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    return mutation;
171959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
172959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
173959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  @Override
174959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  protected void applyMutation(Mutation uncastMutation) {
175959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Cast the Mutation to our AssociatedMutation, so we can access its fields.
176959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    AssociatedMutation mutation = (AssociatedMutation) uncastMutation;
177959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MutatableCode mutatableCode = mutation.mutatableCode;
178959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
179959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MTryBlock tryBlock = mutatableCode.mutatableTries.get(mutation.tryIdx);
180959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
181959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    MInsn newInsn =
182959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        mutatableCode.getInstructionAt(mutation.newShiftedInsnIdx);
183959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
184959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    // Find the right mutatable instruction in try block, and point it at the new instruction.
185959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    if (mutation.shiftingTryBlock && mutation.shiftingStart) {
186959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      tryBlock.startInsn = newInsn;
187959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.info("Shifted the start of try block #" + mutation.tryIdx
188959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          + " to be at " + newInsn);
189959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else if (mutation.shiftingTryBlock && !(mutation.shiftingStart)) {
190959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      tryBlock.endInsn = newInsn;
191959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.info("Shifted the end of try block #" + mutation.tryIdx
192959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          + " to be at " + newInsn);
193959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else if (!(mutation.shiftingTryBlock) && mutation.shiftingHandlerCatchall) {
194959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      tryBlock.catchAllHandler = newInsn;
195959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.info("Shifted the catch all handler of try block #" + mutation.tryIdx
196959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          + " to be at " + newInsn);
197959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else if (!(mutation.shiftingTryBlock) && !(mutation.shiftingHandlerCatchall)
198959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle        && (mutation.shiftingHandlerIdx != -1)) {
199959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      tryBlock.handlers.set(mutation.shiftingHandlerIdx, newInsn);
200959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.info("Shifted handler #" + mutation.shiftingHandlerIdx
201959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle          + " of try block #" + mutation.tryIdx + " to be at " + newInsn);
202959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    } else {
203959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle      Log.errorAndQuit("faulty logic in TryBlockShifter");
204959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    }
205959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle
206959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle    stats.incrementStat("Shifted boundary in a try block");
207959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle  }
208959ffdf65f280ee90b7944a8dd610564e7f99e69Stephen Kyle}
209