Give `NowTask` some teeth
[hiphop-php.git] / hphp / runtime / vm / constant.cpp
blob06a60aa14280ca349700cc10e2962b62202c3311
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/vm/constant.h"
19 #include "hphp/runtime/base/autoload-handler.h"
20 #include "hphp/runtime/base/static-string-table.h"
21 #include "hphp/runtime/base/string-data.h"
22 #include "hphp/runtime/base/strings.h"
23 #include "hphp/runtime/base/tv-refcount.h"
25 #include "hphp/runtime/vm/coeffects.h"
26 #include "hphp/runtime/vm/func.h"
27 #include "hphp/runtime/vm/hhbc.h"
28 #include "hphp/runtime/vm/native.h"
30 namespace HPHP {
32 //////////////////////////////////////////////////////////////////////
34 TRACE_SET_MOD(hhbc);
36 //////////////////////////////////////////////////////////////////////
38 namespace {
40 //////////////////////////////////////////////////////////////////////
42 const StaticString s_stdin("STDIN");
43 const StaticString s_stdout("STDOUT");
44 const StaticString s_stderr("STDERR");
46 //////////////////////////////////////////////////////////////////////
50 void Constant::prettyPrint(std::ostream& out) const {
51 out << "Constant " << name->data();
52 if (type(val) == KindOfUninit) {
53 out << " = " << "<non-scalar>";
54 } else {
55 std::string ss;
56 staticStreamer(&val, ss);
57 out << " = " << ss;
59 out << std::endl;
62 const StringData* Constant::nameFromFuncName(const StringData* func_name) {
63 const int prefix_len = sizeof("86cinit_") - 1;
64 if (func_name->size() <= prefix_len) {
65 return nullptr;
67 auto slice = func_name->slice();
68 auto ns_pos = slice.rfind('\\');
69 folly::StringPiece ns_slice = "";
70 if (ns_pos >= 0) {
71 ns_slice = slice.subpiece(0, ns_pos + 1);
72 slice = slice.subpiece(ns_pos + 1, slice.size() - ns_pos - 1);
74 if (!slice.startsWith("86cinit_")) {
75 return nullptr;
77 slice = slice.subpiece(8, slice.size() - prefix_len);
78 return makeStaticString(folly::sformat("{}{}", ns_slice, slice));
81 const StringData* Constant::funcNameFromName(const StringData* name) {
82 auto slice = name->slice();
83 auto ns_pos = slice.rfind('\\');
84 if (ns_pos < 0) {
85 return makeStaticString(folly::sformat("86cinit_{}", slice));
87 auto ns_slice = slice.subpiece(0, ns_pos + 1);
88 slice = slice.subpiece(ns_pos + 1, slice.size() - ns_pos - 1);
89 return makeStaticString(folly::sformat("{}86cinit_{}", ns_slice, slice));
92 TypedValue Constant::lookup(const StringData* cnsName) {
93 auto const handle = lookupCnsHandle(cnsName);
95 if (LIKELY(rds::isHandleBound(handle) &&
96 rds::isHandleInit(handle))) {
97 auto const& tv = rds::handleToRef<TypedValue, rds::Mode::NonLocal>(handle);
99 if (LIKELY(type(tv) != KindOfUninit)) {
100 assertx(tvIsPlausible(tv));
101 tvIncRefGen(tv);
102 return tv;
105 Variant v = Constant::get(cnsName);
106 const TypedValue tvRet = v.detach();
107 assertx(tvIsPlausible(tvRet));
108 assertx(tvAsCVarRef(&tvRet).isAllowedAsConstantValue() ==
109 Variant::AllowedAsConstantValue::Allowed);
111 if (rds::isNormalHandle(handle) && type(tvRet) != KindOfResource) {
112 tvIncRefGen(tvRet);
113 rds::handleToRef<TypedValue, rds::Mode::Normal>(handle) = tvRet;
115 return tvRet;
117 return make_tv<KindOfUninit>();
120 const TypedValue* Constant::lookupPersistent(const StringData* cnsName) {
121 auto const handle = lookupCnsHandle(cnsName);
122 if (!rds::isHandleBound(handle) || !rds::isPersistentHandle(handle)) {
123 return nullptr;
125 auto const ret = rds::handleToPtr<TypedValue, rds::Mode::Persistent>(handle);
126 assertx(tvIsPlausible(*ret));
127 return ret;
130 TypedValue Constant::load(const StringData* cnsName) {
131 auto const tv = lookup(cnsName);
132 if (LIKELY(type(tv) != KindOfUninit)) return tv;
134 if (needsNSNormalization(cnsName)) {
135 return load(normalizeNS(cnsName));
138 if (!AutoloadHandler::s_instance->autoloadConstant(
139 const_cast<StringData*>(cnsName))) {
140 return make_tv<KindOfUninit>();
142 return lookup(cnsName);
145 Variant Constant::get(const StringData* name) {
146 const StringData* func_name = Constant::funcNameFromName(name);
147 Func* func = Func::lookup(func_name);
148 assertx(
149 func &&
150 "The function should have been autoloaded when we loaded the constant");
151 return Variant::attach(
152 g_context->invokeFuncFew(func, nullptr, 0, nullptr,
153 RuntimeCoeffects::fixme(), false, false)
157 void Constant::def(const Constant* constant) {
158 auto const cnsName = constant->name;
159 FTRACE(3, " Defining def {}\n", cnsName->data());
160 auto const cnsVal = constant->val;
162 if (constant->attrs & Attr::AttrPersistent) {
163 DEBUG_ONLY auto res = bindPersistentCns(cnsName, cnsVal);
164 assertx(res);
165 return;
168 auto const ch = makeCnsHandle(cnsName);
169 assertx(rds::isHandleBound(ch));
171 if (rds::isHandleInit(ch)) {
172 raise_error(Strings::CONSTANT_ALREADY_DEFINED, cnsName->data());
175 assertx(cnsVal.m_type == KindOfUninit ||
176 tvAsCVarRef(&cnsVal).isAllowedAsConstantValue() ==
177 Variant::AllowedAsConstantValue::Allowed);
179 assertx(rds::isNormalHandle(ch));
180 auto cns = rds::handleToPtr<TypedValue, rds::Mode::NonLocal>(ch);
181 tvDup(cnsVal, *cns);
182 rds::initHandle(ch);