SparseArray<FieldReference> linkedFields = new SparseArray<FieldReference>(); ArrayList<Field> fields = getSortedInstanceFields(getClassDef()); FieldReference field = null; int lastOffset = 0; for (int i=0; i<superFields.size(); i++) { int offset = superFields.keyAt(i); field = superFields.valueAt(i); linkedFields.put(offset, field); lastOffset = offset; if (gap != null && gap.size >= fieldSize) { gaps.poll(); linkedFields.put(gap.offset, field); if (gap.size > fieldSize) { addFieldGap(gap.offset + fieldSize, gap.offset + gap.size, gaps); linkedFields.append(fieldOffset, field); fieldOffset += fieldSize;
analyzedInstructions.ensureCapacity(instructions.size()); for (int i=0; i<instructions.size(); i++) { Instruction instruction = instructions.get(i); analyzedInstructions.append(currentCodeAddress, new AnalyzedInstruction(this, instruction, i, registerCount)); assert analyzedInstructions.indexOfKey(currentCodeAddress) == i; currentCodeAddress += instruction.getCodeUnits(); for (int i=0; i< analyzedInstructions.size(); i++) { AnalyzedInstruction instruction = analyzedInstructions.valueAt(i); Opcode instructionOpcode = instruction.instruction.getOpcode(); currentCodeAddress = getInstructionAddress(instruction); assert analyzedInstructions.size() > 0; BitSet instructionsToProcess = new BitSet(instructions.size()); addPredecessorSuccessor(startOfMethod, analyzedInstructions.valueAt(0), exceptionHandlers, instructionsToProcess); while (!instructionsToProcess.isEmpty()) { int currentInstructionIndex = instructionsToProcess.nextSetBit(0); instructionsToProcess.clear(currentInstructionIndex); AnalyzedInstruction instruction = analyzedInstructions.valueAt(currentInstructionIndex); Opcode instructionOpcode = instruction.instruction.getOpcode(); int instructionCodeAddress = getInstructionAddress(instruction); if (currentInstructionIndex == analyzedInstructions.size() - 1) { throw new AnalysisException("Execution can continue past the last instruction");
@Bench public void timeInsertAndLookupSparseArray() { SparseArray<Object> sparse = new SparseArray<Object>(); Object value = null; for (int i = 0; i < data.length; i++) { sparse.put(i, data[i]); // int key = sparse.keyAt(i); value = sparse.get(i); } value.toString(); }
private int getNextFieldOffset() { SparseArray<FieldReference> instanceFields = getInstanceFields(); if (instanceFields.size() == 0) { return classPath.isArt() ? 0 : 8; } int lastItemIndex = instanceFields.size()-1; int fieldOffset = instanceFields.keyAt(lastItemIndex); FieldReference lastField = instanceFields.valueAt(lastItemIndex); if (classPath.isArt()) { return fieldOffset + getTypeSize(lastField.getType().charAt(0)); } else { switch (lastField.getType().charAt(0)) { case 'J': case 'D': return fieldOffset + 8; default: return fieldOffset + 4; } } }
BitSet instructionsToAnalyze = new BitSet(analyzedInstructions.size()); BitSet undeodexedInstructions = new BitSet(analyzedInstructions.size()); continue; AnalyzedInstruction instructionToAnalyze = analyzedInstructions.valueAt(i); try { if (instructionToAnalyze.originalInstruction.getOpcode().odexOnly()) { for (int i=0; i< analyzedInstructions.size(); i++) { AnalyzedInstruction analyzedInstruction = analyzedInstructions.valueAt(i);
private void overridePredecessorRegisterTypeAndPropagateChanges( @Nonnull AnalyzedInstruction analyzedInstruction, @Nonnull AnalyzedInstruction predecessor, int registerNumber, @Nonnull RegisterType registerType) { BitSet changedInstructions = new BitSet(analyzedInstructions.size()); if (!analyzedInstruction.overridePredecessorRegisterType( predecessor, registerNumber, registerType, analyzedState)) { return; } changedInstructions.set(analyzedInstruction.instructionIndex); propagateChanges(changedInstructions, registerNumber, true); if (registerType.category == RegisterType.LONG_LO) { checkWidePair(registerNumber, analyzedInstruction); overridePredecessorRegisterTypeAndPropagateChanges(analyzedInstruction, predecessor, registerNumber + 1, RegisterType.LONG_HI_TYPE); } else if (registerType.category == RegisterType.DOUBLE_LO) { checkWidePair(registerNumber, analyzedInstruction); overridePredecessorRegisterTypeAndPropagateChanges(analyzedInstruction, predecessor, registerNumber + 1, RegisterType.DOUBLE_HI_TYPE); } }
/** * Returns the index for which {@link #keyAt} would return the * specified key, or a negative number if the specified * key is not mapped. */ public int indexOfKey(int key) { if (mGarbage) { gc(); } return binarySearch(mKeys, 0, mSize, key); }
/** * Puts a key/value pair into the array, optimizing for the case where * the key is greater than all existing keys in the array. */ public void append(int key, E value) { if (mSize != 0 && key <= mKeys[mSize - 1]) { put(key, value); return; } if (mGarbage && mSize >= mKeys.length) { gc(); } int pos = mSize; if (pos >= mKeys.length) { int n = Math.max(pos + 1, mKeys.length * 2); int[] nkeys = new int[n]; Object[] nvalues = new Object[n]; // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); System.arraycopy(mValues, 0, nvalues, 0, mValues.length); mKeys = nkeys; mValues = nvalues; } mKeys[pos] = key; mValues[pos] = value; mSize = pos + 1; }
private void propagateChanges(@Nonnull BitSet changedInstructions, int registerNumber, boolean override) { //Using a for loop inside the while loop optimizes for the common case of the successors of an instruction //occurring after the instruction. Any successors that occur prior to the instruction will be picked up on //the next iteration of the while loop. //This could also be done recursively, but in large methods it would likely cause very deep recursion. while (!changedInstructions.isEmpty()) { for (int instructionIndex=changedInstructions.nextSetBit(0); instructionIndex>=0; instructionIndex=changedInstructions.nextSetBit(instructionIndex+1)) { changedInstructions.clear(instructionIndex); propagateRegisterToSuccessors(analyzedInstructions.valueAt(instructionIndex), registerNumber, changedInstructions, override); } } }
public int getInstructionAddress(@Nonnull AnalyzedInstruction instruction) { return analyzedInstructions.keyAt(instruction.instructionIndex); }
@Nonnull private AnalyzedInstruction[] buildExceptionHandlerArray(@Nonnull TryBlock<? extends ExceptionHandler> tryBlock) { List<? extends ExceptionHandler> exceptionHandlers = tryBlock.getExceptionHandlers(); AnalyzedInstruction[] handlerInstructions = new AnalyzedInstruction[exceptionHandlers.size()]; for (int i=0; i<exceptionHandlers.size(); i++) { handlerInstructions[i] = analyzedInstructions.get(exceptionHandlers.get(i).getHandlerCodeAddress()); } return handlerInstructions; }
/** * Gets the Object mapped from the specified key, or the specified Object * if no such mapping has been made. */ public E get(int key, E valueIfKeyNotFound) { int i = binarySearch(mKeys, 0, mSize, key); if (i < 0 || mValues[i] == DELETED) { return valueIfKeyNotFound; } else { return (E) mValues[i]; } }
/** * Alias for {@link #delete(int)}. */ public void remove(int key) { delete(key); }
@BeforeBenchClass @BeforeClass public static void beforeClass() { for (int i = 0; i < data.length; i++) { data[i] = new Integer(i); mySparse.put(i, data[i]); myTrove.put(i, data[i]); } }
instanceFields.append(fieldOffset, field); fieldOffset += sizeof_uint32_t; continue; instanceFields.append(fieldOffset, field); fields.remove(i); break; final Field field = fields.remove(0); final int type = getTypeAsPrimitiveType(field); instanceFields.append(fieldOffset, field); fieldOffset += (type == kPrimLong || type == kPrimDouble) ? sizeof_uint64_t : sizeof_uint32_t;
private int getNextFieldOffset() { SparseArray<FieldReference> instanceFields = getInstanceFields(); if (instanceFields.size() == 0) { return 8; } int lastItemIndex = instanceFields.size()-1; int fieldOffset = instanceFields.keyAt(lastItemIndex); FieldReference lastField = instanceFields.valueAt(lastItemIndex); switch (lastField.getType().charAt(0)) { case 'J': case 'D': return fieldOffset + 8; default: return fieldOffset + 4; } }
private void setPostRegisterTypeAndPropagateChanges(@Nonnull AnalyzedInstruction analyzedInstruction, int registerNumber, @Nonnull RegisterType registerType) { BitSet changedInstructions = new BitSet(analyzedInstructions.size()); if (!analyzedInstruction.setPostRegisterType(registerNumber, registerType)) { return; } propagateRegisterToSuccessors(analyzedInstruction, registerNumber, changedInstructions); //Using a for loop inside the while loop optimizes for the common case of the successors of an instruction //occurring after the instruction. Any successors that occur prior to the instruction will be picked up on //the next iteration of the while loop. //This could also be done recursively, but in large methods it would likely cause very deep recursion, //which requires the user to specify a larger stack size. This isn't really a problem, but it is slightly //annoying. while (!changedInstructions.isEmpty()) { for (int instructionIndex=changedInstructions.nextSetBit(0); instructionIndex>=0; instructionIndex=changedInstructions.nextSetBit(instructionIndex+1)) { changedInstructions.clear(instructionIndex); propagateRegisterToSuccessors(analyzedInstructions.valueAt(instructionIndex), registerNumber, changedInstructions); } } if (registerType.category == RegisterType.LONG_LO) { checkWidePair(registerNumber, analyzedInstruction); setPostRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1, RegisterType.LONG_HI_TYPE); } else if (registerType.category == RegisterType.DOUBLE_LO) { checkWidePair(registerNumber, analyzedInstruction); setPostRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1, RegisterType.DOUBLE_HI_TYPE); } }