Exemplo n.º 1
0
 @Override
 public Result attempt(
     final List<AvailObject> args, final Interpreter interpreter, final boolean skipReturnCheck) {
   assert args.size() == 4;
   final A_BasicObject methodPojo = args.get(0);
   final A_Tuple methodArgs = args.get(1);
   final A_Tuple marshaledTypePojos = args.get(2);
   final A_Type expectedType = args.get(3);
   // Marshal the arguments and invoke the method.
   final Method method = (Method) methodPojo.javaObject();
   assert method != null;
   final Object[] marshaledArgs = new Object[methodArgs.tupleSize()];
   try {
     for (int i = 0; i < marshaledArgs.length; i++) {
       final Class<?> marshaledType = (Class<?>) marshaledTypePojos.tupleAt(i + 1).javaObject();
       marshaledArgs[i] = methodArgs.tupleAt(i + 1).marshalToJava(marshaledType);
     }
   } catch (final MarshalingException e) {
     return interpreter.primitiveFailure(
         PojoDescriptor.newPojo(
             RawPojoDescriptor.identityWrap(e), PojoTypeDescriptor.forClass(e.getClass())));
   }
   final Object result;
   try {
     result = method.invoke(null, marshaledArgs);
   } catch (final InvocationTargetException e) {
     final Throwable cause = e.getCause();
     return interpreter.primitiveFailure(
         PojoDescriptor.newPojo(
             RawPojoDescriptor.identityWrap(cause),
             PojoTypeDescriptor.forClass(cause.getClass())));
   } catch (final Throwable e) {
     // This is an unexpected failure.
     error("reflected method call unexpectedly failed");
     throw new Error();
   }
   if (result == null) {
     return interpreter.primitiveSuccess(PojoDescriptor.nullObject());
   }
   final AvailObject unmarshaled = PojoTypeDescriptor.unmarshal(result, expectedType);
   return interpreter.primitiveSuccess(unmarshaled);
 }
Exemplo n.º 2
0
  /**
   * 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;
  }