Beispiel #1
0
void tvCastToResourceInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  switch (tv->m_type) {
  case KindOfUninit:
  case KindOfNull:
  case KindOfBoolean:
  case KindOfInt64:
  case KindOfDouble:
  case KindOfStaticString:
    break;
  case KindOfString:
  case KindOfArray:
  case KindOfObject:
    tvDecRef(tv);
    break;
  case KindOfResource:
    // no op, return
    return;
  default:
    assert(false);
    break;
  }
  tv->m_type = KindOfResource;
  tv->m_data.pres = NEWOBJ(DummyResource);
  tv->m_data.pres->incRefCount();
  return;
}
Beispiel #2
0
void tvCastToArrayInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  ArrayData * a;
  switch (tv->m_type) {
  case KindOfUninit:
  case KindOfNull:    a = ArrayData::Create(); break;
  case KindOfBoolean:
  case KindOfInt64:
  case KindOfDouble:
  case KindOfStaticString: a = ArrayData::Create(tvAsVariant(tv)); break;
  case KindOfString:  {
    a = ArrayData::Create(tvAsVariant(tv));
    tvDecRefStr(tv);
    break;
  }
  case KindOfArray:   return;
  case KindOfObject:  {
    // For objects, we fall back on the Variant machinery
    tvAsVariant(tv) = tv->m_data.pobj->o_toArray();
    return;
  }
  case KindOfResource:  {
    // For resources, we fall back on the Variant machinery
    tvAsVariant(tv) = tv->m_data.pres->o_toArray();
    return;
  }
  default:            assert(false); a = ArrayData::Create(); break;
  }
  tv->m_data.parr = a;
  tv->m_type = KindOfArray;
  tv->m_data.parr->incRefCount();
}
Beispiel #3
0
void tvCastToObjectInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  ObjectData* o;
  switch (tv->m_type) {
  case KindOfUninit:
  case KindOfNull:    o = SystemLib::AllocStdClassObject(); break;
  case KindOfBoolean:
  case KindOfInt64:
  case KindOfDouble:
  case KindOfStaticString: {
    o = SystemLib::AllocStdClassObject();
    o->o_set(s_scalar, tvAsVariant(tv));
    break;
  }
  case KindOfString: {
    o = SystemLib::AllocStdClassObject();
    o->o_set(s_scalar, tvAsVariant(tv));
    tvDecRefStr(tv);
    break;
  }
  case KindOfArray:   {
    // For arrays, we fall back on the Variant machinery
    tvAsVariant(tv) = tv->m_data.parr->toObject();
    return;
  }
  case KindOfObject: return;
  case KindOfResource: return;
  default: assert(false); o = SystemLib::AllocStdClassObject(); break;
  }
  tv->m_data.pobj = o;
  tv->m_type = KindOfObject;
  tv->m_data.pobj->incRefCount();
}
Beispiel #4
0
void tvCastToDoubleInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);

  double d;
  switch (tv->m_type) {
  case KindOfUninit:
  case KindOfNull:    d = 0.0; break;
  case KindOfBoolean: assert(tv->m_data.num == 0LL || tv->m_data.num == 1LL);
  case KindOfInt64:   d = (double)(tv->m_data.num); break;
  case KindOfDouble:  return;
  case KindOfStaticString: d = tv->m_data.pstr->toDouble(); break;
  case KindOfString:  d = tv->m_data.pstr->toDouble(); tvDecRefStr(tv); break;
  case KindOfArray:   {
    d = (double)(tv->m_data.parr->empty() ? 0LL : 1LL);
    tvDecRefArr(tv);
    break;
  }
  case KindOfObject:  {
    d = tv->m_data.pobj->o_toDouble();
    tvDecRefObj(tv);
    break;
  }
  case KindOfResource:  {
    d = tv->m_data.pres->o_toDouble();
    tvDecRefRes(tv);
    break;
  }
  default:            assert(false); d = 0.0; break;
  }
  tv->m_data.dbl = d;
  tv->m_type = KindOfDouble;
}
Beispiel #5
0
double tvCastToDouble(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  if (tv->m_type == KindOfRef) {
    tv = tv->m_data.pref->tv();
  }

  switch(tv->m_type) {
  case KindOfUninit:
  case KindOfNull:
    return 0;
  case KindOfBoolean:
    assert(tv->m_data.num == 0LL || tv->m_data.num == 1LL);
    // Fall through
  case KindOfInt64:
    return (double)(tv->m_data.num);
  case KindOfDouble:
    return tv->m_data.dbl;
  case KindOfStaticString:
  case KindOfString:
    return tv->m_data.pstr->toDouble();
  case KindOfArray:
    return tv->m_data.parr->empty() ? 0.0 : 1.0;
  case KindOfObject:
    return tv->m_data.pobj->o_toDouble();
  case KindOfResource:
    return tv->m_data.pres->o_toDouble();
  default:
    not_reached();
  }
}
void checkFrame(ActRec* fp, Cell* sp, bool checkLocals) {
  const Func* func = fp->m_func;
  func->validate();
  if (func->cls()) {
    assert(!func->cls()->isZombie());
  }
  if (fp->hasVarEnv()) {
    assert(fp->getVarEnv()->getCfp() == fp);
  }
  // TODO: validate this pointer from actrec
  int numLocals = func->numLocals();
  assert(sp <= (Cell*)fp - func->numSlotsInFrame()
         || func->isGenerator());
  if (checkLocals) {
    int numParams = func->numParams();
    for (int i=0; i < numLocals; i++) {
      if (i >= numParams && func->isGenerator() && i < func->numNamedLocals()) {
        continue;
      }
      assert(tvIsPlausible(*frame_local(fp, i)));
    }
  }
  // We unfortunately can't do the same kind of check for the stack
  // without knowing about FPI regions, because it may contain
  // ActRecs.
}
Beispiel #7
0
bool tvCoerceParamToArrayInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);

  switch (tv->m_type) {
    case KindOfUninit:
    case KindOfNull:
    case KindOfBoolean:
    case KindOfInt64:
    case KindOfDouble:
    case KindOfPersistentString:
    case KindOfString:
      return false;

    case KindOfPersistentArray:
    case KindOfArray:
      return true;

    case KindOfObject:
      if (LIKELY(tv->m_data.pobj->isCollection())) {
        tvAsVariant(tv) = tv->m_data.pobj->toArray();
        return true;
      }
      return false;
    case KindOfResource:
      return false;

    case KindOfRef:
    case KindOfClass:
      break;
  }
  not_reached();
}
Beispiel #8
0
bool tvCoerceParamToBooleanInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);

  switch (tv->m_type) {
    case KindOfUninit:
    case KindOfNull:
    case KindOfBoolean:
    case KindOfInt64:
    case KindOfDouble:
    case KindOfPersistentString:
    case KindOfString:
      // In PHP 7 mode handling of null types is stricter
      if (tv->m_type == KindOfNull && RuntimeOption::PHP7_ScalarTypes) {
        return false;
      }
      tvCastToBooleanInPlace(tv);
      return true;

    case KindOfPersistentArray:
    case KindOfArray:
    case KindOfObject:
    case KindOfResource:
      return false;

    case KindOfRef:
    case KindOfClass:
      break;
  }
  not_reached();
}
Beispiel #9
0
void tvCastToStringInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  StringData* s;

  do {
    switch (tv->m_type) {
      case KindOfUninit:
      case KindOfNull:
        s = staticEmptyString();
        goto static_string;

      case KindOfBoolean:
        s = tv->m_data.num ? s_1.get() : staticEmptyString();
        goto static_string;

      case KindOfInt64:
        s = buildStringData(tv->m_data.num);
        continue;

      case KindOfDouble:
        s = buildStringData(tv->m_data.dbl);
        continue;

      case KindOfStaticString:
      case KindOfString:
        return;

      case KindOfArray:
        raise_notice("Array to string conversion");
        s = array_string.get();
        tvDecRefArr(tv);
        goto static_string;

      case KindOfObject:
        // For objects, we fall back on the Variant machinery
        tvAsVariant(tv) = tv->m_data.pobj->invokeToString();
        return;

      case KindOfResource:
        // For resources, we fall back on the Variant machinery
        tvAsVariant(tv) = tv->m_data.pres->o_toString();
        return;

      case KindOfRef:
      case KindOfClass:
        break;
    }
    not_reached();
  } while (0);

  s->incRefCount();
  tv->m_data.pstr = s;
  tv->m_type = KindOfString;
  return;

