@Override
 @AvailMethod
 void o_SetMethodName(final AvailObject object, final A_String methodName) {
   assert methodName.isString();
   methodName.makeImmutable();
   final A_Atom propertyAtom = object.mutableSlot(PROPERTY_ATOM);
   propertyAtom.setAtomProperty(methodNameKeyAtom(), methodName);
   // Now scan all sub-blocks. Some literals will be functions and some
   // will be compiled code objects.
   int counter = 1;
   for (int i = 1, limit = object.numLiterals(); i <= limit; i++) {
     final AvailObject literal = object.literalAt(i);
     final A_RawFunction subCode;
     if (literal.isFunction()) {
       subCode = literal.code();
     } else if (literal.isInstanceOf(CompiledCodeTypeDescriptor.mostGeneralType())) {
       subCode = literal;
     } else {
       subCode = null;
     }
     if (subCode != null) {
       final String suffix = String.format("[%d]", counter);
       counter++;
       final A_Tuple newName = methodName.concatenateWith(StringDescriptor.from(suffix), true);
       subCode.setMethodName((A_String) newName);
     }
   }
 }
 /** Answer the starting line number for this block of code. */
 @Override
 @AvailMethod
 int o_StartingLineNumber(final AvailObject object) {
   final A_Atom properties = object.mutableSlot(PROPERTY_ATOM);
   final A_Number lineInteger = properties.getAtomProperty(lineNumberKeyAtom());
   return lineInteger.equalsNil() ? 0 : lineInteger.extractInt();
 }
 @Override
 @AvailMethod
 A_String o_MethodName(final AvailObject object) {
   final A_Atom propertyAtom = object.mutableSlot(PROPERTY_ATOM);
   final A_String methodName = propertyAtom.getAtomProperty(methodNameKeyAtom());
   if (methodName.equalsNil()) {
     return StringDescriptor.from("Unknown function");
   }
   return methodName;
 }
  /**
   * Create a new compiled code object with the given properties.
   *
   * @param nybbles The nybblecodes.
   * @param locals The number of local variables.
   * @param stack The maximum stack depth.
   * @param functionType The type that the code's functions will have.
   * @param primitive Which primitive to invoke, or zero.
   * @param literals A tuple of literals.
   * @param localTypes A tuple of types of local variables.
   * @param outerTypes A tuple of types of outer (captured) variables.
   * @param module The module in which the code, or nil.
   * @param lineNumber The module line number on which this code starts.
   * @return The new compiled code object.
   */
  public static AvailObject create(
      final A_Tuple nybbles,
      final int locals,
      final int stack,
      final A_Type functionType,
      final @Nullable Primitive primitive,
      final A_Tuple literals,
      final A_Tuple localTypes,
      final A_Tuple outerTypes,
      final A_Module module,
      final int lineNumber) {
    if (primitive != null) {
      // Sanity check for primitive blocks.  Use this to hunt incorrectly
      // specified primitive signatures.
      final boolean canHaveCode = primitive.canHaveNybblecodes();
      assert canHaveCode == (nybbles.tupleSize() > 0);
      final A_Type restrictionSignature = primitive.blockTypeRestriction();
      assert restrictionSignature.isSubtypeOf(functionType);
    } else {
      assert nybbles.tupleSize() > 0;
    }

    assert localTypes.tupleSize() == locals;
    final A_Type argCounts = functionType.argsTupleType().sizeRange();
    final int numArgs = argCounts.lowerBound().extractInt();
    assert argCounts.upperBound().extractInt() == numArgs;
    final int literalsSize = literals.tupleSize();
    final int outersSize = outerTypes.tupleSize();

    assert 0 <= numArgs && numArgs <= 0xFFFF;
    assert 0 <= locals && locals <= 0xFFFF;
    final int slotCount = numArgs + locals + stack;
    assert 0 <= slotCount && slotCount <= 0xFFFF;
    assert 0 <= outersSize && outersSize <= 0xFFFF;

    assert module.equalsNil() || module.isInstanceOf(MODULE.o());
    assert lineNumber >= 0;

    final AvailObject code = mutable.create(literalsSize + outersSize + locals);

    final InvocationStatistic statistic = new InvocationStatistic();
    statistic.countdownToReoptimize.set(L2Chunk.countdownForNewCode());
    final AvailObject statisticPojo = RawPojoDescriptor.identityWrap(statistic);

    code.setSlot(NUM_LOCALS, locals);
    code.setSlot(NUM_ARGS, numArgs);
    code.setSlot(FRAME_SLOTS, slotCount);
    code.setSlot(NUM_OUTERS, outersSize);
    code.setSlot(PRIMITIVE, primitive == null ? 0 : primitive.primitiveNumber);
    code.setSlot(NYBBLES, nybbles.makeShared());
    code.setSlot(FUNCTION_TYPE, functionType.makeShared());
    code.setSlot(PROPERTY_ATOM, NilDescriptor.nil());
    code.setSlot(STARTING_CHUNK, L2Chunk.unoptimizedChunk().chunkPojo);
    code.setSlot(INVOCATION_STATISTIC, statisticPojo);

    // Fill in the literals.
    int dest;
    for (dest = 1; dest <= literalsSize; dest++) {
      code.setSlot(LITERAL_AT_, dest, literals.tupleAt(dest).makeShared());
    }
    for (int i = 1; i <= outersSize; i++) {
      code.setSlot(LITERAL_AT_, dest++, outerTypes.tupleAt(i).makeShared());
    }
    for (int i = 1; i <= locals; i++) {
      code.setSlot(LITERAL_AT_, dest++, localTypes.tupleAt(i).makeShared());
    }
    assert dest == literalsSize + outersSize + locals + 1;

    final A_Atom propertyAtom =
        AtomWithPropertiesDescriptor.create(TupleDescriptor.empty(), module);
    propertyAtom.setAtomProperty(lineNumberKeyAtom(), IntegerDescriptor.fromInt(lineNumber));
    code.setSlot(PROPERTY_ATOM, propertyAtom.makeShared());
    final int hash = propertyAtom.hash() ^ -0x3087B215;
    code.setSlot(HASH, hash);
    code.makeShared();

    // Add the newborn raw function to the weak set being used for code
    // coverage tracking.
    activeRawFunctions.add(code);

    return code;
  }
 /** Answer the module in which this code occurs. */
 @Override
 @AvailMethod
 A_Module o_Module(final AvailObject object) {
   final A_Atom properties = object.mutableSlot(PROPERTY_ATOM);
   return properties.issuingModule();
 }