예제 #1
0
  private static Type getPropertyType(final ScriptObject sobj, final String name) {
    final FindProperty find = sobj.findProperty(name, true);
    if (find == null) {
      return null;
    }

    final Property property = find.getProperty();
    final Class<?> propertyClass = property.getType();
    if (propertyClass == null) {
      // propertyClass == null means its value is Undefined. It is probably not initialized yet, so
      // we won't make
      // a type assumption yet.
      return null;
    } else if (propertyClass.isPrimitive()) {
      return Type.typeFor(propertyClass);
    }

    final ScriptObject owner = find.getOwner();
    if (property.hasGetterFunction(owner)) {
      // Can have side effects, so we can't safely evaluate it; since !propertyClass.isPrimitive(),
      // it's Object.
      return Type.OBJECT;
    }

    // Safely evaluate the property, and return the narrowest type for the actual value (e.g.
    // Type.INT for a boxed
    // integer).
    final Object value =
        property.needsDeclaration()
            ? ScriptRuntime.UNDEFINED
            : property.getObjectValue(owner, owner);
    if (value == ScriptRuntime.UNDEFINED) {
      return null;
    }
    return Type.typeFor(JSType.unboxedFieldType(value));
  }
 @Override
 public Type getType() {
   return Type.typeFor(NativeArray.class);
 }
 @Override
 public Type getType() {
   return Type.typeFor(value.getClass());
 }
예제 #4
0
  private Type getEvaluatedType(final Optimistic expr) {
    if (expr instanceof IdentNode) {
      if (runtimeScope == null) {
        return null;
      }
      return getPropertyType(runtimeScope, ((IdentNode) expr).getName());
    } else if (expr instanceof AccessNode) {
      final AccessNode accessNode = (AccessNode) expr;
      final Object base = evaluateSafely(accessNode.getBase());
      if (!(base instanceof ScriptObject)) {
        return null;
      }
      return getPropertyType((ScriptObject) base, accessNode.getProperty());
    } else if (expr instanceof IndexNode) {
      final IndexNode indexNode = (IndexNode) expr;
      final Object base = evaluateSafely(indexNode.getBase());
      if (base instanceof NativeArray || base instanceof ArrayBufferView) {
        // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of
        // their
        // underlying array storage, not based on values of individual elements. Thus, a
        // LongArrayData will
        // throw UOE for every optimistic int linkage attempt, even if the long value being returned
        // in the
        // first invocation would be representable as int. That way, we can presume that the array's
        // optimistic
        // type is the most optimistic type for which an element getter has a chance of executing
        // successfully.
        return ((ScriptObject) base).getArray().getOptimisticType();
      }
    } else if (expr instanceof CallNode) {
      // Currently, we'll only try to guess the return type of immediately invoked function
      // expressions with no
      // parameters, that is (function() { ... })(). We could do better, but these are all
      // heuristics and we can
      // gradually introduce them as needed. An easy one would be to do the same for .call(this)
      // idiom.
      final CallNode callExpr = (CallNode) expr;
      final Expression fnExpr = callExpr.getFunction();
      if (fnExpr instanceof FunctionNode) {
        final FunctionNode fn = (FunctionNode) fnExpr;
        if (callExpr.getArgs().isEmpty()) {
          final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId());
          if (data != null) {
            final Type returnType =
                Type.typeFor(data.getReturnType(EMPTY_INVOCATION_TYPE, runtimeScope));
            if (returnType == Type.BOOLEAN) {
              // We don't have optimistic booleans. In fact, optimistic call sites getting back
              // boolean
              // currently deoptimize all the way to Object.
              return Type.OBJECT;
            }
            assert returnType == Type.INT
                || returnType == Type.LONG
                || returnType == Type.NUMBER
                || returnType == Type.OBJECT;
            return returnType;
          }
        }
      }
    }

    return null;
  }