49
49
#include "hphp/compiler/expression/modifier_expression.h"
50
50
#include "hphp/compiler/expression/new_object_expression.h"
51
51
#include "hphp/compiler/expression/object_method_expression.h"
52
-
#include "hphp/compiler/expression/object_property_expression.h"
53
52
#include "hphp/compiler/expression/parameter_expression.h"
54
53
#include "hphp/compiler/expression/qop_expression.h"
55
54
#include "hphp/compiler/expression/scalar_expression.h"
@@ -156,6 +155,7 @@ namespace StackSym {
156
155
static const char S = 0x60; // Static property marker
157
156
static const char M = 0x70; // Non elem/prop/W part of M-vector
158
157
static const char K = 0x80; // Marker for information about a class base
158
+
static const char Q = 0x90; // NullSafe Property marker
159
159
160
160
static const char CN = C | N;
161
161
static const char CG = C | G;
@@ -189,6 +189,7 @@ namespace StackSym {
189
189
case StackSym::E: res += "E"; break;
190
190
case StackSym::W: res += "W"; break;
191
191
case StackSym::P: res += "P"; break;
192
+
case StackSym::Q: res += "Q"; break;
192
193
case StackSym::S: res += "S"; break;
193
194
case StackSym::K: res += "K"; break;
194
195
default: break;
@@ -1983,7 +1984,8 @@ void EmitterVisitor::popEvalStackMMany() {
1983
1984
char sym = m_evalStack.top();
1984
1985
char symFlavor = StackSym::GetSymFlavor(sym);
1985
1986
char marker = StackSym::GetMarker(sym);
1986
-
if (marker == StackSym::E || marker == StackSym::P) {
1987
+
if (marker == StackSym::E || marker == StackSym::P ||
1988
+
marker == StackSym::Q) {
1987
1989
if (symFlavor != StackSym::C && symFlavor != StackSym::L &&
1988
1990
symFlavor != StackSym::T && symFlavor != StackSym::I) {
1989
1991
InvariantViolation(
@@ -4370,6 +4372,16 @@ bool EmitterVisitor::visit(ConstructPtr node) {
4370
4372
case Expression::KindOfObjectPropertyExpression: {
4371
4373
ObjectPropertyExpressionPtr op(
4372
4374
static_pointer_cast<ObjectPropertyExpression>(node));
4375
+
if (op->isNullSafe() &&
4376
+
op->hasAnyContext(
4377
+
Expression::RefValue
4378
+
| Expression::LValue
4379
+
| Expression::DeepReference
4380
+
) && !op->hasContext(Expression::InvokeArgument)
4381
+
) {
4382
+
throw IncludeTimeFatalException(op,
4383
+
Strings::NULLSAFE_PROP_WRITE_ERROR);
4384
+
}
4373
4385
ExpressionPtr obj = op->getObject();
4374
4386
SimpleVariablePtr sv = dynamic_pointer_cast<SimpleVariable>(obj);
4375
4387
if (sv && sv->isThis() && sv->hasContext(Expression::ObjectContext)) {
@@ -4387,7 +4399,12 @@ bool EmitterVisitor::visit(ConstructPtr node) {
4387
4399
Expression::ObjectContext)) {
4388
4400
m_tempLoc = op->getLocation();
4389
4401
}
4390
-
markProp(e);
4402
+
markProp(
4403
+
e,
4404
+
op->isNullSafe()
4405
+
? PropAccessType::NullSafe
4406
+
: PropAccessType::Normal
4407
+
);
4391
4408
return true;
4392
4409
}
4393
4410
@@ -4872,7 +4889,8 @@ int EmitterVisitor::scanStackForLocation(int iLast) {
4872
4889
for (int i = iLast; i >= 0; --i) {
4873
4890
char marker = StackSym::GetMarker(m_evalStack.get(i));
4874
4891
if (marker != StackSym::E && marker != StackSym::W &&
4875
-
marker != StackSym::P && marker != StackSym::M) {
4892
+
marker != StackSym::P && marker != StackSym::M &&
4893
+
marker != StackSym::Q) {
4876
4894
return i;
4877
4895
}
4878
4896
}
@@ -4998,6 +5016,10 @@ void EmitterVisitor::buildVectorImm(std::vector<uchar>& vectorImm,
4998
5016
vectorImm.push_back(MPC);
4999
5017
}
5000
5018
} break;
5019
+
case StackSym::Q: {
5020
+
assert(symFlavor == StackSym::T);
5021
+
vectorImm.push_back(MQT);
5022
+
} break;
5001
5023
case StackSym::S: {
5002
5024
assert(false);
5003
5025
}
@@ -5981,7 +6003,7 @@ void EmitterVisitor::markNewElem(Emitter& e) {
5981
6003
m_evalStack.push(StackSym::W);
5982
6004
}
5983
6005
5984
-
void EmitterVisitor::markProp(Emitter& e) {
6006
+
void EmitterVisitor::markProp(Emitter& e, PropAccessType propAccessType) {
5985
6007
if (m_evalStack.empty()) {
5986
6008
InvariantViolation(
5987
6009
"Emitter encountered an empty evaluation stack inside "
@@ -5991,7 +6013,13 @@ void EmitterVisitor::markProp(Emitter& e) {
5991
6013
}
5992
6014
char sym = m_evalStack.top();
5993
6015
if (sym == StackSym::C || sym == StackSym::L || sym == StackSym::T) {
5994
-
m_evalStack.set(m_evalStack.size()-1, (sym | StackSym::P));
6016
+
m_evalStack.set(
6017
+
m_evalStack.size()-1,
6018
+
(sym | (propAccessType == PropAccessType::NullSafe
6019
+
? StackSym::Q
6020
+
: StackSym::P
6021
+
))
6022
+
);
5995
6023
} else {
5996
6024
InvariantViolation(
5997
6025
"Emitter encountered an unsupported StackSym \"%s\" on "
@@ -6928,7 +6956,7 @@ void EmitterVisitor::emitMemoizeProp(Emitter& e,
6928
6956
m_evalStack.setKnownCls(m_curFunc->pce()->name(), false);
6929
6957
m_evalStack.push(StackSym::T);
6930
6958
m_evalStack.setString(m_curFunc->memoizePropName);
6931
-
markProp(e);
6959
+
markProp(e, PropAccessType::Normal);
6932
6960
}
6933
6961
6934
6962
assert(numParams <= paramIDs.size());
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4