HEX
Server: Apache
System: Linux wp02.tdr-lab.com 3.10.0-1160.42.2.el7.x86_64 #1 SMP Tue Sep 7 14:49:57 UTC 2021 x86_64
User: kusanagi (1001)
PHP: 7.4.23
Disabled: NONE
Upload Files
File: //usr/include/hphp/hhbbc/eval-cell.h
/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com)  |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
*/
#ifndef incl_HHBBC_EVAL_CELL_H_
#define incl_HHBBC_EVAL_CELL_H_

#include <stdexcept>
#include <exception>

#include <folly/ScopeGuard.h>
#include <folly/Optional.h>

#include "hphp/runtime/base/array-data.h"
#include "hphp/runtime/base/execution-context.h"
#include "hphp/runtime/base/string-data.h"
#include "hphp/runtime/vm/repo.h"

#include "hphp/hhbbc/hhbbc.h"
#include "hphp/hhbbc/type-system.h"

namespace HPHP { namespace HHBBC {

//////////////////////////////////////////////////////////////////////

/*
 * When constant-evaluating certain operations, it's possible they
 * will return non-static objects, or throw exceptions (e.g. cellAdd()
 * with an array and an int).
 *
 * This routine converts these things back to types.  In the case of
 * an exception it returns TInitCell.
 */
template<class Pred>
folly::Optional<Type> eval_cell(Pred p) {
  try {
    assert(!RuntimeOption::EvalJit);
    ThrowAllErrorsSetter taes;

    Cell c = p();
    if (isRefcountedType(c.m_type)) {
      switch (c.m_type) {
      case KindOfString:
        {
          if (c.m_data.pstr->size() > Repo::get().stringLengthLimit()) {
            tvDecRef(&c);
            return TStr;
          }
          auto const sstr = makeStaticString(c.m_data.pstr);
          tvDecRef(&c);
          c = make_tv<KindOfPersistentString>(sstr);
        }
        break;
      case KindOfArray:
        {
          auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
          tvDecRef(&c);
          c = make_tv<KindOfPersistentArray>(sarr);
        }
        break;
      case KindOfVec:
        {
          auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
          tvDecRef(&c);
          c = make_tv<KindOfPersistentVec>(sarr);
        }
        break;
      case KindOfDict:
        {
          auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
          tvDecRef(&c);
          c = make_tv<KindOfPersistentDict>(sarr);
        }
        break;
      case KindOfKeyset:
        {
          auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
          tvDecRef(&c);
          c = make_tv<KindOfPersistentKeyset>(sarr);
        }
        break;
      case KindOfUninit:
      case KindOfNull:
      case KindOfInt64:
      case KindOfBoolean:
      case KindOfDouble:
      case KindOfPersistentString:
      case KindOfPersistentArray:
      case KindOfPersistentVec:
      case KindOfPersistentDict:
      case KindOfPersistentKeyset:
      case KindOfObject:
      case KindOfResource:
      case KindOfRef:
        always_assert(0 && "Impossible constant evaluation occurred");
      }
    }

    /*
     * We need to get rid of statics if we're not actually going to do
     * constant propagation.  When ConstantProp is on, the types we
     * create here can reflect that we'll be changing bytecode later
     * to actually make these into non-reference-counted SStr or
     * SArrs.  If we leave the bytecode alone, though, it generally
     * won't actually be static at runtime.
     *
     * TODO(#3696042): loosen_statics here should ideally not give up
     * on the array or string value, just its staticness.
     */
    auto const t = from_cell(c);
    return options.ConstantProp ? t : loosen_statics(t);
  } catch (const Object&) {
    return folly::none;
  } catch (const std::exception&) {
    return folly::none;
  } catch (...) {
    always_assert_flog(0, "a non-std::exception was thrown in eval_cell");
  }
}

template<typename Pred>
folly::Optional<typename std::result_of<Pred()>::type>
eval_cell_value(Pred p) {
  try {
    ThrowAllErrorsSetter taes;
    return p();
  } catch (const Object&) {
    return folly::none;
  } catch (const std::exception&) {
    return folly::none;
  } catch (...) {
    always_assert_flog(0, "a non-std::exception was thrown in eval_cell_value");
  }
}

//////////////////////////////////////////////////////////////////////

}}

#endif