示例#1
0
void SCCP::analyzeSSA(Instr* instr) {
    if (numDefs(instr) == 0) {
        if (isBlockEnd(instr))
            analyzeBranch((BlockEndInstr*)instr);
        return;
    }
    // dev: save current types for later check
    int i = 0;
    for (ArrayRange<Def> d = defRange(instr); !d.empty(); d.popFront(), ++i)
        old_types[i] = type(d.front());
    // compute types
    eval_counts[instr->id]++;
    analyzer.computeTypes(instr);
    // dev: check computation result
    bool changed2 = false;
    i = 0;
    for (ArrayRange<Def> d = defRange(instr); !d.empty(); d.popFront(), ++i) {
        AvmAssert(subtypeof(old_types[i], type(d.front())) && "illegal type narrowing");
        changed2 |= *type(d.front()) != *old_types[i];
    }
    if (changed2) {
        if (enable_typecheck) {
            printInstr(instr);
        }
        addInstrUsers(instr);
    }
}
示例#2
0
Def* IdentityAnalyzer::do_coerce(BinaryStmt* instr) {
  const Type* traits_type = type(instr->lhs_in());
  if (isConst(traits_type)) {
    const Type* to_type = lattice_->makeType(traitsVal(traits_type));
    Def* value_in = def(instr->rhs_in());
    if (subtypeof(type(value_in), to_type))
      return identity(instr, value_in);
  }
  return def_;
}
示例#3
0
Def* IdentityAnalyzer::do_cast(BinaryStmt* instr) {
  const Type* traits_type = type(instr->lhs_in());
  if (!isConst(traits_type))
    return def_; // Don't know the target traits.
  const Type* to_type = lattice_->makeType(traitsVal(traits_type));
  // fixme: this is copied from coerceIdentity().
  Def* value_in = def(instr->rhs_in());
  if (subtypeof(type(value_in), to_type))  
    return identity(instr, value_in);
  return def_;
}
示例#4
0
/* This function is the top level implementation of the instanceof operator. This is what
 * will actually get called by the program.
 *  object: a pointer to the object being tested
 *  isa_class: a pointer to the info of the class or interface which we are asking about
 *  isa_type_args: type arguments for the class or interface, stored in the same depth-first
 *    format as the object.
 */
bool wrt_instanceof(const w_object* object, 
                    const w_class_info* isa_class,
                    const w_class_info* const* isa_type_args)
{
  const w_class_info* obj_class = object->vtable->info;
  intptr_t obj_type_args_offset = obj_class->instance_size / sizeof(w_class_info*) - 1;
  const w_class_info* const* obj_type_args = object->type_args + obj_type_args_offset;
  intptr_t obj_type_args_size = 
    find_type_args_size(obj_class->type_parameters.size, obj_type_args);
  intptr_t* obj_type_args_index = alloca(obj_type_args_size * sizeof(intptr_t));
  index_type_args(obj_class->type_parameters.size, obj_type_args, obj_type_args_index, NULL);

  intptr_t isa_type_args_size = 
    find_type_args_size(isa_class->type_parameters.size, isa_type_args);
  intptr_t* isa_type_args_index = alloca(isa_type_args_size * sizeof(intptr_t));
  index_type_args(isa_class->type_parameters.size, isa_type_args, isa_type_args_index, NULL);

  return subtypeof(obj_class, obj_type_args, obj_type_args_index,
                   isa_class, isa_type_args, isa_type_args_index);
}
示例#5
0
Def* IdentityAnalyzer::coerceIdentity(UnaryStmt* instr, const Type* to_type) {
  Def* value_in = def(instr->value_in());
  if (subtypeof(type(value_in), to_type))
    return identity(instr, value_in);
  return def_;
}
示例#6
0
/* Test whether one object type S is a subtype of another T.
 * {s,t}_class: the class or interface of the types
 * {s,t}_type_args: a list of type argument words for S and T, stored in depth-first format
 * {s,t}_type_args_index: an index used to navigate the type argument words. See index_type_args.
 */
