OSDN Git Service

am c12b0da0: am e0b23da8: Merge "Tweak sanity check." into gingerbread
authorAndy McFadden <fadden@android.com>
Mon, 14 Jun 2010 21:44:13 +0000 (14:44 -0700)
committerAndroid Git Automerger <android-git-automerger@android.com>
Mon, 14 Jun 2010 21:44:13 +0000 (14:44 -0700)
Merge commit 'c12b0da035901923893f50663c48cb4efd390712'

* commit 'c12b0da035901923893f50663c48cb4efd390712':
  Tweak sanity check.

1  2 
vm/analysis/CodeVerify.c

diff --combined vm/analysis/CodeVerify.c
@@@ -29,7 -29,6 +29,7 @@@
   */
  #include "Dalvik.h"
  #include "analysis/CodeVerify.h"
 +#include "analysis/Optimize.h"
  #include "analysis/RegisterMap.h"
  #include "libdex/DexCatch.h"
  #include "libdex/InstrUtils.h"
@@@ -114,9 -113,7 +114,9 @@@ typedef struct RegisterTable 
  
  
  /* fwd */
 +#ifndef NDEBUG
  static void checkMergeTab(void);
 +#endif
  static bool isInitMethod(const Method* meth);
  static RegType getInvocationThis(const RegType* insnRegs,\
      const int insnRegCount, const DecodedInstruction* pDecInsn,
@@@ -542,12 -539,10 +542,12 @@@ static bool isInitMethod(const Method* 
  /*
   * Is this method a class initializer?
   */
 +#if 0
  static bool isClassInitMethod(const Method* meth)
  {
      return (*meth->name == '<' && strcmp(meth->name+1, "clinit>") == 0);
  }
 +#endif
  
  /*
   * Look up a class reference given as a simple string descriptor.
@@@ -1342,6 -1337,8 +1342,6 @@@ static ClassObject* getFieldClass(cons
  static inline RegType getRegisterType(const RegType* insnRegs,
      const int insnRegCount, u4 vsrc, VerifyError* pFailure)
  {
 -    RegType type;
 -
      if (vsrc >= (u4) insnRegCount) {
          *pFailure = VERIFY_ERROR_GENERIC;
          return kRegTypeUnknown;
@@@ -2924,10 -2921,6 +2924,10 @@@ static void verifyFilledNewArrayRegs(co
   * Replace an instruction with "throw-verification-error".  This allows us to
   * defer error reporting until the code path is first used.
   *
 + * This is expected to be called during "just in time" verification, not
 + * from within dexopt.  (Verification failures in dexopt will result in
 + * postponement of verification to first use of the class.)
 + *
   * The throw-verification-error instruction requires two code units.  Some
   * of the replaced instructions require three; the third code unit will
   * receive a "nop".  The instruction's length will be left unchanged
@@@ -2949,6 -2942,8 +2949,6 @@@ static bool replaceFailingInstruction(M
      u2 oldInsn = *oldInsns;
      bool result = false;
  
 -    //dvmMakeCodeReadWrite(meth);
 -
      //LOGD("  was 0x%04x\n", oldInsn);
      u2* newInsns = (u2*) meth->insns + insnIdx;
  
      result = true;
  
  bail:
 -    //dvmMakeCodeReadOnly(meth);
      return result;
  }
  
 +/*
 + * Replace {iget,iput,sget,sput}-wide with the -wide-volatile form.
 + *
 + * If this is called during dexopt, we can modify the instruction in
 + * place.  If this happens during just-in-time verification, we need to
 + * use the DEX read/write page feature.
 + *
 + * NOTE:
 + * This shouldn't really be tied to verification.  It ought to be a
 + * separate pass that is run before or after the verifier.  However, that
 + * requires a bunch of extra code, and the only advantage of doing so is
 + * that the feature isn't disabled when verification is turned off.  At
 + * some point we may need to revisit this choice.
 + */
 +static void replaceVolatileInstruction(Method* meth, InsnFlags* insnFlags,
 +    int insnIdx)
 +{
 +    u2* oldInsns = (u2*)meth->insns + insnIdx;
 +    u2 oldInsn = *oldInsns;
 +    u2 newVal;
 +
 +    switch (oldInsn & 0xff) {
 +    case OP_IGET_WIDE:  newVal = OP_IGET_WIDE_VOLATILE;     break;
 +    case OP_IPUT_WIDE:  newVal = OP_IPUT_WIDE_VOLATILE;     break;
 +    case OP_SGET_WIDE:  newVal = OP_SGET_WIDE_VOLATILE;     break;
 +    case OP_SPUT_WIDE:  newVal = OP_SPUT_WIDE_VOLATILE;     break;
 +    default:
 +        LOGE("wide-volatile op mismatch (0x%x)\n", oldInsn);
 +        dvmAbort();
 +        return;     // in-lieu-of noreturn attribute
 +    }
 +
 +    /* merge new opcode into 16-bit code unit */
 +    newVal |= (oldInsn & 0xff00);
 +
 +    if (gDvm.optimizing) {
 +        /* dexopt time, alter the output */
 +        *oldInsns = newVal;
 +    } else {
 +        /* runtime, make the page read/write */
 +        dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns, newVal);
 +    }
 +}
 +
  
  /*
   * ===========================================================================
@@@ -3107,7 -3059,10 +3107,7 @@@ bool dvmVerifyCodeFlow(Method* meth, In
  {
      bool result = false;
      const int insnsSize = dvmGetMethodInsnsSize(meth);
 -    const u2* insns = meth->insns;
      const bool generateRegisterMap = gDvm.generateRegisterMaps;
 -    int i, offset;
 -    bool isConditional;
      RegisterTable regTable;
  
      memset(&regTable, 0, sizeof(regTable));
          gDvm.classJavaLangObject =
              dvmFindSystemClassNoInit("Ljava/lang/Object;");
  
-     if (meth->registersSize * insnsSize > 2*1024*1024) {
+     if (meth->registersSize * insnsSize > 4*1024*1024) {
          /* should probably base this on actual memory requirements */
          LOG_VFY_METH(meth,
              "VFY: arbitrarily rejecting large method (regs=%d count=%d)\n",
@@@ -3257,10 -3212,11 +3257,10 @@@ static bool doCodeVerification(Method* 
      RegisterTable* regTable, UninitInstanceMap* uninitMap)
  {
      const int insnsSize = dvmGetMethodInsnsSize(meth);
 -    const u2* insns = meth->insns;
      RegType workRegs[meth->registersSize + kExtraRegs];
      bool result = false;
      bool debugVerbose = false;
 -    int insnIdx, startGuess, prevAddr;
 +    int insnIdx, startGuess;
  
      /*
       * Begin by marking the first instruction as "changed".
@@@ -3518,6 -3474,7 +3518,6 @@@ static bool verifyInstruction(Method* m
      const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
      RegType entryRegs[meth->registersSize + kExtraRegs];
      ClassObject* resClass;
 -    const char* className;
      int branchTarget = 0;
      const int insnRegCount = meth->registersSize;
      RegType tmpType;
      case OP_IF_NE:
          {
              RegType type1, type2;
 -            bool tmpResult;
  
              type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA,
                          &failure);
@@@ -4484,6 -4442,7 +4484,6 @@@ aput_1nr_common
          goto iget_1nr_common;
  iget_1nr_common:
          {
 -            ClassObject* fieldClass;
              InstField* instField;
              RegType objType, fieldType;
  
          }
          break;
      case OP_IGET_WIDE:
 +    case OP_IGET_WIDE_VOLATILE:
          {
              RegType dstType;
 -            ClassObject* fieldClass;
              InstField* instField;
              RegType objType;
  
                  setRegisterType(workRegs, insnRegCount, decInsn.vA,
                      dstType, &failure);
              }
 +            if (VERIFY_OK(failure)) {
 +                if (decInsn.opCode != OP_IGET_WIDE_VOLATILE &&
 +                    dvmIsVolatileField(&instField->field))
 +                {
 +                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
 +                }
 +            }
          }
          break;
      case OP_IGET_OBJECT:
  iput_1nr_common:
          {
              RegType srcType, fieldType, objType;
 -            ClassObject* fieldClass;
              InstField* instField;
  
              srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
          }
          break;
      case OP_IPUT_WIDE:
 +    case OP_IPUT_WIDE_VOLATILE:
          tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
          if (VERIFY_OK(failure)) {
              RegType typeHi =
              checkWidePair(tmpType, typeHi, &failure);
          }
          if (VERIFY_OK(failure)) {
 -            ClassObject* fieldClass;
              InstField* instField;
              RegType objType;
  
                  failure = VERIFY_ERROR_GENERIC;
                  break;
              }
 +            if (VERIFY_OK(failure)) {
 +                if (decInsn.opCode != OP_IPUT_WIDE_VOLATILE &&
 +                    dvmIsVolatileField(&instField->field))
 +                {
 +                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
 +                }
 +            }
          }
          break;
      case OP_IPUT_OBJECT:
@@@ -4802,7 -4748,6 +4802,7 @@@ sget_1nr_common
          }
          break;
      case OP_SGET_WIDE:
 +    case OP_SGET_WIDE_VOLATILE:
          {
              StaticField* staticField;
              RegType dstType;
                  setRegisterType(workRegs, insnRegCount, decInsn.vA,
                      dstType, &failure);
              }
 +            if (VERIFY_OK(failure)) {
 +                if (decInsn.opCode != OP_SGET_WIDE_VOLATILE &&
 +                    dvmIsVolatileField(&staticField->field))
 +                {
 +                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
 +                }
 +            }
          }
          break;
      case OP_SGET_OBJECT:
@@@ -4926,7 -4864,6 +4926,7 @@@ sput_1nr_common
          }
          break;
      case OP_SPUT_WIDE:
 +    case OP_SPUT_WIDE_VOLATILE:
          tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
          if (VERIFY_OK(failure)) {
              RegType typeHi =
                  failure = VERIFY_ERROR_GENERIC;
                  break;
              }
 +            if (VERIFY_OK(failure)) {
 +                if (decInsn.opCode != OP_SPUT_WIDE_VOLATILE &&
 +                    dvmIsVolatileField(&staticField->field))
 +                {
 +                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
 +                }
 +            }
          }
          break;
      case OP_SPUT_OBJECT:
                   * do this for all registers that have the same object
                   * instance in them, not just the "this" register.
                   */
 -                int uidx = regTypeToUninitIndex(thisType);
                  markRefsAsInitialized(workRegs, insnRegCount, uninitMap,
                      thisType, &failure);
                  if (!VERIFY_OK(failure))
      case OP_UNUSED_E5:
      case OP_UNUSED_E6:
      case OP_UNUSED_E7:
 -    case OP_UNUSED_E8:
 -    case OP_UNUSED_E9:
 -    case OP_UNUSED_EA:
 -    case OP_UNUSED_EB:
      case OP_BREAKPOINT:
      case OP_UNUSED_F1:
      case OP_UNUSED_FC:
      /*
       * If we didn't just set the result register, clear it out.  This
       * ensures that you can only use "move-result" immediately after the
 -     * result is set.
 +     * result is set.  (We could check this statically, but it's not
 +     * expensive and it makes our debugging output cleaner.)
       */
      if (!justSetResult) {
          int reg = RESULT_REGISTER(insnRegCount);
       */
      if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
      {
 -        DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
          const DexCode* pCode = dvmGetMethodCode(meth);
          DexCatchIterator iterator;