static_string:
  tv->m_data.pstr = s;
  tv->m_type = KindOfStaticString;
}
Beispiel #10
0
void tvCastToBooleanInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  bool b;
  switch (tv->m_type) {
  case KindOfUninit:
  case KindOfNull:    b = false; break;
  case KindOfBoolean: return;
  case KindOfInt64:   b = (tv->m_data.num != 0LL); break;
  case KindOfDouble:  b = (tv->m_data.dbl != 0); break;
  case KindOfStaticString: b = tv->m_data.pstr->toBoolean(); break;
  case KindOfString:  b = tv->m_data.pstr->toBoolean(); tvDecRefStr(tv); break;
  // Note that this is intentionally incorrect for NameValueTableWrapper, for
  // which getSize() will always return -1, empty or not.
  case KindOfArray:   b = !!tv->m_data.parr->getSize();
                      tvDecRefArr(tv);
                      break;
  case KindOfObject:  b = tv->m_data.pobj->o_toBoolean();
                      tvDecRefObj(tv);
                      break;
  case KindOfResource: b = tv->m_data.pres->o_toBoolean();
                       tvDecRefRes(tv);
                       break;
  default:            assert(false); b = false; break;
  }
  tv->m_data.num = b;
  tv->m_type = KindOfBoolean;
}
Beispiel #11
0
StringData* tvCastToString(const TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  if (tv->m_type == KindOfRef) {
    tv = tv->m_data.pref->tv();
  }

  StringData* s;
  switch (tv->m_type) {
  case KindOfUninit:
  case KindOfNull:    return empty_string.get();
  case KindOfBoolean: return tv->m_data.num ? s_1.get() : empty_string.get();
  case KindOfInt64:   s = buildStringData(tv->m_data.num); break;
  case KindOfDouble:  s = buildStringData(tv->m_data.dbl); break;
  case KindOfStaticString: return tv->m_data.pstr;
  case KindOfString:  s = tv->m_data.pstr; break;
  case KindOfArray:   raise_notice("Array to string conversion");
                      return array_string.get();
  case KindOfObject:  return tv->m_data.pobj->invokeToString().detach();
  case KindOfResource: return tv->m_data.pres->o_toString().detach();
  default:            not_reached();
  }

  s->incRefCount();
  return s;
}
Beispiel #12
0
void tvCastToDoubleInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  double d;

  do {
    switch (tv->m_type) {
      case KindOfUninit:
      case KindOfNull:
        d = 0.0;
        continue;

      case KindOfBoolean:
        assert(tv->m_data.num == 0LL || tv->m_data.num == 1LL);
        // fallthru
      case KindOfInt64:
        d = (double)(tv->m_data.num);
        continue;

      case KindOfDouble:
        return;

      case KindOfPersistentString:
        d = tv->m_data.pstr->toDouble();
        continue;

      case KindOfString:
        d = tv->m_data.pstr->toDouble();
        tvDecRefStr(tv);
        continue;

      case KindOfPersistentArray:
        d = tv->m_data.parr->empty() ? 0 : 1;
        continue;

      case KindOfArray:
        d = tv->m_data.parr->empty() ? 0 : 1;
        tvDecRefArr(tv);
        continue;

      case KindOfObject:
        d = tv->m_data.pobj->toDouble();
        tvDecRefObj(tv);
        continue;

      case KindOfResource:
        d = tv->m_data.pres->data()->o_toDouble();
        tvDecRefRes(tv);
        continue;

      case KindOfRef:
      case KindOfClass:
        break;
    }
    not_reached();
  } while (0);

  tv->m_data.dbl = d;
  tv->m_type = KindOfDouble;
}
Beispiel #13
0
Type typeFromTV(const TypedValue* tv) {
  assertx(tv->m_type == KindOfClass || tvIsPlausible(*tv));

  if (tv->m_type == KindOfObject) {
    auto const cls = tv->m_data.pobj->getVMClass();

    // We only allow specialization on classes that can't be overridden for
    // now.  If this changes, then this will need to specialize on sub object
    // types instead.
    if (!cls || !(cls->attrs() & AttrNoOverride)) return TObj;
    return Type::ExactObj(cls);
  }

  if (isArrayType(tv->m_type)) {
    auto const ar = tv->m_data.parr;
    if (ar->kind() == ArrayData::kStructKind) {
      return Type::Array(StructArray::asStructArray(ar)->shape());
    }
    return Type::Array(tv->m_data.parr->kind());
  }

  auto outer = tv->m_type;
  auto inner = KindOfUninit;

  if (outer == KindOfPersistentString) outer = KindOfString;
  if (outer == KindOfRef) {
    inner = tv->m_data.pref->tv()->m_type;
    if (inner == KindOfPersistentString) inner = KindOfString;
    else if (inner == KindOfPersistentArray) inner = KindOfArray;
  }
  return Type(outer, inner);
}
Beispiel #14
0
bool tvCoerceParamToArrayInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);

  switch (tv->m_type) {
    DT_UNCOUNTED_CASE:
    case KindOfString:
      return false;

    case KindOfArray:
      return true;

    case KindOfObject:
      if (LIKELY(tv->m_data.pobj->isCollection())) {
        tvAsVariant(tv) = tv->m_data.pobj->toArray();
        return true;
      }
      return false;
    case KindOfResource:
      return false;

    case KindOfRef:
    case KindOfClass:
      break;
  }
  not_reached();
}
Beispiel #15
0
void tvCastToResourceInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);

  do {
    switch (tv->m_type) {
      DT_UNCOUNTED_CASE:
        continue;
      case KindOfString:
      case KindOfArray:
      case KindOfObject:
        tvDecRef(tv);
        continue;
      case KindOfResource:
        // no op, return
        return;
      case KindOfRef:
      case KindOfClass:
        break;
    }
    not_reached();
  } while (0);

  tv->m_type = KindOfResource;
  tv->m_data.pres = newres<DummyResource>();
}
Beispiel #16
0
void tvCastToArrayInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  ArrayData* a;

  do {
    switch (tv->m_type) {
      case KindOfUninit:
      case KindOfNull:
        a = ArrayData::Create();
        continue;

      case KindOfBoolean:
      case KindOfInt64:
      case KindOfDouble:
      case KindOfPersistentString:
        a = ArrayData::Create(tvAsVariant(tv));
        continue;

      case KindOfString:
        a = ArrayData::Create(tvAsVariant(tv));
        tvDecRefStr(tv);
        continue;

      case KindOfPersistentArray:
      case KindOfArray: {
        ArrayData* adIn = tv->m_data.parr;
        if (adIn->isVecArray()) {
          tv->m_data.parr = PackedArray::MakeFromVec(adIn, adIn->cowCheck());
          tv->m_type = KindOfArray;
        } else if (adIn->isDict()) {
          tv->m_data.parr = MixedArray::MakeFromDict(adIn, adIn->cowCheck());
          tv->m_type = KindOfArray;
        }
        return;
      }

      case KindOfObject:
        // For objects, we fall back on the Variant machinery
        tvAsVariant(tv) = tv->m_data.pobj->toArray();
        return;

      case KindOfResource:
        a = ArrayData::Create(tvAsVariant(tv));
        tvDecRefRes(tv);
        continue;

      case KindOfRef:
      case KindOfClass:
        break;
    }
    not_reached();
  } while (0);

  assert(!a->isRefCounted() || a->hasExactlyOneRef());

  tv->m_data.parr = a;
  tv->m_type = KindOfArray;
}
Beispiel #17
0
void tvCastToBooleanInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  bool b;

  do {
    switch (tv->m_type) {
      case KindOfUninit:
      case KindOfNull:
        b = false;
        continue;

      case KindOfBoolean:
        return;

      case KindOfInt64:
        b = (tv->m_data.num != 0LL);
        continue;

      case KindOfDouble:
        b = (tv->m_data.dbl != 0);
        continue;

      case KindOfStaticString:
        b = tv->m_data.pstr->toBoolean();
        continue;

      case KindOfString:
        b = tv->m_data.pstr->toBoolean();
        tvDecRefStr(tv);
        continue;

      case KindOfArray:
        b = !!tv->m_data.parr->size();
        tvDecRefArr(tv);
        continue;

      case KindOfObject:
        b = tv->m_data.pobj->toBoolean();
        tvDecRefObj(tv);
        continue;

      case KindOfResource:
        b = tv->m_data.pres->o_toBoolean();
        tvDecRefRes(tv);
        continue;

      case KindOfRef:
      case KindOfClass:
        break;
    }
    not_reached();
  } while (0);

  tv->m_data.num = b;
  tv->m_type = KindOfBoolean;
}
Beispiel #18
0
bool tvCoerceParamToDoubleInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  if (!tvCanBeCoercedToNumber(tv)) {
    return false;
  }
  tvCastToDoubleInPlace(tv);
  return true;
}
Beispiel #19
0
bool tvCoerceParamToBooleanInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  if (tv->m_type == KindOfArray || tv->m_type == KindOfObject ||
      tv->m_type == KindOfResource) {
    return false;
  }
  tvCastToBooleanInPlace(tv);
  return true;
}
Beispiel #20
0
bool tvCoerceParamToNullableObjectInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  if (IS_NULL_TYPE(tv->m_type)) {
    // See comment in tvCastToNullableObjectInPlace
    tv->m_data.pobj = nullptr;
    return true;
  }
  return tv->m_type == KindOfObject;
}
Beispiel #21
0
void tvCastToObjectInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  ObjectData* o;

  do {
    switch (tv->m_type) {
      case KindOfUninit:
      case KindOfNull:
        o = SystemLib::AllocStdClassObject().detach();
        continue;

      case KindOfBoolean:
      case KindOfInt64:
      case KindOfDouble:
      case KindOfPersistentString:
      case KindOfResource:
        o = SystemLib::AllocStdClassObject().detach();
        o->o_set(s_scalar, tvAsVariant(tv));
        continue;

      case KindOfString:
        o = SystemLib::AllocStdClassObject().detach();
        o->o_set(s_scalar, tvAsVariant(tv));
        tvDecRefStr(tv);
        continue;

      case KindOfPersistentVec:
      case KindOfVec:
      case KindOfPersistentDict:
      case KindOfDict:
      case KindOfPersistentKeyset:
      case KindOfKeyset:
        tvCastToArrayInPlace(tv);
        // Fall-through to array case
      case KindOfPersistentArray:
      case KindOfArray:
        // For arrays, we fall back on the Variant machinery
        tvAsVariant(tv) = ObjectData::FromArray(tv->m_data.parr);
        return;

      case KindOfObject:
        return;

      case KindOfRef:
      case KindOfClass:
        break;
    }
    not_reached();
  } while (0);

  tv->m_data.pobj = o;
  tv->m_type = KindOfObject;
  assert(cellIsPlausible(*tv));
}
Beispiel #22
0
void NameValueTable::rehash(Elm* const oldTab, const size_t oldMask) {
  for (Elm* srcElm = &oldTab[oldMask]; srcElm != &oldTab[-1]; --srcElm) {
    if (srcElm->m_name) {
      assert(srcElm->m_tv.m_type == KindOfNamedLocal ||
             tvIsPlausible(srcElm->m_tv));
      Elm* dstElm = insertImpl(srcElm->m_name);
      dstElm->m_name = srcElm->m_name;
      dstElm->m_tv = srcElm->m_tv;
    }
  }
}
Beispiel #23
0
void tvCastToStringInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);

  auto string = [&](StringData* s) {
    tv->m_type = KindOfString;
    tv->m_data.pstr = s;
  };
  auto persistentString = [&](StringData* s) {
    assert(!s->isRefCounted());
    tv->m_type = KindOfPersistentString;
    tv->m_data.pstr = s;
  };

  switch (tv->m_type) {
    case KindOfUninit:
    case KindOfNull:
      return persistentString(staticEmptyString());

    case KindOfBoolean:
      return persistentString(tv->m_data.num ? s_1.get() : staticEmptyString());

    case KindOfInt64:
      return string(buildStringData(tv->m_data.num));

    case KindOfDouble:
      return string(buildStringData(tv->m_data.dbl));

    case KindOfPersistentString:
    case KindOfString:
      return;

    case KindOfArray:
    case KindOfPersistentArray:
      raise_notice("Array to string conversion");
      if (tv->m_type == KindOfArray) tvDecRefArr(tv);
      return persistentString(array_string.get());

    case KindOfObject:
      // For objects, we fall back on the Variant machinery
      tvAsVariant(tv) = tv->m_data.pobj->invokeToString();
      return;

    case KindOfResource:
      // For resources, we fall back on the Variant machinery
      tvAsVariant(tv) = tv->m_data.pres->data()->o_toString();
      return;

    case KindOfRef:
    case KindOfClass:
      break;
  }
  not_reached();
}
Beispiel #24
0
bool tvCoerceParamToArrayInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  if (tv->m_type == KindOfArray) {
    return true;
  } else if (tv->m_type == KindOfObject) {
    tvAsVariant(tv) = tv->m_data.pobj->o_toArray();
    return true;
  } else if (tv->m_type == KindOfResource) {
    tvAsVariant(tv) = tv->m_data.pres->o_toArray();
    return true;
  }
  return false;
}
Beispiel #25
0
void tvCastToArrayInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  ArrayData* a;

  do {
    switch (tv->m_type) {
      case KindOfUninit:
      case KindOfNull:
        a = ArrayData::Create();
        continue;

      case KindOfBoolean:
      case KindOfInt64:
      case KindOfDouble:
      case KindOfStaticString:
        a = ArrayData::Create(tvAsVariant(tv));
        continue;

      case KindOfString:
        a = ArrayData::Create(tvAsVariant(tv));
        tvDecRefStr(tv);
        continue;

      case KindOfArray:
        return;

      case KindOfObject:
        // For objects, we fall back on the Variant machinery
        tvAsVariant(tv) = tv->m_data.pobj->toArray();
        return;

      case KindOfResource:
        a = ArrayData::Create(tvAsVariant(tv));
        tvDecRefRes(tv);
        continue;

      case KindOfRef:
      case KindOfClass:
        break;
    }
    not_reached();
  } while (0);

  assert(a->isStatic() || a->hasExactlyOneRef());

  tv->m_data.parr = a;
  tv->m_type = KindOfArray;
}
Beispiel #26
0
bool tvCoerceParamToInt64InPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  if (!tvCanBeCoercedToNumber(tv)) {
    return false;
  }
  // In PHP 7 mode doubles only convert to integers when the conversion is non-
  // narrowing
  if (RuntimeOption::PHP7_ScalarTypes && tv->m_type == KindOfDouble) {
    if (tv->m_data.dbl < std::numeric_limits<int64_t>::min()) return false;
    if (tv->m_data.dbl > std::numeric_limits<int64_t>::max()) return false;
    if (std::isnan(tv->m_data.dbl)) return false;
  }
  tvCastToInt64InPlace(tv);
  return true;
}
Beispiel #27
0
double tvCastToDouble(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  if (tv->m_type == KindOfRef) {
    tv = tv->m_data.pref->tv();
  }

  switch (tv->m_type) {
    case KindOfUninit:
    case KindOfNull:
      return 0;

    case KindOfBoolean:
      assert(tv->m_data.num == 0LL || tv->m_data.num == 1LL);
      // fallthru
    case KindOfInt64:
      return (double)(tv->m_data.num);

    case KindOfDouble:
      return tv->m_data.dbl;

    case KindOfPersistentString:
    case KindOfString:
      return tv->m_data.pstr->toDouble();

    case KindOfPersistentVec:
    case KindOfVec:
    case KindOfPersistentDict:
    case KindOfDict:
    case KindOfPersistentKeyset:
    case KindOfKeyset:
    case KindOfPersistentArray:
    case KindOfArray:
      return tv->m_data.parr->empty() ? 0.0 : 1.0;

    case KindOfObject:
      return tv->m_data.pobj->toDouble();

    case KindOfResource:
      return tv->m_data.pres->data()->o_toDouble();

    case KindOfRef:
    case KindOfClass:
      break;
  }
  not_reached();
}
Beispiel #28
0
StringData* tvCastToString(const TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  if (tv->m_type == KindOfRef) {
    tv = tv->m_data.pref->tv();
  }

  switch (tv->m_type) {
    case KindOfUninit:
    case KindOfNull:
      return staticEmptyString();

    case KindOfBoolean:
      return tv->m_data.num ? s_1.get() : staticEmptyString();

    case KindOfInt64:
      return buildStringData(tv->m_data.num);

    case KindOfDouble:
      return buildStringData(tv->m_data.dbl);

    case KindOfPersistentString:
      return tv->m_data.pstr;

    case KindOfString: {
      auto s = tv->m_data.pstr;
      s->incRefCount();
      return s;
    }

    case KindOfPersistentArray:
    case KindOfArray:
      raise_notice("Array to string conversion");
      return array_string.get();

    case KindOfObject:
      return tv->m_data.pobj->invokeToString().detach();

    case KindOfResource:
      return tv->m_data.pres->data()->o_toString().detach();

    case KindOfRef:
    case KindOfClass:
      not_reached();
  }
  not_reached();
}
Beispiel #29
0
bool tvCoerceParamToStringInPlace(TypedValue* tv) {
  assert(tvIsPlausible(*tv));
  tvUnboxIfNeeded(tv);
  switch (tv->m_type) {
  case KindOfArray:
    return false;
  case KindOfObject:
    if (tv->m_data.pobj->hasToString()) {
      tvAsVariant(tv) = tv->m_data.pobj->invokeToString();
      return true;
    }
    return false;
  case KindOfResource:
    return false;
  default:
    break;
  }
  tvCastToStringInPlace(tv);
  return true;
}
Beispiel #30
0
bool PackedArray::checkInvariants(const ArrayData* arr) {
  assert(arr->isPacked());
  assert(arr->m_packedCap < kMaxPackedCap);
  assert(arr->m_size <= arr->m_packedCap);
  static_assert(ArrayData::kPackedKind == 0, "");
  // Note that m_pos < m_size is not an invariant, because an array
  // that grows will only adjust m_size to zero on the old array.

  // This loop is too slow for normal use, but can be enabled to debug
  // packed arrays.
  if (false) {
    auto ptr = reinterpret_cast<const TypedValue*>(arr + 1);
    auto const stop = ptr + arr->m_size;
    for (; ptr != stop; ptr++) {
      assert(ptr->m_type != KindOfUninit);
      assert(tvIsPlausible(*ptr));
    }
  }
  return true;
}