canonicalize \print_r to print_r at runtime

builds on D795509.

This copies all the callsites where we autoload.
Esse commit está contido em:
Paul Tarjan
2013-05-08 22:30:40 -07:00
commit de Sara Golemon
commit 99fcd4295e
16 arquivos alterados com 109 adições e 18 exclusões
+2 -1
Ver Arquivo
@@ -15,6 +15,8 @@
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/ext/ext_misc.h"
#include "hphp/runtime/base/server/server_stats.h"
#include "hphp/runtime/base/util/exceptions.h"
#include "hphp/runtime/base/zend/zend_pack.h"
@@ -23,7 +25,6 @@
#include "hphp/runtime/base/strings.h"
#include "hphp/runtime/ext/ext_class.h"
#include "hphp/runtime/ext/ext_math.h"
#include "hphp/runtime/ext/ext_misc.h"
#include "hphp/runtime/vm/bytecode.h"
#include "hphp/util/parser/scanner.h"
#include "hphp/runtime/base/class_info.h"
+16 -1
Ver Arquivo
@@ -739,6 +739,8 @@ lookupKnownClass(Class** cache, const StringData* clsName, bool isClass) {
Class* cls = *cache;
assert(!cls); // the caller should already have checked
assert(clsName->data()[0] != '\\'); // namespace names should be done earlier
AutoloadHandler::s_instance->invokeHandler(
StrNR(const_cast<StringData*>(clsName)));
cls = *cache;
@@ -772,17 +774,30 @@ ClassCache::lookup(Handle handle, StringData *name,
const void* unused) {
ClassCache* thiz = cacheAtHandle(handle);
Pair *pair = thiz->keyToPair(name);
String normName;
const StringData* pairSd = pair->m_key;
if (!stringMatches(pairSd, name)) {
TRACE(1, "ClassCache miss: %s\n", name->data());
const NamedEntity *ne = Unit::GetNamedEntity(name);
Class *c = Unit::lookupClass(ne);
if (UNLIKELY(!c)) {
c = Unit::loadMissingClass(ne, name);
normName = normalizeNS(name);
if (normName) {
name = normName.get();
ne = Unit::GetNamedEntity(name);
c = Unit::lookupClass(ne);
if (!c) {
c = Unit::loadMissingClass(ne, name);
}
} else {
c = Unit::loadMissingClass(ne, name);
}
if (UNLIKELY(!c)) {
undefinedError(Strings::UNKNOWN_CLASS, name->data());
}
}
if (pair->m_key) decRefStr(pair->m_key);
pair->m_key = name;
name->incRefCount();
+63 -15
Ver Arquivo
@@ -633,10 +633,11 @@ void Unit::defTypedef(Id id) {
assert(id < m_typedefs.size());
auto thisType = &m_typedefs[id];
auto nameList = GetNamedEntity(thisType->m_name);
const StringData* typeName = thisType->m_value;
auto checkExistingClass = [&] (Class* cls) {
if (thisType->m_kind != KindOfObject ||
!cls->name()->isame(thisType->m_value)) {
!cls->name()->isame(typeName)) {
raise_error("The type %s is already defined to a different class (%s)",
thisType->m_name->data(),
cls->name()->data());
@@ -655,7 +656,7 @@ void Unit::defTypedef(Id id) {
Typedef* td = current.asTypedef();
assert(td);
if (thisType->m_kind != td->m_kind ||
!td->m_value->isame(thisType->m_value)) {
!td->m_value->isame(typeName)) {
raise_error("The type %s is already defined to an incompatible type",
thisType->m_name->data());
}
@@ -688,19 +689,28 @@ void Unit::defTypedef(Id id) {
nameList->setCachedNameDef(NameDef(thisType));
return;
}
if (auto klass = Unit::loadClass(thisType->m_value)) {
if (auto klass = Unit::loadClass(typeName)) {
nameList->setCachedNameDef(NameDef(klass));
return;
}
auto targetNameList = GetNamedEntity(thisType->m_value);
auto targetNameList = GetNamedEntity(typeName);
NameDef target = targetNameList->getCachedNameDef();
if (!target) {
AutoloadHandler::s_instance->autoloadType(thisType->m_value->data());
target = targetNameList->getCachedNameDef();
String normName = normalizeNS(typeName);
if (normName) {
typeName = normName.get();
targetNameList = GetNamedEntity(typeName);
target = targetNameList->getCachedNameDef();
}
if (!target) {
raise_error("Unknown type or class %s", thisType->m_value->data());
return;
AutoloadHandler::s_instance->autoloadType(typeName->data());
target = targetNameList->getCachedNameDef();
if (!target) {
raise_error("Unknown type or class %s", typeName->data());
return;
}
}
}
assert(target);
@@ -734,6 +744,16 @@ Class* Unit::loadClass(const NamedEntity* ne,
return cls;
}
VMRegAnchor _;
String normName = normalizeNS(name);
if (normName) {
name = normName.get();
ne = GetNamedEntity(name);
if ((cls = ne->getCachedClass()) != nullptr) {
return cls;
}
}
AutoloadHandler::s_instance->invokeHandler(
StrNR(const_cast<StringData*>(name)));
return Unit::lookupClass(ne);
@@ -749,8 +769,20 @@ Class* Unit::loadMissingClass(const NamedEntity* ne,
Class* Unit::getClass(const NamedEntity* ne,
const StringData *name, bool tryAutoload) {
Class *cls = lookupClass(ne);
if (UNLIKELY(!cls && tryAutoload)) {
return loadMissingClass(ne, name);
if (UNLIKELY(!cls)) {
String normName = normalizeNS(name);
if (normName) {
name = normName.get();
ne = GetNamedEntity(name);
if ((cls = lookupClass(ne)) != nullptr) {
return cls;
}
}
if (tryAutoload) {
return loadMissingClass(ne, name);
}
}
return cls;
}
@@ -910,6 +942,14 @@ TypedValue* Unit::lookupPersistentCns(const StringData* cnsName) {
TypedValue* Unit::loadCns(const StringData* cnsName) {
TypedValue* tv = lookupCns(cnsName);
if (LIKELY(tv != nullptr)) return tv;
String normName = normalizeNS(cnsName);
if (normName) {
cnsName = normName.get();
tv = lookupCns(cnsName);
if (tv != nullptr) return tv;
}
if (!AutoloadHandler::s_instance->autoloadConstant(
const_cast<StringData*>(cnsName))) {
return nullptr;
@@ -1598,11 +1638,19 @@ Func* Unit::lookupFunc(const StringData* funcName) {
Func* Unit::loadFunc(const NamedEntity* ne, const StringData* funcName) {
Func* func = ne->getCachedFunc();
if (UNLIKELY(!func)) {
if (AutoloadHandler::s_instance->autoloadFunc(
const_cast<StringData*>(funcName))) {
func = ne->getCachedFunc();
}
if (LIKELY(func != nullptr)) return func;
String normName = normalizeNS(funcName);
if (normName) {
funcName = normName.get();
ne = GetNamedEntity(funcName);
func = ne->getCachedFunc();
if (func) return func;
}
if (AutoloadHandler::s_instance->autoloadFunc(
const_cast<StringData*>(funcName))) {
func = ne->getCachedFunc();
}
return func;
}
+13 -1
Ver Arquivo
@@ -1092,5 +1092,17 @@ public:
Class* popFront();
};
} // HPHP::VM
/**
* If name starts with '\\', returns a new String with the leading
* slash stripped. Otherwise returns a null string.
*/
inline const String normalizeNS(const StringData* name) {
assert(name->data()[name->size()] == 0);
if (name->data()[0] == '\\') {
return String(name->data() + 1);
}
return null_string;
}
}
#endif
+4
Ver Arquivo
@@ -0,0 +1,4 @@
<?php
namespace A;
new \B;
@@ -0,0 +1 @@
HipHop Fatal error: Class undefined: B in %s on line 4
+4
Ver Arquivo
@@ -0,0 +1,4 @@
<?php
namespace A;
echo \B;
@@ -0,0 +1 @@
HipHop Fatal error: Undefined constant 'B' in %s on line 4
+4
Ver Arquivo
@@ -0,0 +1,4 @@
<?php
namespace A;
\b();
@@ -0,0 +1 @@
HipHop Fatal error: Call to undefined function b() in %s on line 4