Package jadx.core.dex.visitors.regions

Source Code of jadx.core.dex.visitors.regions.RegionMakerVisitor

package jadx.core.dex.visitors.regions;

import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.Region;
import jadx.core.dex.regions.SynchronizedRegion;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.exceptions.JadxException;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Pack blocks into regions for code generation
*/
public class RegionMakerVisitor extends AbstractVisitor {
  private static final Logger LOG = LoggerFactory.getLogger(RegionMakerVisitor.class);

  @Override
  public void visit(MethodNode mth) throws JadxException {
    if (mth.isNoCode()) {
      return;
    }
    RegionMaker rm = new RegionMaker(mth);
    RegionStack state = new RegionStack(mth);

    // fill region structure
    mth.setRegion(rm.makeRegion(mth.getEnterBlock(), state));

    if (!mth.isNoExceptionHandlers()) {
      rm.processTryCatchBlocks(mth);
    }

    postProcessRegions(mth);
  }

  private static void postProcessRegions(MethodNode mth) {
    // make try-catch regions
    ProcessTryCatchRegions.process(mth);

    // merge conditions in loops
    if (mth.getLoopsCount() != 0) {
      DepthRegionTraversal.traverseAll(mth, new AbstractRegionVisitor() {
        @Override
        public void enterRegion(MethodNode mth, IRegion region) {
          if (region instanceof LoopRegion) {
            LoopRegion loop = (LoopRegion) region;
            loop.mergePreCondition();
          }
        }
      });
    }

    CleanRegions.process(mth);

    if (mth.getAccessFlags().isSynchronized()) {
      removeSynchronized(mth);
    }
  }

  private static void removeSynchronized(MethodNode mth) {
    Region startRegion = mth.getRegion();
    List<IContainer> subBlocks = startRegion.getSubBlocks();
    if (!subBlocks.isEmpty() && subBlocks.get(0) instanceof SynchronizedRegion) {
      SynchronizedRegion synchRegion = (SynchronizedRegion) subBlocks.get(0);
      InsnNode synchInsn = synchRegion.getEnterInsn();
      if (!synchInsn.getArg(0).isThis()) {
        LOG.warn("In synchronized method {}, top region not synchronized by 'this' {}", mth, synchInsn);
        return;
      }
      // replace synchronized block with inner region
      startRegion.getSubBlocks().set(0, synchRegion.getRegion());
      // remove 'monitor-enter' instruction
      InstructionRemover.remove(mth, synchInsn);
      // remove 'monitor-exit' instruction
      for (InsnNode exit : synchRegion.getExitInsns()) {
        InstructionRemover.remove(mth, exit);
      }
      // run region cleaner again
      CleanRegions.process(mth);
      // assume that CodeShrinker will be run after this
    }
  }
}
TOP

Related Classes of jadx.core.dex.visitors.regions.RegionMakerVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.