예제 #1
0
bool
Emitter::needs_excessive_magic(PerlJIT::AST::Op *ast)
{
  std::deque<Term *> nodes(1, ast);

  while (nodes.size()) {
    Term *node = nodes.front();
    nodes.pop_front();

    if ((node->get_type() == pj_ttype_lexical || node->get_type() == pj_ttype_variabledeclaration) &&
            node->get_value_type()->is_opaque())
      return true;

    if (node->get_type() != pj_ttype_op)
      continue;
    Op *op = static_cast<Op *>(node);

    bool known = Jittable_Ops.find(op->get_op_type()) != Jittable_Ops.end();

    if (!known || !op->may_have_explicit_overload())
      continue;

    std::vector<Term *> kids = node->get_kids();
    nodes.insert(nodes.end(), kids.begin(), kids.end());
  }

  return false;
}
예제 #2
0
bool
Emitter::is_jittable(PerlJIT::AST::Term *ast)
{
  switch (ast->get_type()) {
  case pj_ttype_constant:
  case pj_ttype_lexical:
  case pj_ttype_variabledeclaration:
    return true;
  case pj_ttype_optree:
    return false;
  case pj_ttype_statement:
    return is_jittable(static_cast<PerlJIT::AST::Statement *>(ast)->kids[0]);
  case pj_ttype_statementsequence: {
    std::vector<Term *> all = ast->get_kids();
    unsigned int jittable = 0;

    for (size_t i = 0, max = all.size(); i < max; ++i)
      jittable += is_jittable(all[i]);

    // TODO arbitrary threshold, it's probably better to look for
    //      long stretches of JITtable ops
    return jittable * 2 >= all.size();

  }
  case pj_ttype_op: {
    Op *op = static_cast<Op *>(ast);
    bool known = Jittable_Ops.find(op->get_op_type()) != Jittable_Ops.end();

    if (!known)
      return false;
    if (op->may_have_explicit_overload())
      return true;
    if (op->op_class() == pj_opc_binop &&
        static_cast<Binop *>(op)->is_synthesized_assignment())
      return is_jittable(op->kids[1]);
    return !needs_excessive_magic(op);
  }
  default:
    return false;
  }
}