Don't use LdClsPropAddrCached for properties that might not be accessible

Tx64 only translates CGetS when you do it with the context
class the same as the class being looked up, to avoid the need for
accessibility checks.  The IR can translate it more often, but was
using its fast path even when it was not safe to do so: if a previous
(safe) access had allocated a targetcache entry, later accesses would
be able to get to the property without an access check.  For now just
limit the optimiation to safe cases.
Esse commit está contido em:
jdelong
2013-03-22 18:20:55 -07:00
commit de Sara Golemon
commit 2c72411dae
7 arquivos alterados com 67 adições e 28 exclusões
+24 -24
Ver Arquivo
@@ -1037,15 +1037,15 @@ void HhbcTranslator::emitIssetL(int32_t id) {
void HhbcTranslator::emitIssetG(const StringData* gblName) {
TRACE(3, "%u: IssetG\n", m_bcOff);
emitIsset(gblName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedGblName,
&HPHP::VM::JIT::HhbcTranslator::emitLdGblAddr);
&HhbcTranslator::checkSupportedGblName,
&HhbcTranslator::emitLdGblAddr);
}
void HhbcTranslator::emitIssetS(const StringData* propName) {
TRACE(3, "%u: IssetS\n", m_bcOff);
emitIsset(propName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedClsProp,
&HPHP::VM::JIT::HhbcTranslator::emitLdClsPropAddrOrExit);
&HhbcTranslator::checkSupportedClsProp,
&HhbcTranslator::emitLdClsPropAddrOrExit);
}
void HhbcTranslator::emitEmptyL(int32_t id) {
@@ -1065,15 +1065,15 @@ void HhbcTranslator::emitEmptyL(int32_t id) {
void HhbcTranslator::emitEmptyG(const StringData* gblName) {
TRACE(3, "%u: EmptyG\n", m_bcOff);
emitEmpty(gblName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedGblName,
&HPHP::VM::JIT::HhbcTranslator::emitLdGblAddr);
&HhbcTranslator::checkSupportedGblName,
&HhbcTranslator::emitLdGblAddr);
}
void HhbcTranslator::emitEmptyS(const StringData* propName) {
TRACE(3, "%u: EmptyS\n", m_bcOff);
emitEmpty(propName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedClsProp,
&HPHP::VM::JIT::HhbcTranslator::emitLdClsPropAddrOrExit);
&HhbcTranslator::checkSupportedClsProp,
&HhbcTranslator::emitLdClsPropAddrOrExit);
}
void HhbcTranslator::emitIsTypeC(Type t) {
@@ -2251,41 +2251,41 @@ void HhbcTranslator::emitEmpty(const StringData* name,
void HhbcTranslator::emitBindG(const StringData* gblName) {
TRACE(3, "%u: BindG\n", m_bcOff);
emitBind(gblName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedGblName,
&HPHP::VM::JIT::HhbcTranslator::emitLdGblAddrDef);
&HhbcTranslator::checkSupportedGblName,
&HhbcTranslator::emitLdGblAddrDef);
}
void HhbcTranslator::emitBindS(const StringData* propName) {
TRACE(3, "%u: BindS\n", m_bcOff);
emitBind(propName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedClsProp,
&HPHP::VM::JIT::HhbcTranslator::emitLdClsPropAddr);
&HhbcTranslator::checkSupportedClsProp,
&HhbcTranslator::emitLdClsPropAddr);
}
void HhbcTranslator::emitVGetG(const StringData* gblName) {
TRACE(3, "%u: VGetG\n", m_bcOff);
emitVGet(gblName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedGblName,
&HPHP::VM::JIT::HhbcTranslator::emitLdGblAddrDef);
&HhbcTranslator::checkSupportedGblName,
&HhbcTranslator::emitLdGblAddrDef);
}
void HhbcTranslator::emitVGetS(const StringData* propName) {
TRACE(3, "%u: VGetS\n", m_bcOff);
emitVGet(propName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedClsProp,
&HPHP::VM::JIT::HhbcTranslator::emitLdClsPropAddr);
&HhbcTranslator::checkSupportedClsProp,
&HhbcTranslator::emitLdClsPropAddr);
}
void HhbcTranslator::emitSetG(const StringData* gblName) {
emitSet(gblName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedGblName,
&HPHP::VM::JIT::HhbcTranslator::emitLdGblAddrDef);
&HhbcTranslator::checkSupportedGblName,
&HhbcTranslator::emitLdGblAddrDef);
}
void HhbcTranslator::emitSetS(const StringData* propName) {
emitSet(propName,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedClsProp,
&HPHP::VM::JIT::HhbcTranslator::emitLdClsPropAddr);
&HhbcTranslator::checkSupportedClsProp,
&HhbcTranslator::emitLdClsPropAddr);
}
static Type getResultType(Type resultType, bool isInferedType) {
@@ -2322,8 +2322,8 @@ void HhbcTranslator::emitCGetG(const StringData* gblName,
bool isInferedType) {
TRACE(3, "%u: CGetG\n", m_bcOff);
emitCGet(gblName, resultType, isInferedType, true,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedGblName,
&HPHP::VM::JIT::HhbcTranslator::emitLdGblAddr);
&HhbcTranslator::checkSupportedGblName,
&HhbcTranslator::emitLdGblAddr);
}
void HhbcTranslator::emitCGetS(const StringData* propName,
@@ -2331,8 +2331,8 @@ void HhbcTranslator::emitCGetS(const StringData* propName,
bool isInferedType) {
TRACE(3, "%u: CGetS\n", m_bcOff);
emitCGet(propName, resultType, isInferedType, false,
&HPHP::VM::JIT::HhbcTranslator::checkSupportedClsProp,
&HPHP::VM::JIT::HhbcTranslator::emitLdClsPropAddrOrExit);
&HhbcTranslator::checkSupportedClsProp,
&HhbcTranslator::emitLdClsPropAddrOrExit);
}
void HhbcTranslator::emitBinaryArith(Opcode opc) {
+11 -4
Ver Arquivo
@@ -1214,12 +1214,12 @@ SSATmp* Simplifier::simplifyConvToStr(IRInstruction* inst) {
SSATmp* Simplifier::simplifyLdClsPropAddr(IRInstruction* inst) {
SSATmp* propName = inst->getSrc(1);
if (!propName->isConst()) return NULL;
if (!propName->isConst()) return nullptr;
SSATmp* cls = inst->getSrc(0);
const StringData* clsNameString = cls->isConst()
? cls->getValClass()->preClass()->name()
: NULL;
: nullptr;
if (!clsNameString) {
// see if you can get the class name from a LdCls
IRInstruction* clsInst = cls->getInstruction();
@@ -1233,8 +1233,15 @@ SSATmp* Simplifier::simplifyLdClsPropAddr(IRInstruction* inst) {
}
if (!clsNameString) return nullptr;
// we known both the class name and the property name statically
// so use the caching version of LdClsPropAddr
// We known both the class name and the property name statically so
// we can use the caching version of LdClsPropAddr. To avoid doing
// accessibility checks, we only do this if the context class is the
// same as the actual class the property is on.
auto const ctxCls = inst->getSrc(2)->getValClass();
if (!ctxCls || !clsNameString->isame(ctxCls->preClass()->name())) {
return nullptr;
}
return m_tb->gen(LdClsPropAddrCached,
inst->getTaken(),
cls,
+15
Ver Arquivo
@@ -0,0 +1,15 @@
<?php
$nonstaticUnscoped = function () {
var_dump(A::$priv);
};
class A {
private static $priv = 7;
function readVar() {
A::$priv;
}
}
(new A())->readVar();
$nonstaticUnscoped();
@@ -0,0 +1 @@
HipHop Fatal error: Invalid static property access: A::priv in hphp/test/vm/hopt_sprop_accessibility.php on line 4
+1
Ver Arquivo
@@ -0,0 +1 @@
filepath.filter
+14
Ver Arquivo
@@ -0,0 +1,14 @@
<?php
class A {
private static $priv = 7;
function readVar() {
A::$priv;
}
}
function main() {
(new A())->readVar();
var_dump(isset(A::$priv));
}
main();
@@ -0,0 +1 @@
bool(false)