// TODO zPrepArgs needs to be updated so take care of // boxing varargs void zPrepArgs(ActRec* ar) { // If you call a function with too few params, zend_parse_parameters will // reject it, but we don't want this function boxing random slots from the // stack int32_t numArgs = std::min(ar->numArgs(), ar->m_func->numParams()); TypedValue* args = (TypedValue*)ar - 1; for (int32_t i = 0; i < numArgs; ++i) { TypedValue* arg = args-i; zBoxAndProxy(arg); } }
void * ProxyArray::elementToData(TypedValue * tv) const { if (!tv) { return nullptr; } if (hasZvalValues()) { zBoxAndProxy(tv); return (void*)(&tv->m_data.pref); } else { always_assert(tv->m_type == KindOfResource); ZendCustomElement * elt = dynamic_cast<ZendCustomElement*>(tv->m_data.pres); always_assert(elt); return elt->data(); } }
zval* ZendExecutionStack::getArg(int i) { auto& stack = getStack(); auto& entry = stack.m_stack.back(); switch (entry.mode) { case ZendStackMode::HHVM_STACK: { ActRec* ar = (ActRec*)entry.value; const int numNonVaradic = ar->m_func->numNonVariadicParams(); TypedValue* arg; if (i < numNonVaradic) { arg = (TypedValue*)ar - i - 1; } else if (i < ar->numArgs()) { arg = ar->getExtraArg(i - numNonVaradic); } else { if (!stack.m_nullArg) { stack.m_nullArg = RefData::Make(make_tv<KindOfNull>()); } return stack.m_nullArg; } zBoxAndProxy(arg); return arg->m_data.pref; } case ZendStackMode::SIDE_STACK: { // Zend puts the number of args as the last thing on the stack int numargs = uintptr_t(entry.value); assert(numargs < 4096); assert(i < numargs); zval* zv = (zval*) stack.m_stack[stack.m_stack.size() - 1 - numargs + i].value; zv->assertValid(); return zv; } } not_reached(); return nullptr; }