Array hhvm_get_frame_args(const ActRec* ar) { if (ar == NULL) { return Array(); } HPHP::VM::ExtraArgs* eArgs = ar->getExtraArgs(); int numParams = ar->m_func->numParams(); int numArgs = ar->numArgs(); HphpArray* retval = NEW(HphpArray)(numArgs); TypedValue* local = (TypedValue*)(uintptr_t(ar) - sizeof(TypedValue)); for (int i = 0; i < numArgs; ++i) { if (i < numParams) { // This corresponds to one of the function's formal parameters, so it's // on the stack. retval->nvAppend(local, false); --local; } else { // This is not a formal parameter, so it's in the ExtraArgs. ASSERT(eArgs); ASSERT(i - numParams < (int)eArgs->numExtraArgs()); retval->nvAppend(eArgs->getExtraArg(i - numParams), false); } } return Array(retval); }
RefData* staticLocInitImpl(StringData* name, ActRec* fp, TypedValue val, TargetCache::CacheHandle ch) { assert(useTargetCache == (bool)ch); HphpArray* map; if (useTargetCache) { // If we have a cache handle, we know the current func isn't a // closure or generator closure so we can directly grab its static // locals map. const Func* func = fp->m_func; assert(!(func->isClosureBody() || func->isGeneratorFromClosure())); map = func->getStaticLocals(); } else { map = get_static_locals(fp); } TypedValue *mapVal = map->nvGet(name); if (!mapVal) { map->set(name, tvAsCVarRef(&val), false); mapVal = map->nvGet(name); } if (mapVal->m_type != KindOfRef) { tvBox(mapVal); } assert(mapVal->m_type == KindOfRef); RefData* ret = mapVal->m_data.pref; if (useTargetCache) { *TargetCache::handleToPtr<RefData*>(ch) = ret; } ret->incRefCount(); return ret; }
bool run_intercept_handler_for_invokefunc(TypedValue* retval, const Func* f, CArrRef params, ObjectData* this_, StringData* invName, Variant* ihandler) { using namespace HPHP::VM::Transl; ASSERT(ihandler); ASSERT(retval); Variant doneFlag = true; Array args = params; if (invName) { // This is a magic call, so we need to shuffle the args HphpArray* magicArgs = NEW(HphpArray)(2); magicArgs->append(invName, false); magicArgs->append(params, false); args = magicArgs; } Array intArgs = CREATE_VECTOR5(f->fullNameRef(), (this_ ? Variant(Object(this_)) : null), args, ihandler->asCArrRef()[1], ref(doneFlag)); call_intercept_handler<false>(retval, intArgs, NULL, ihandler); // $done is true, meaning don't enter the intercepted function. return !doneFlag.toBoolean(); }
HOT_FUNC int64 new_iter_array(Iter* dest, ArrayData* ad, TypedValue* valOut) { TRACE(2, "%s: I %p, ad %p\n", __func__, dest, ad); valOut = tvToCell(valOut); if (UNLIKELY(!IsHphpArray(ad))) { goto cold; } { HphpArray* arr = (HphpArray*)ad; if (LIKELY(arr->getSize() != 0)) { if (UNLIKELY(tvWillBeReleased(valOut))) { goto cold; } tvDecRefOnly(valOut); // We are transferring ownership of the array to the iterator, therefore // we do not need to adjust the refcount. (void) new (&dest->arr()) ArrayIter(arr, ArrayIter::noIncNonNull); dest->m_itype = Iter::TypeArray; HphpArray::Elm* elm = arr->getElm(dest->arr().m_pos); getHphpArrayElm(elm, valOut, NULL); return 1LL; } // We did not transfer ownership of the array to an iterator, so we need // to decRef the array. if (UNLIKELY(arr->getCount() == 1)) { goto cold; } arr->decRefCount(); return 0LL; } cold: return new_iter_array_cold(dest, ad, valOut, NULL); }
Array vm_get_class_vars(CStrRef className) { HPHP::VM::Class* cls = HPHP::VM::Unit::lookupClass(className.get()); if (cls == NULL) { raise_error("Unknown class %s", className->data()); } cls->initialize(); const VM::Class::SProp* sPropInfo = cls->staticProperties(); const size_t numSProps = cls->numStaticProperties(); const VM::Class::Prop* propInfo = cls->declProperties(); const size_t numDeclProps = cls->numDeclProperties(); // The class' instance property initialization template is in different // places, depending on whether it has any request-dependent initializers // (i.e. constants) const VM::Class::PropInitVec& declPropInitVec = cls->declPropInit(); const VM::Class::PropInitVec* propVals = !cls->pinitVec().empty() ? cls->getPropData() : &declPropInitVec; ASSERT(propVals != NULL); ASSERT(propVals->size() == numDeclProps); // For visibility checks CallerFrame cf; HPHP::VM::Class* ctx = arGetContextClass(cf()); const ClassInfo* ctxCI = (ctx == NULL ? NULL : g_vmContext->findClassInfo(CStrRef(ctx->nameRef()))); ClassInfo::PropertyMap propMap; g_vmContext->findClassInfo(className)->getAllProperties(propMap); HphpArray* ret = NEW(HphpArray)(numDeclProps + numSProps); for (size_t i = 0; i < numDeclProps; ++i) { StringData* name = const_cast<StringData*>(propInfo[i].m_name); // Empty names are used for invisible/private parent properties; skip them if (name->size() == 0) continue; if (propMap[String(name)]->isVisible(ctxCI)) { const TypedValue* value = &((*propVals)[i]); ret->nvSet(name, value, false); } } for (size_t i = 0; i < numSProps; ++i) { bool vis, access; TypedValue* value = cls->getSProp(ctx, sPropInfo[i].m_name, vis, access); if (vis) { ret->nvSet(const_cast<StringData*>(sPropInfo[i].m_name), value, false); } } return ret; }
// static size_t MemoryProfile::getSizeOfArray(ArrayData *arr) { size_t size = getSizeOfPtr(arr); if (size == 0) { return 0; } if (arr->isHphpArray()) { // calculate extra size HphpArray *ha = static_cast<HphpArray *>(arr); size_t hashSize = ha->hashSize(); size_t maxElms = HphpArray::computeMaxElms(ha->m_tableMask); if (maxElms > HphpArray::SmallSize) { size += maxElms * sizeof(HphpArray::Elm) + hashSize * sizeof(int32_t); } } return size; }
// Returned array has refcount one! Caller must not incref. HphpArray* pack_args_into_array(ActRec* ar, int nargs) { HphpArray* argArray = HphpArray::MakeReserve(nargs); for (int i = 0; i < nargs; ++i) { TypedValue* tv = (TypedValue*)(ar) - (i+1); argArray->HphpArray::appendWithRef(tvAsCVarRef(tv), false); } if (!ar->hasInvName()) { // If this is not a magic call, we're done return argArray; } // This is a magic call, so we need to shuffle the args HphpArray* magicArgs = HphpArray::MakeReserve(2); magicArgs->append(ar->getInvName(), false); magicArgs->append(argArray, false); return magicArgs; }
static Array get_frame_args_with_ref(const ActRec* ar) { int numParams = ar->m_func->numParams(); int numArgs = ar->numArgs(); HphpArray* retval = ArrayData::Make(numArgs); TypedValue* local = (TypedValue*)(uintptr_t(ar) - sizeof(TypedValue)); for (int i = 0; i < numArgs; ++i) { if (i < numParams) { // This corresponds to one of the function's formal parameters, so it's // on the stack. retval->appendWithRef(tvAsCVarRef(local), false); --local; } else { // This is not a formal parameter, so it's in the ExtraArgs. retval->appendWithRef(tvAsCVarRef(ar->getExtraArg(i - numParams)), false); } } return Array(retval); }
HOT_FUNC void ArrayData::release() { if (isHphpArray()) { HphpArray* that = static_cast<HphpArray*>(this); that->release(); return; } if (isSharedMap()) { SharedMap* that = static_cast<SharedMap*>(this); that->release(); return; } if (isArrayShell()) { auto that = static_cast<ArrayShell*>(this); that->release(); return; } assert(m_kind == kNameValueTableWrapper); // NameValueTableWrapper: nop. }
Array vm_get_class_constants(CStrRef className) { HPHP::VM::Class* cls = HPHP::VM::Unit::lookupClass(className.get()); if (cls == NULL) { return NEW(HphpArray)(0); } size_t numConstants = cls->numConstants(); HphpArray* retVal = NEW(HphpArray)(numConstants); const VM::Class::Const* consts = cls->constants(); for (size_t i = 0; i < numConstants; i++) { // Note: hphpc doesn't include inherited constants in // get_class_constants(), so mimic that behavior if (consts[i].m_class == cls) { StringData* name = const_cast<StringData*>(consts[i].m_name); TypedValue* value = cls->clsCnsGet(consts[i].m_name); retVal->nvSet(name, value, false); } } return retVal; }
ArrayData* new_tuple(int n, const TypedValue* values) { HphpArray* a = NEW(HphpArray)(n, values); a->incRefCount(); TRACE(2, "newTupleHelper: size %d\n", n); return a; }