2 +----------------------------------------------------------------------+
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"
32 //////////////////////////////////////////////////////////////////////
36 //////////////////////////////////////////////////////////////////////
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>";
56 staticStreamer(&val
, ss
);
62 const StringData
* Constant::nameFromFuncName(const StringData
* func_name
) {
63 const int prefix_len
= sizeof("86cinit_") - 1;
64 if (func_name
->size() <= prefix_len
) {
67 auto slice
= func_name
->slice();
68 auto ns_pos
= slice
.rfind('\\');
69 folly::StringPiece ns_slice
= "";
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_")) {
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('\\');
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
));
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
) {
113 rds::handleToRef
<TypedValue
, rds::Mode::Normal
>(handle
) = 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
)) {
125 auto const ret
= rds::handleToPtr
<TypedValue
, rds::Mode::Persistent
>(handle
);
126 assertx(tvIsPlausible(*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
);
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
);
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
);