Example #1
0
void emitColAddElemC(HTS& env) {
  if (!topC(env, 2)->isA(Type::Obj)) {
    return interpOne(env, Type::Obj, 3);
  }
  if (!topC(env, 1, DataTypeGeneric)->type().
      subtypeOfAny(Type::Int, Type::Str)) {
    interpOne(env, Type::Obj, 3);
    return;
  }

  auto const val = popC(env);
  auto const key = popC(env);
  auto const coll = popC(env);
  push(env, gen(env, ColAddElemC, coll, key, val));
  gen(env, DecRef, key);
}
Example #2
0
void emitPrint(HTS& env) {
  auto const type = topC(env)->type();
  if (!type.subtypeOfAny(Type::Int, Type::Bool, Type::Null, Type::Str)) {
    interpOne(env, Type::Int, 1);
    return;
  }

  auto const cell = popC(env);

  Opcode op;
  if (type <= Type::Str) {
    op = PrintStr;
  } else if (type <= Type::Int) {
    op = PrintInt;
  } else if (type <= Type::Bool) {
    op = PrintBool;
  } else {
    assert(type <= Type::Null);
    op = Nop;
  }
  // the print helpers decref their arg, so don't decref pop'ed value
  if (op != Nop) {
    gen(env, op, cell);
  }
  push(env, cns(env, 1));
}
Example #3
0
void emitParent(HTS& env) {
  auto const clss = curClass(env);
  if (clss == nullptr || clss->parent() == nullptr) {
    interpOne(env, Type::Cls, 0);
  } else {
    push(env, cns(env, clss->parent()));
  }
}
Example #4
0
void emitSelf(HTS& env) {
  auto const clss = curClass(env);
  if (clss == nullptr) {
    interpOne(env, Type::Cls, 0);
  } else {
    push(env, cns(env, clss));
  }
}
Example #5
0
Block* makeExitSlow(IRGS& env) {
  auto const exit = env.unit.defBlock(Block::Hint::Unlikely);
  BlockPusher bp(*env.irb, makeMarker(env, bcOff(env)), exit);
  interpOne(env, *env.currentNormalizedInstruction);
  // If it changes the PC, InterpOneCF will get us to the new location.
  if (!opcodeChangesPC(env.currentNormalizedInstruction->op())) {
    gen(env, Jmp, makeExit(env, nextBcOff(env)));
  }
  return exit;
}
Example #6
0
void emitAGetC(HTS& env) {
  auto const name = topC(env);
  if (name->type().subtypeOfAny(Type::Obj, Type::Str)) {
    popC(env);
    implAGet(env, name);
    gen(env, DecRef, name);
  } else {
    interpOne(env, Type::Cls, 1);
  }
}
Example #7
0
void emitLateBoundCls(HTS& env) {
  auto const clss = curClass(env);
  if (!clss) {
    // no static context class, so this will raise an error
    interpOne(env, Type::Cls, 0);
    return;
  }
  auto const ctx = ldCtx(env);
  push(env, gen(env, LdClsCtx, ctx));
}
Example #8
0
void emitColAddNewElemC(HTS& env) {
  if (!topC(env, 1)->isA(Type::Obj)) {
    return interpOne(env, Type::Obj, 2);
  }

  auto const val = popC(env);
  auto const coll = popC(env);
  // The AddNewElem helper decrefs its args, so don't decref pop'ed values.
  push(env, gen(env, ColAddNewElemC, coll, val));
}
Example #9
0
void emitAddNewElemC(HTS& env) {
  if (!topC(env, 1)->isA(Type::Arr)) {
    return interpOne(env, Type::Arr, 2);
  }

  auto const val = popC(env);
  auto const arr = popC(env);
  // The AddNewElem helper decrefs its args, so don't decref pop'ed values.
  push(env, gen(env, AddNewElem, arr, val));
}
Example #10
0
void emitBareThis(HTS& env, BareThisOp subop) {
  if (!curClass(env)) {
    interpOne(env, Type::InitNull, 0); // will raise notice and push null
    return;
  }
  auto const ctx = gen(env, LdCtx, fp(env));
  if (subop == BareThisOp::NeverNull) {
    env.irb->setThisAvailable();
  } else {
    gen(env, CheckCtxThis, makeExitSlow(env), ctx);
  }
  pushIncRef(env, gen(env, CastCtxThis, ctx));
}
Example #11
0
void emitBindL(HTS& env, int32_t id) {
  if (curFunc(env)->isPseudoMain()) {
    interpOne(env, Type::BoxedInitCell, 1);
    return;
  }

  auto const ldPMExit = makePseudoMainExit(env);
  auto const newValue = popV(env);
  // Note that the IncRef must happen first, for correctness in a
  // pseudo-main: the destructor could decref the value again after
  // we've stored it into the local.
  pushIncRef(env, newValue);
  auto const oldValue = ldLoc(env, id, ldPMExit, DataTypeSpecific);
  stLocRaw(env, id, fp(env), newValue);
  gen(env, DecRef, oldValue);
}
Example #12
0
void emitAddElemC(HTS& env) {
  // This is just to peek at the type; it'll be consumed for real down below and
  // we don't want to constrain it if we're just going to InterpOne.
  auto const kt = topC(env, 1, DataTypeGeneric)->type();
  Opcode op;
  if (kt <= Type::Int) {
    op = AddElemIntKey;
  } else if (kt <= Type::Str) {
    op = AddElemStrKey;
  } else {
    interpOne(env, Type::Arr, 3);
    return;
  }

  // val is teleported from the stack to the array, so we don't have to do any
  // refcounting.
  auto const val = popC(env, DataTypeGeneric);
  auto const key = popC(env);
  auto const arr = popC(env);
  // The AddElem* instructions decref their args, so don't decref pop'ed
  // values.
  push(env, gen(env, op, arr, key, val));
}
Example #13
0
void interpOne(IRGS& env, Type outType, int popped) {
  InterpOneData idata { offsetFromIRSP(env, BCSPOffset{0}) };
  interpOne(env, outType, popped, 1, idata);
}
Example #14
0
void interpOne(IRGS& env, Type outType, int popped) {
  InterpOneData idata { spOffBCFromIRSP(env) };
  interpOne(env, outType, popped, 1, idata);
}
Example #15
0
void interpOne(IRGS& env, int popped) {
  InterpOneData idata { spOffBCFromIRSP(env) };
  interpOne(env, folly::none, popped, 0, idata);
}
Example #16
0
void interpOne(IRGS& env, Type outType, int popped) {
  InterpOneData idata { bcSPOffset(env) };
  interpOne(env, outType, popped, 1, idata);
}