예제 #1
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;
  }
}
예제 #2
0
bool
Emitter::_jit_emit_return(Term *ast, pj_op_context context, Value *value, const PerlJIT::AST::Type *type)
{
  // TODO OPs with OPpTARGET_MY flag are in scalar context even when
  // they should be in void context, so we're emitting an useless push
  // below

  if (context == pj_context_caller) {
    set_error("Caller-determined context not implemented");
    return false;
  }

  if (context != pj_context_scalar)
    return true;

  Op *op = dynamic_cast<Op *>(ast);
  Value *res;

  switch (op->op_class()) {
  case pj_opc_binop: {
    // the assumption here is that the OPf_STACKED assignment
    // has been handled by _jit_emit below, and here we only need
    // to handle cases like '$x = $y += 7'
    if (op->get_op_type() == pj_binop_sassign) {
      if (type->equals(&SCALAR_T)) {
        res = value;
      } else {
        // TODO suboptimal, but correct, need to ask for SCALAR
        // in the call to _jit_emit() above
        res = pa.emit_sv_newmortal();
      }
    } else {
      if (!op->get_perl_op()->op_targ && type->equals(&SCALAR_T)) {
        res = value;
      } else {
        if (!op->get_perl_op()->op_targ) {
          set_error("Binary OP without target");
          return false;
        }
        res = pa.emit_OP_targ();
      }
    }
  }
  case pj_opc_unop:
    if (!op->get_perl_op()->op_targ) {
      set_error("Unary OP without target");
      return false;
    }
    res = pa.emit_OP_targ();
  default:
    res = pa.emit_sv_newmortal();
    break;
  }

  if (res != value)
    if (!_jit_assign_sv(res, value, type))
      return false;

  pa.alloc_sp();
  pa.emit_SPAGAIN();
  pa.emit_XPUSHs(res);
  pa.emit_PUTBACK();

  return true;
}