Object HHVM_STATIC_METHOD(AwaitAllWaitHandle, fromArray,
                          const Array& dependencies) {
  auto ad = dependencies.get();
  assertx(ad);
  assertx(ad->isPHPArray());
  if (!ad->size()) return Object{returnEmpty()};

retry:
  switch (ad->kind()) {
    case ArrayData::kPackedKind:
      return c_AwaitAllWaitHandle::Create<true>([=](auto fn) {
        PackedArray::IterateV(ad, fn);
      });

    case ArrayData::kMixedKind:
      return c_AwaitAllWaitHandle::Create<true>([=](auto fn) {
        MixedArray::IterateV(MixedArray::asMixed(ad), fn);
      });

    case ArrayData::kProxyKind:
      ad = ProxyArray::innerArr(ad);
      goto retry;

    case ArrayData::kApcKind:
    case ArrayData::kGlobalsKind:
      // APC can't store WaitHandles, GlobalsArray is used only for
      // $GLOBALS, which contain non-WaitHandles.
      failArray();

    case ArrayData::kEmptyKind:
      // Handled by dependencies->size() check.
      not_reached();

    case ArrayData::kVecKind:
    case ArrayData::kDictKind:
    case ArrayData::kKeysetKind:
      // Shouldn't get Hack arrays
      not_reached();

    case ArrayData::kNumKinds:
      not_reached();
  }

  not_reached();
}
Exemple #2
0
APCHandle::Pair APCHandle::Create(const Variant& source,
                                  bool serialized,
                                  APCHandleLevel level,
                                  bool unserializeObj) {

  auto type = source.getType(); // this gets rid of the ref, if it was one
  switch (type) {
    case KindOfUninit: {
      auto value = APCTypedValue::tvUninit();
      return {value->getHandle(), sizeof(APCTypedValue)};
    }
    case KindOfNull: {
      auto value = APCTypedValue::tvNull();
      return {value->getHandle(), sizeof(APCTypedValue)};
    }
    case KindOfBoolean: {
      auto value = source.getBoolean() ? APCTypedValue::tvTrue()
                                       : APCTypedValue::tvFalse();
      return {value->getHandle(), sizeof(APCTypedValue)};
    }
    case KindOfInt64: {
      auto value = new APCTypedValue(source.getInt64());
      return {value->getHandle(), sizeof(APCTypedValue)};
    }
    case KindOfDouble: {
      auto value = new APCTypedValue(source.getDouble());
      return {value->getHandle(), sizeof(APCTypedValue)};
    }
    case KindOfPersistentString:
    case KindOfString: {
      StringData* s = source.getStringData();
      if (serialized) {
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        return APCString::MakeSerializedObject(apc_reserialize(String{s}));
      }
      if (s->isStatic()) {
        auto value = new APCTypedValue(APCTypedValue::StaticStr{}, s);
        return APCHandle::Pair{value->getHandle(), sizeof(APCTypedValue)};
      }
      auto const st = lookupStaticString(s);
      if (st) {
        auto value = new APCTypedValue(APCTypedValue::StaticStr{}, st);
        return {value->getHandle(), sizeof(APCTypedValue)};
      }
      if (apcExtension::UseUncounted) {
        auto st = StringData::MakeUncounted(s->slice());
        auto value = new APCTypedValue(APCTypedValue::UncountedStr{}, st);
        return {value->getHandle(), st->size() + sizeof(APCTypedValue)};
      }
      return APCString::MakeSharedString(s);
    }

    case KindOfPersistentVec:
    case KindOfVec: {
      auto ad = source.getArrayData();
      assert(ad->isVecArray());
      if (ad->isStatic()) {
        auto value = new APCTypedValue(APCTypedValue::StaticVec{}, ad);
        return {value->getHandle(), sizeof(APCTypedValue)};
      }

      return APCArray::MakeSharedVec(ad, level, unserializeObj);
    }

    case KindOfPersistentDict:
    case KindOfDict: {
      auto ad = source.getArrayData();
      assert(ad->isDict());
      if (ad->isStatic()) {
        auto value = new APCTypedValue(APCTypedValue::StaticDict{}, ad);
        return {value->getHandle(), sizeof(APCTypedValue)};
      }

      return APCArray::MakeSharedDict(ad, level, unserializeObj);
    }

    case KindOfPersistentKeyset:
    case KindOfKeyset: {
      auto ad = source.getArrayData();
      assert(ad->isKeyset());
      if (ad->isStatic()) {
        auto value = new APCTypedValue(APCTypedValue::StaticKeyset{}, ad);
        return {value->getHandle(), sizeof(APCTypedValue)};
      }

      return APCArray::MakeSharedKeyset(ad, level, unserializeObj);
    }

    case KindOfPersistentArray:
    case KindOfArray: {
      auto ad = source.getArrayData();
      assert(ad->isPHPArray());
      if (ad->isStatic()) {
        auto value = new APCTypedValue(APCTypedValue::StaticArr{}, ad);
        return {value->getHandle(), sizeof(APCTypedValue)};
      }

      return APCArray::MakeSharedArray(ad, level, unserializeObj);
    }

    case KindOfObject:
      if (source.getObjectData()->isCollection()) {
        return APCCollection::Make(source.getObjectData(),
                                   level,
                                   unserializeObj);
      }
      return unserializeObj ? APCObject::Construct(source.getObjectData()) :
             APCString::MakeSerializedObject(apc_serialize(source));

    case KindOfResource:
      // TODO Task #2661075: Here and elsewhere in the runtime, we convert
      // Resources to the empty array during various serialization operations,
      // which does not match Zend behavior. We should fix this.
      return APCArray::MakeSharedEmptyArray();

    case KindOfRef:
    case KindOfClass:
      return {nullptr, 0};
  }
  not_reached();
}
Exemple #3
0
Variant APCHandle::toLocal() const {
  switch (m_kind) {
    case APCKind::Uninit:
    case APCKind::Null:
      return init_null(); // shortcut.. no point to forward
    case APCKind::Bool:
      return APCTypedValue::fromHandle(this)->getBoolean();
    case APCKind::Int:
      return APCTypedValue::fromHandle(this)->getInt64();
    case APCKind::Double:
      return APCTypedValue::fromHandle(this)->getDouble();
    case APCKind::StaticString:
    case APCKind::UncountedString:
      return Variant{APCTypedValue::fromHandle(this)->getStringData(),
                     Variant::PersistentStrInit{}};
    case APCKind::SharedString:
      return Variant::attach(
        StringData::MakeProxy(APCString::fromHandle(this))
      );
    case APCKind::StaticArray:
    case APCKind::UncountedArray:
      return Variant{APCTypedValue::fromHandle(this)->getArrayData(),
                     KindOfPersistentArray,
                     Variant::PersistentArrInit{}};
    case APCKind::StaticVec:
    case APCKind::UncountedVec:
      return Variant{APCTypedValue::fromHandle(this)->getVecData(),
                     KindOfPersistentVec,
                     Variant::PersistentArrInit{}};
    case APCKind::StaticDict:
    case APCKind::UncountedDict:
      return Variant{APCTypedValue::fromHandle(this)->getDictData(),
                     KindOfPersistentDict,
                     Variant::PersistentArrInit{}};
    case APCKind::StaticKeyset:
    case APCKind::UncountedKeyset:
      return Variant{APCTypedValue::fromHandle(this)->getKeysetData(),
                     KindOfPersistentKeyset,
                     Variant::PersistentArrInit{}};
    case APCKind::SerializedArray: {
      auto const serArr = APCString::fromHandle(this)->getStringData();
      auto const v = apc_unserialize(serArr->data(), serArr->size());
      assert(v.isPHPArray());
      return v;
    }
    case APCKind::SerializedVec: {
      auto const serVec = APCString::fromHandle(this)->getStringData();
      auto const v = apc_unserialize(serVec->data(), serVec->size());
      assert(v.isVecArray());
      return v;
    }
    case APCKind::SerializedDict: {
      auto const serDict = APCString::fromHandle(this)->getStringData();
      auto const v = apc_unserialize(serDict->data(), serDict->size());
      assert(v.isDict());
      return v;
    }
    case APCKind::SerializedKeyset: {
      auto const serKeyset = APCString::fromHandle(this)->getStringData();
      auto const v = apc_unserialize(serKeyset->data(), serKeyset->size());
      assert(v.isKeyset());
      return v;
    }
    case APCKind::SharedArray:
    case APCKind::SharedPackedArray:
      return Variant::attach(
        APCLocalArray::Make(APCArray::fromHandle(this))->asArrayData()
      );
    case APCKind::SharedVec:
      return Variant::attach(
        APCArray::fromHandle(this)->toLocalVec()
      );
    case APCKind::SharedDict:
      return Variant::attach(
        APCArray::fromHandle(this)->toLocalDict()
      );
    case APCKind::SharedKeyset:
      return Variant::attach(
        APCArray::fromHandle(this)->toLocalKeyset()
      );
    case APCKind::SerializedObject: {
      auto const serObj = APCString::fromHandle(this)->getStringData();
      return apc_unserialize(serObj->data(), serObj->size());
    }
    case APCKind::SharedCollection:
      return APCCollection::fromHandle(this)->createObject();
    case APCKind::SharedObject:
      return APCObject::MakeLocalObject(this);
  }
  not_reached();
}