コード例 #1
0
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;
}
コード例 #2
0
ファイル: name-value-table.cpp プロジェクト: asvinours/hhvm
TypedValue* NameValueTable::bind(const StringData* name, TypedValue* val) {
  TypedValue* target = findTypedValue(name);
  if (val->m_type != KindOfRef) {
    tvBox(val);
  }
  tvBind(val, target);
  return target;
}
コード例 #3
0
ファイル: zend-wrap-func.cpp プロジェクト: 409033632/hhvm
void zBoxAndProxy(TypedValue* arg) {
  if (arg->m_type != KindOfRef) {
    tvBox(arg);
  }
  auto inner = arg->m_data.pref->tv();
  if (inner->m_type == KindOfArray) {
    inner->m_data.parr = ProxyArray::Make(inner->m_data.parr);
  }
}
コード例 #4
0
Object c_SetResultToRefWaitHandle::ti_create(CObjRef wait_handle, VRefParam ref) {
  TypedValue* var_or_cell = ref->asTypedValue();
  if (wait_handle.isNull()) {
    tvSetNull(*var_or_cell);
    return wait_handle;
  }

  if (!wait_handle.get()->getAttribute(ObjectData::IsWaitHandle)) {
    Object e(SystemLib::AllocInvalidArgumentExceptionObject(
        "Expected wait_handle to be an instance of WaitHandle or null"));
    throw e;
  }

  auto wh = static_cast<c_WaitHandle*>(wait_handle.get());

  // succeeded? set result to ref and give back succeeded wait handle
  if (wh->isSucceeded()) {
    tvSet(wh->getResult(), *var_or_cell);
    return wh;
  }

  // failed? reset ref and give back failed wait handle
  if (wh->isFailed()) {
    tvSetNull(*var_or_cell);
    return wh;
  }

  // it's still running so it must be WaitableWaitHandle
  auto child = static_cast<c_WaitableWaitHandle*>(wh);

  // import child into the current context, detect cross-context cycles
  auto session = AsioSession::Get();
  if (session->isInContext()) {
    child->enterContext(session->getCurrentContextIdx());
  }

  // make sure the reference is properly boxed so that we can store cell pointer
  if (UNLIKELY(var_or_cell->m_type != KindOfRef)) {
    tvBox(var_or_cell);
  }

  p_SetResultToRefWaitHandle my_wh = NEWOBJ(c_SetResultToRefWaitHandle)();
  my_wh->initialize(child, var_or_cell->m_data.pref);

  if (UNLIKELY(session->hasOnSetResultToRefCreateCallback())) {
    session->onSetResultToRefCreate(my_wh.get(), child);
  }

  return my_wh;
}
コード例 #5
0
ファイル: zend-wrap-func.cpp プロジェクト: AmineCherrai/hhvm
void zBoxAndProxy(TypedValue* arg) {
  if (arg->m_type != KindOfRef) {
    tvBox(arg);
  }
  auto inner = arg->m_data.pref->tv();
  if (inner->m_type == KindOfArray && !inner->m_data.parr->isProxyArray()) {
    ArrayData * inner_arr = inner->m_data.parr;
    if (inner_arr->isStatic() || inner_arr->hasMultipleRefs()) {
      ArrayData * tmp = inner_arr->copy();
      tmp->incRefCount();
      inner_arr->decRefAndRelease();
      inner_arr = tmp;
    }
    inner->m_data.parr = ProxyArray::Make(inner_arr);
  }
}
コード例 #6
0
Object c_SetResultToRefWaitHandle::ti_create(CObjRef wait_handle, VRefParam ref) {
  TypedValue* var_or_cell = ref->asTypedValue();
  if (wait_handle.isNull()) {
    tvSet(make_tv<KindOfNull>(), *var_or_cell);
    return wait_handle;
  }

  if (!wait_handle.get()->instanceof(c_WaitHandle::classof())) {
    Object e(SystemLib::AllocInvalidArgumentExceptionObject(
        "Expected wait_handle to be an instance of WaitHandle or null"));
    throw e;
  }

  c_WaitHandle* wh = static_cast<c_WaitHandle*>(wait_handle.get());

  // succeeded? set result to ref and give back succeeded wait handle
  if (wh->isSucceeded()) {
    tvSet(wh->getResult(), *var_or_cell);
    return wh;
  }

  // failed? reset ref and give back failed wait handle
  if (wh->isFailed()) {
    tvSet(make_tv<KindOfNull>(), *var_or_cell);
    return wh;
  }

  // it's still running so it must be WaitableWaitHandle
  c_WaitableWaitHandle* child_wh = static_cast<c_WaitableWaitHandle*>(wh);

  // make sure the reference is properly boxed so that we can store cell pointer
  if (UNLIKELY(var_or_cell->m_type != KindOfRef)) {
    tvBox(var_or_cell);
  }

  p_SetResultToRefWaitHandle my_wh = NEWOBJ(c_SetResultToRefWaitHandle)();
  my_wh->initialize(child_wh, var_or_cell->m_data.pref);

  AsioSession* session = AsioSession::Get();
  if (UNLIKELY(session->hasOnSetResultToRefCreateCallback())) {
    session->onSetResultToRefCreate(my_wh.get(), child_wh);
  }

  return my_wh;
}
コード例 #7
0
ファイル: zend-wrap-func.cpp プロジェクト: MatmaRex/hhvm
void zBoxAndProxy(TypedValue* arg) {
  if (arg->m_type != KindOfRef) {
    tvBox(arg);
  }
  auto inner = arg->m_data.pref->tv();
  assert(!isHackArrayType(inner->m_type));
  if (isArrayType(inner->m_type) && !inner->m_data.parr->isProxyArray()) {
    ArrayData * inner_arr = inner->m_data.parr;
    if (inner_arr->cowCheck()) {
      ArrayData * tmp = inner_arr->copy();
      if (inner_arr != tmp) {
        inner_arr->decRefAndRelease();
        inner_arr = tmp;
      }
    }
    inner->m_data.parr = ProxyArray::Make(inner_arr);
    inner->m_type = KindOfArray;
  }
}
コード例 #8
0
// Defined here so it can be inlined below.
RefData* lookupStaticFromClosure(ObjectData* closure,
                                 StringData* name,
                                 bool& inited) {
  assert(closure->instanceof(c_Closure::classof()));
  String str(StringData::Make(s_staticPrefix->slice(), name->slice()));
  auto const cls = closure->getVMClass();
  auto const slot = cls->lookupDeclProp(str.get());
  assert(slot != kInvalidSlot);
  auto const val = static_cast<c_Closure*>(closure)->getStaticVar(slot);

  if (val->m_type == KindOfUninit) {
    inited = false;
    val->m_type = KindOfNull;
    tvBox(val);
    return val->m_data.pref;
  }
  inited = true;
  assert(val->m_type == KindOfRef);
  return val->m_data.pref;
}
コード例 #9
0
ファイル: zend-wrap-func.cpp プロジェクト: MatmaRex/hhvm
TypedValue* zend_wrap_func(ActRec* ar) {
  // Sync the translator state.
  // We need to do this before a native function calls into a C library
  // compiled with -fomit-frame-pointer with the intention of having it call
  // back. Normal HHVM extensions have the luxury of only when such a thing
  // will be attempted, but we have no way to know in advance.
  VMRegAnchor _;

  TSRMLS_FETCH();
  zend_ext_func native_func = reinterpret_cast<zend_ext_func>(ar->func()->nativeFuncPtr());

  // Using Variant so exceptions will decref them
  Variant return_value_var(Variant::NullInit{});
  auto const return_value = return_value_var.asTypedValue();
  tvBox(return_value);

  Variant this_ptr_var(Variant::NullInit{});
  auto const this_ptr = this_ptr_var.asTypedValue();
  tvBox(this_ptr);

  if (ar->func()->cls() && ar->hasThis()) {
    tvWriteObject(
      ar->getThis(),
      this_ptr->m_data.pref->tv()
    );
  }

  auto *return_value_ptr = &return_value->m_data.pref;

  // Clear any stored exception
  zend_clear_exception(TSRMLS_C);

  // Invoke the PHP extension function/method
  ZendExecutionStack::pushHHVMStack((void*)ar);
  try {
    native_func(
      ar->numArgs(),
      return_value->m_data.pref,
      return_value_ptr,
      this_ptr_var.isNull() ? nullptr : this_ptr->m_data.pref,
      1
      TSRMLS_CC
    );
  } catch (...) {
    zend_wrap_func_cleanup();
    throw;
  }
  zend_wrap_func_cleanup();

  // If an exception was caught, rethrow it
  ZendExceptionStore& exceptionStore = ZendExceptionStore::getInstance();
  if (!exceptionStore.empty()) {
    exceptionStore.rethrow();
  }

  // Take care of freeing the args, tearing down the ActRec, and moving the
  // return value to the right place.  Note that frame_free_locals expects to
  // be able to free return_value in the event of an exception, so we have to
  // take it out of our Variant /before/ calling that.
  TypedValue return_value_copy = *return_value;
  return_value->m_type = KindOfNull; // clear the Variant's copy
  frame_free_locals_inl(ar, ar->func()->numLocals(), &return_value_copy);
  memcpy(&ar->m_r, &return_value_copy, sizeof(TypedValue));
  if (ar->func()->isReturnRef()) {
    if (!ar->m_r.m_data.pref->isReferenced()) {
      tvUnbox(&ar->m_r);
    }
  } else {
    tvUnbox(&ar->m_r);
  }

  return &ar->m_r;
}
コード例 #10
0
ファイル: zend-wrap-func.cpp プロジェクト: 409033632/hhvm
TypedValue* zend_wrap_func(
    ActRec* ar,
    zend_ext_func builtin_func,
    int numParams,
    bool isReturnRef) {
  TSRMLS_FETCH();

  // Prepare the arguments and return value before they are
  // exposed to the PHP extension
  zPrepArgs(ar);

  // Using Variant so exceptions will decref them
  Variant return_value_var(Variant::NullInit{});
  auto const return_value = return_value_var.asTypedValue();
  tvBox(return_value);

  Variant this_ptr_var(Variant::NullInit{});
  auto const this_ptr = this_ptr_var.asTypedValue();
  tvBox(this_ptr);

  if (ar->hasThis()) {
    tvWriteObject(
      ar->getThis(),
      this_ptr->m_data.pref->tv()
    );
  }

  auto *return_value_ptr = &return_value->m_data.pref;

  // Clear any stored exception
  ZendExceptionStore& exceptionStore = ZendExceptionStore::getInstance();
  exceptionStore.clear();

  // Invoke the PHP extension function/method
  ZendExecutionStack::pushHHVMStack();
  try {
    builtin_func(
      ar->numArgs(),
      return_value->m_data.pref,
      return_value_ptr,
      this_ptr_var.isNull() ? nullptr : this_ptr->m_data.pref,
      1
	  TSRMLS_CC
    );
  } catch (...) {
    ZendExecutionStack::popHHVMStack();
    throw;
  }
  ZendExecutionStack::popHHVMStack();

  // If an exception was caught, rethrow it
  if (!exceptionStore.empty()) {
    exceptionStore.rethrow();
  }

  // Take care of freeing the args, tearing down the ActRec,
  // and moving the return value to the right place
  frame_free_locals_inl(ar, numParams);
  memcpy(&ar->m_r, return_value, sizeof(TypedValue));
  return_value->m_type = KindOfNull;
  if (isReturnRef) {
    if (!ar->m_r.m_data.pref->isReferenced()) {
      tvUnbox(&ar->m_r);
    }
  } else {
    tvUnbox(&ar->m_r);
  }

  return &ar->m_r;
}