Search code examples
androidmethodslimit

'Method exceeds compiler instruction limit' message on well under 64K method


I often see repeated messages like this in my log:

Method exceeds compiler instruction limit: 29278 in void com.xxxxxxapp.xxxxxx.MyGLRenderer.onDrawFrame(javax.microedition.khronos.opengles.GL10)
Method exceeds compiler instruction limit: 29278 in void com.xxxxxxapp.xxxxxx.MyGLRenderer.onDrawFrame(javax.microedition.khronos.opengles.GL10)
Method exceeds compiler instruction limit: 29278 in void com.xxxxxxapp.xxxxxx.MyGLRenderer.onDrawFrame(javax.microedition.khronos.opengles.GL10)

Breaking the code down typically gives the same message with a smaller number:

Method exceeds compiler instruction limit: 22400 in void com.xxxxxxapp.xxxxxx.MyGLRenderer.onDrawFrame(javax.microedition.khronos.opengles.GL10)

I thought 64000 was the magic number to keep under here. My game code has always appeared to run fine despite nagging messages like this, and it's not just in the opengl onDrawFrame method. I've gotten similar messages in my update method for well under 64K, although update code is easier to break down than drawing code.

Searches for 'Method exceeds compiler instruction limit' have just gotten me links to the dreaded 'Dalvik compiler limit on 64K methods' error. Do I have to keep ignoring this?


Solution

  • This happens because of Compiler::IsPathologicalCase:

    Skip compilation for pathologically large methods - either by instruction count or num vregs.

    Dalvik uses 16-bit uints for instruction and register counts. We'll limit to a quarter of that, which also guarantees we cannot overflow our 16-bit internal Quick SSA name space.

    Source: compiler.cc.

    16-bit uint can represent a maximum value of 65535, divided by 4, equals 16383.75.

    Raising the target level from Dalvik to ART might circumvent it; because Dalvik and javax.microedition.khronos.opengles.GL10 seem to be incompatible, due to instruction count.

    The register count is being checked after that, therefore this doesn't seem to the issue here.

    Patching compiler.cc would also be an option, despite not a good one.

    • when 4 would be 2, this would permit double the amount.

    • when not return true it should also proceed with the compilation.

    This is the check, which is at fault:

    if (accessor.InsnsSizeInCodeUnits() >= UINT16_MAX / 4) {
      LOG(INFO) << "Method exceeds compiler instruction limit: "
                << accessor.InsnsSizeInCodeUnits()
                << " in " << dex_file.PrettyMethod(method_idx);
      return true;
    }
    

    Disclaimer: without the least guarantee of "no side effects".