static bool subtypeof(const w_class_info* s_class, 
                      const w_class_info* const* s_type_args,
                      const intptr_t* s_type_args_index,
                      const w_class_info* t_class, 
                      const w_class_info* const* t_type_args,
                      const intptr_t* t_type_args_index)
{
  if (s_class == NULL) {
    // Nothing is a subtype of everything
    return true;
  } else if (t_class == NULL) {
    // There is no subtype of nothing
    return false;
  } else if (s_class != t_class) {
    // If S and T are of different classes, we can't compare them directly. We need to see if
    // S is a subtype of another type, S', which IS of the same class as T. Every class_info
    // and interface_info has a list of supertypes and an array of instructions for converting
    // to each supertype.

    // Determine whether we even support the other type
    intptr_t supertype_index = find_supertype(s_class, t_class);
    if (supertype_index == s_class->supertype_count)
      return false;

    // If we do support the other type, we need to convert S to that type. If there are no
    // instructions for doing so, T must have no reified type parameters, so we can stop.
    if (s_class->supertype_instructions == NULL)
      return true;
    const int8_t* const* supertype_instructions = 
      s_class->supertype_instructions[supertype_index];
    if (supertype_instructions == NULL)
      return true;

    // Do the actual conversion. We create a small array of offsets to the end of each 
    // type argument so we can easily move whole arguments. We create a new array of type
    // arguments of the appropriate size and execute the instructions.
    intptr_t s_type_arg_count = s_class->type_parameters.size;
    intptr_t* s_type_arg_offsets = alloca(s_type_arg_count * sizeof(intptr_t));
    intptr_t current_offset = 0;
    for (intptr_t i = 0; i < s_type_arg_count; i++) {
      current_offset += s_type_args_index[current_offset];
      s_type_arg_offsets[i] = current_offset;
    }
    intptr_t super_type_args_size = find_super_type_args_size(supertype_instructions,
                                                              s_type_arg_offsets);
    const w_class_info** super_type_args = alloca(super_type_args_size * sizeof(w_class_info*));
    execute_supertype_instructions(supertype_instructions,
                                   s_type_args,
                                   s_type_arg_offsets,
                                   super_type_args);

    // We need to create a new index for the converted type arguments. This can probably
    // be optimized to be done at the same time.
    intptr_t* super_type_args_index = alloca(super_type_args_size * sizeof(intptr_t));
    index_type_args(t_class->type_parameters.size, super_type_args, super_type_args_index, NULL);

    s_class = t_class;
    s_type_args = super_type_args;
    s_type_args_index = super_type_args_index;
  }

  // At this point, S and T are of the same class and will have the same number of type 
  // arguments. We just need to compare each pair of type arguments according to the variance
  // of the corresponding parameter.
  const w_type_parameter_info* tp_info = 
    (const w_type_parameter_info*) t_class->type_parameters.data;
  intptr_t next_s = 0, next_t = 0;
  for (intptr_t i = 0; i < t_class->type_parameters.size; ++i) {
    const w_class_info* tp_s_class = s_type_args[next_s];
    const w_class_info* const* tp_s_type_args = s_type_args + next_s + 1;
    const intptr_t* tp_s_type_args_index = s_type_args_index + next_s + 1;
    next_s += s_type_args_index[next_s];

    const w_class_info* tp_t_class = t_type_args[next_t];
    const w_class_info* const* tp_t_type_args = t_type_args + next_t + 1;
    const intptr_t* tp_t_type_args_index = t_type_args_index + next_t + 1;
    next_t += t_type_args_index[next_t];

    uint32_t variance = tp_info[i].flags & TYPE_PARAMETER_INFO_VARIANCE_MASK;
    if (variance == TYPE_PARAMETER_INFO_INVARIANT_FLAG) {
      if(!equals(tp_s_class, tp_s_type_args, tp_s_type_args_index,
                 tp_t_class, tp_t_type_args, tp_t_type_args_index))
        return false;
    } else if (variance == TYPE_PARAMETER_INFO_COVARIANT_FLAG) {
      if (!subtypeof(tp_s_class, tp_s_type_args, tp_s_type_args_index,
                     tp_t_class, tp_t_type_args, tp_t_type_args_index))
        return false;
    } else { // variance == TYPE_PARAMETER_INFO_CONTRAVARIANT_FLAG
      if (!subtypeof(tp_t_class, tp_t_type_args, tp_t_type_args_index,
                     tp_s_class, tp_s_type_args, tp_s_type_args_index))
        return false;
    }
  }
  return true;
}