23 Commits

Autor SHA1 Mensagem Data
Sara Golemon d660972153 HPHP 2.0.1 2013-03-22 19:14:35 -07:00
ptarjan ca437add64 fix this callsite incase someone ever does the TODO for setting valueClass() 2013-03-25 13:59:21 -07:00
mwilliams 3611bf3d58 Fix getContextClassName and getParentContextClassName
They both returned the late static bound class, not the context
class. This meant that eg "constant('self::FOO')" was actually
returning what "constant('static::FOO')" should have done.

In addition, we often want the Class*, not its name, so
change them to return Class*. The remaining places that then
read the name from the Class* should be fixed to use the Class*
directly (in a later diff).

Finally, noticed that while "defined()" was recently fixed to
support "static::", "constant()" was not. Pulled out a common
function to find the correct Class*.
2013-03-25 13:59:02 -07:00
jan 565c8477f8 Fix ref generator parameters
Alias manager does not know whether generator parameters are passed by
reference. This didn't matter, because every generator had at least one
function call (hphp_continuation_done()) that pretty much disabled unused
variable elimination.

This diff fixes that, lets us get rid of artificial function calls in
generators and will allow later improvements in alias manager.
2013-03-22 13:57:25 -07:00
mwilliams 8f3512f6d3 Filter strict_warnings like notices
There is a runtime option to filter out notices and warnings,
but strict_warnings were left out. Bundle them with notices.

We raise a lot of strict_warnings; and when we fix hphpiCompat
(to match zend better) we will raise a lot more, so this could
matter.
2013-03-22 13:57:18 -07:00
ottoni 7241c247dd Disable spilling into MMX registers 2013-03-22 13:57:06 -07:00
jan f06575d4e2 Fix local propagation of generator parameters
Alias manager does not know that generator parameters are populated and
assumes they are uninit. The current code works because control flow
algorithm gives up while trying to deal with the continuation switch
statement full of gotos.

This diff fixes it by setting isGeneratorParameter flag in symbols
representing parameters of enclosing generator wrapper and use variables
of enclosing closure.
2013-03-21 20:41:02 -07:00
Owen Yamauchi cc897749f8 Fix the RIP_REGISTER macro
Pretty simple. This makes me slightly nervous because I've only
confirmed it works in my stupid OpenEmbedded ARM SDK; a different Linux
might call this something else. But we'll cross that bridge when we get
to it, and this works for now.

I'm also sneaking in a change to remove x29 from the list of
callee-saved regs; I put it in there by accident last time.
2013-03-21 20:41:02 -07:00
ptarjan b597e3a753 fix static closures
I added the check for this in the interpreter but ##f_array_map## re-enteres the VM via a different path than FCall. Here is the equivilent check for the VM.
2013-03-21 20:41:02 -07:00
mwilliams 8ec621676d Fix args for embedded repo
When we generate a binary with an embedded repo,
we add various args (-vRepo.Authoritative etc) to the end
of the command line. But the argument "--" is taken to mean
"pass the rest of the args to the script". So if you use
"--" on such a binary, it gets rather badly broken.

Reorder the args so that the inserted ones come first.
2013-03-21 20:41:02 -07:00
mwilliams a134b25671 Fix nemo warnings about undefined $this
The fix for the crash caused us to take a different path
when checking locals.
2013-03-21 20:41:01 -07:00
mwilliams 15fa1ebfde Fix StringBuffer::resize()
capacity doesnt include the terminating null, so len is
allowed to grow to capacity (not capacity - 1).
2013-03-19 14:47:25 -07:00
mwilliams ce75713972 Fix assertion when target==analyze
Option::OutputHHBC should always be true.
2013-03-19 14:47:15 -07:00
Owen Yamauchi adc56c6d8c Fix includes in curl_tls_workarounds.cpp
raise_notice() wasn't declared in this file, so include runtime_error.h.
This caused further problems with ATTRIBUTE_PRINTF not being defined
yet, so include some more stuff.
2013-03-19 14:47:06 -07:00
Sara Golemon 3fb0fe8a6a SSL_OP_NO_TLSv1_2 is not supported by all openssl versions 2013-03-18 18:38:47 -07:00
ottoni 38306b527f SIMPLIFY_COMMUTATIVE only handles Type::Int
So check that the inputs are really Ints.
2013-03-18 18:38:37 -07:00
aravind e4e3bee5d3 Don't simplify Same to Eq to arrays 2013-03-18 18:38:29 -07:00
michalburger1 d25adc550b Fix bzdecompress
Bad memory allocation, the buffer needs to be large enough to fit all
the data we've decompressed so far plus the extra storage we're
incrementally allocationg, not just the incremental part.
2013-03-18 16:20:44 -07:00
Sara Golemon 8b23419a37 HPHP version 2.0.0 2013-03-14 16:00:42 -07:00
ottoni af5623b4fc Properly patch exit traces ending with JmpZero and JmpNZero
The hoistConditionalJumps pass was not handling traces ending with
JmpZero and JmpNZero.  This was resulting in spurious jumps to
'astubs' instead of patching the jcc+jump pair in 'a'.
2013-03-14 15:45:51 -07:00
ptarjan b51003b5aa tell closures about scope clones
In HHBC mode, traits are flattened into their classes.
When that happens, closures need to know about all the
classes that contain them so that when we find a ##$this##
inside the closure, it can tell EVERY containing scope to
please propogate ##$this## down to me.
2013-03-14 15:45:40 -07:00
mwilliams 5f019f5b43 Fix CodeGenerator::cgNInstanceOf
It assumed the result would be in rax, but it isnt always.
Use the correct register.
2013-03-13 10:16:23 -07:00
bertrand 35e347efa5 Fixed ContNext by writing InitNull rather than Uninit.
Apparently, m_received needs to be InitNull, rather than
Uninit.
2013-03-13 10:16:14 -07:00
46 arquivos alterados com 706 adições e 229 exclusões
+2 -1
Ver Arquivo
@@ -1503,7 +1503,8 @@ ExpressionPtr AliasManager::canonicalizeNode(
e->is(Expression::KindOfSimpleVariable) &&
!e->isThis()) {
Symbol *s = spc(SimpleVariable, e)->getSymbol();
if (s && !s->isParameter() && !s->isClosureVar()) {
if (s && !s->isParameter() && !s->isGeneratorParameter() &&
!s->isClosureVar()) {
rep = e->makeConstant(m_arp, "null");
Compiler::Error(Compiler::UseUndeclaredVariable, e);
if (m_variables->getAttribute(VariableTable::ContainsCompact)) {
+31
Ver Arquivo
@@ -25,6 +25,7 @@
#include <compiler/analysis/variable_table.h>
#include <compiler/construct.h>
#include <compiler/expression/class_constant_expression.h>
#include <compiler/expression/closure_expression.h>
#include <compiler/expression/constant_expression.h>
#include <compiler/expression/scalar_expression.h>
#include <compiler/expression/unary_op_expression.h>
@@ -32,6 +33,7 @@
#include <compiler/option.h>
#include <compiler/parser/parser.h>
#include <compiler/statement/interface_statement.h>
#include <compiler/statement/function_statement.h>
#include <compiler/statement/method_statement.h>
#include <compiler/statement/statement_list.h>
#include <runtime/base/builtin_functions.h>
@@ -445,6 +447,7 @@ ClassScope::importTraitMethod(const TraitMethod& traitMethod,
cloneMeth->getModifiers()));
cloneMeth->resetScope(cloneFuncScope, true);
cloneFuncScope->setOuterScope(shared_from_this());
informClosuresAboutScopeClone(cloneMeth, cloneFuncScope, ar);
cloneMeth->addTraitMethodToScope(ar,
dynamic_pointer_cast<ClassScope>(shared_from_this()));
@@ -452,6 +455,34 @@ ClassScope::importTraitMethod(const TraitMethod& traitMethod,
return cloneMeth;
}
void ClassScope::informClosuresAboutScopeClone(
ConstructPtr root,
FunctionScopePtr outerScope,
AnalysisResultPtr ar) {
if (!root) {
return;
}
for (int i = 0; i < root->getKidCount(); i++) {
ConstructPtr cons = root->getNthKid(i);
ClosureExpressionPtr closure =
dynamic_pointer_cast<ClosureExpression>(cons);
if (!closure) {
informClosuresAboutScopeClone(cons, outerScope, ar);
continue;
}
FunctionStatementPtr func = closure->getClosureFunction();
HPHP::FunctionScopePtr funcScope = func->getFunctionScope();
assert(funcScope->isClosure());
funcScope->addClonedTraitOuterScope(outerScope);
// Don't need to recurse
}
}
void ClassScope::addImportTraitMethod(const TraitMethod &traitMethod,
const string &methName) {
m_importMethToTraitMap[methName].push_back(traitMethod);
+3
Ver Arquivo
@@ -437,6 +437,9 @@ private:
void addImportTraitMethod(const TraitMethod &traitMethod,
const std::string &methName);
void informClosuresAboutScopeClone(ConstructPtr root,
FunctionScopePtr outerScope,
AnalysisResultPtr ar);
void setImportTraitMethodModifiers(const std::string &methName,
ClassScopePtr traitCls,
+40
Ver Arquivo
@@ -410,6 +410,46 @@ bool FunctionScope::containsReference() const {
return m_attribute & FileScope::ContainsReference;
}
void FunctionScope::setContainsThis(bool f /* = true */) {
m_containsThis = f;
BlockScopePtr bs(this->getOuterScope());
while (bs && bs->is(BlockScope::FunctionScope)) {
FunctionScopePtr fs = static_pointer_cast<FunctionScope>(bs);
if (!fs->isClosure()) {
break;
}
fs->setContainsThis(f);
bs = bs->getOuterScope();
}
for (auto it = m_clonedTraitOuterScope.begin(); it != m_clonedTraitOuterScope.end(); it++) {
(*it)->setContainsThis(f);
}
}
void FunctionScope::setContainsBareThis(bool f, bool ref /* = false */) {
if (f) {
m_containsBareThis |= ref ? 2 : 1;
} else {
m_containsBareThis = 0;
}
BlockScopePtr bs(this->getOuterScope());
while (bs && bs->is(BlockScope::FunctionScope)) {
FunctionScopePtr fs = static_pointer_cast<FunctionScope>(bs);
if (!fs->isClosure()) {
break;
}
fs->setContainsBareThis(f, ref);
bs = bs->getOuterScope();
}
for (auto it = m_clonedTraitOuterScope.begin(); it != m_clonedTraitOuterScope.end(); it++) {
(*it)->setContainsBareThis(f, ref);
}
}
bool FunctionScope::hasImpl() const {
if (!isUserFunction()) {
return !isAbstract();
+10 -8
Ver Arquivo
@@ -176,6 +176,13 @@ public:
m_volatile = false;
}
/**
* Tell this function about another outer scope that contains it.
*/
void addClonedTraitOuterScope(FunctionScopePtr scope) {
m_clonedTraitOuterScope.push_back(scope);
}
/**
* Get/set original name of the function, without case being lowered.
*/
@@ -237,16 +244,10 @@ public:
* Whether this function contains a usage of $this
*/
bool containsThis() const { return m_containsThis;}
void setContainsThis(bool f=true) { m_containsThis = f;}
void setContainsThis(bool f = true);
bool containsBareThis() const { return m_containsBareThis; }
bool containsRefThis() const { return m_containsBareThis & 2; }
void setContainsBareThis(bool f, bool ref = false) {
if (f) {
m_containsBareThis |= ref ? 2 : 1;
} else {
m_containsBareThis = 0;
}
}
void setContainsBareThis(bool f, bool ref = false);
/**
* How many parameters a caller should provide.
*/
@@ -492,6 +493,7 @@ private:
ExpressionListPtr m_closureValues;
ReadWriteMutex m_inlineMutex;
unsigned m_nextID; // used when cloning generators for traits
std::list<FunctionScopeRawPtr> m_clonedTraitOuterScope;
};
///////////////////////////////////////////////////////////////////////////////
+2 -17
Ver Arquivo
@@ -461,25 +461,11 @@ bool LiveDict::color(TypePtr type) {
if (Type::SameType(type, e->getCPPType())) {
SimpleVariablePtr sv(
static_pointer_cast<SimpleVariable>(e));
bool isGenParam = false;
if (sv->getFunctionScope()->isGenerator()) {
// do not allow coalescing of symbols which are parameters/use vars
// in the generator (sym->isParameter() will be false b/c we are in
// the scope of the generator function)
FunctionScopeRawPtr origScope(sv->getFunctionScope()->getOrigGenFS());
assert(origScope);
Symbol *origSym =
origScope->getVariables()->getSymbol(sv->getName());
if (origSym &&
(origSym->isParameter() || origSym->isClosureVar())) {
isGenParam = true;
}
}
Symbol *sym = sv->getSymbol();
if (sym &&
!sym->isGlobal() &&
!sym->isParameter() &&
!isGenParam &&
!sym->isGeneratorParameter() &&
!sym->isClosureVar() &&
!sym->isStatic() &&
!e->isThis()) {
@@ -623,9 +609,8 @@ public:
always_assert(e && e->is(Expression::KindOfSimpleVariable));
SimpleVariablePtr sv(static_pointer_cast<SimpleVariable>(e));
Symbol *sym = sv->getSymbol();
bool inGen = sv->getFunctionScope()->isGenerator();
if (!sym || sym->isGlobal() || sym->isStatic() || sym->isParameter() ||
sym->isClosureVar() || sv->isThis() || inGen) {
sym->isGeneratorParameter() || sym->isClosureVar() || sv->isThis()) {
continue;
}
+11 -1
Ver Arquivo
@@ -115,6 +115,8 @@ public:
bool isIndirectAltered() const { return m_flags.m_indirectAltered; }
bool isReferenced() const { return !m_flags.m_notReferenced; }
bool isHidden() const { return m_flags.m_hidden; }
bool isGeneratorParameter() const { return m_flags.m_generatorParameter; }
bool isRefGeneratorParameter() const { return m_flags.m_refGeneratorParameter; }
bool isClosureVar() const { return m_flags.m_closureVar; }
bool isRefClosureVar() const { return m_flags.m_refClosureVar; }
bool isPassClosureVar() const { return m_flags.m_passClosureVar; }
@@ -140,6 +142,8 @@ public:
void setIndirectAltered() { m_flags.m_indirectAltered = true; }
void setReferenced() { m_flags.m_notReferenced = false; }
void setHidden() { m_flags.m_hidden = true; }
void setGeneratorParameter() { m_flags.m_generatorParameter = true; }
void setRefGeneratorParameter() { m_flags.m_refGeneratorParameter = true; }
void setClosureVar() { m_flags.m_closureVar = true; }
void setRefClosureVar() { m_flags.m_refClosureVar = true; }
void setPassClosureVar() { m_flags.m_passClosureVar = true; }
@@ -185,7 +189,7 @@ private:
std::string m_name;
unsigned int m_hash;
union {
unsigned m_flags_val;
uint64_t m_flags_val;
struct {
/* internal */
unsigned m_declaration_set : 1;
@@ -219,6 +223,8 @@ private:
unsigned m_indirectAltered : 1;
unsigned m_notReferenced : 1;
unsigned m_hidden : 1;
unsigned m_generatorParameter : 1;
unsigned m_refGeneratorParameter : 1;
unsigned m_closureVar : 1;
unsigned m_refClosureVar : 1;
unsigned m_passClosureVar : 1;
@@ -227,6 +233,10 @@ private:
unsigned m_stashedVal : 1;
unsigned m_reseated : 1;
} m_flags;
static_assert(
sizeof(m_flags_val) == sizeof(m_flags),
"m_flags_val must cover all the flags");
};
ConstructPtr m_declaration;
ConstructPtr m_value;
+4
Ver Arquivo
@@ -567,6 +567,10 @@ void VariableTable::clearUsed() {
} else {
sym.second.setReferenced();
}
if (sym.second.isRefGeneratorParameter()) {
sym.second.setReferenced();
}
}
}
+1 -1
Ver Arquivo
@@ -473,8 +473,8 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
(Util::format_pattern(po.excludeStaticPatterns[i], true));
}
Option::OutputHHBC = true;
if (po.target == "hhbc" || po.target == "run") {
Option::OutputHHBC = true;
Option::AnalyzePerfectVirtuals = false;
}
+1 -1
Ver Arquivo
@@ -172,7 +172,7 @@ void SimpleVariable::analyzeProgram(AnalysisResultPtr ar) {
}
}
} else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
if (m_sym) {
if (m_sym && !m_this) {
if (!m_sym->isSystem() &&
!(getContext() &
(LValue|RefValue|RefParameter|UnsetContext|ExistContext)) &&
+6 -3
Ver Arquivo
@@ -1569,10 +1569,13 @@ void Parser::onClosure(Token &out, Token &ret, Token &ref, Token &params,
Token func, name;
onFunction(func, ret, ref, name, params, stmts, 0);
ClosureExpressionPtr closure = NEW_EXP(
ClosureExpression,
dynamic_pointer_cast<FunctionStatement>(func->stmt),
dynamic_pointer_cast<ExpressionList>(cparams->exp));
closure->getClosureFunction()->setContainingClosure(closure);
out.reset();
out->exp = NEW_EXP(ClosureExpression,
dynamic_pointer_cast<FunctionStatement>(func->stmt),
dynamic_pointer_cast<ExpressionList>(cparams->exp));
out->exp = closure;
}
void Parser::onClosureParam(Token &out, Token *params, Token &param,
+35 -5
Ver Arquivo
@@ -33,6 +33,7 @@
#include <compiler/expression/parameter_expression.h>
#include <compiler/expression/assignment_expression.h>
#include <compiler/expression/simple_variable.h>
#include <compiler/expression/closure_expression.h>
#include <compiler/analysis/ast_walker.h>
#include <compiler/analysis/analysis_result.h>
@@ -372,15 +373,44 @@ void MethodStatement::analyzeProgram(AnalysisResultPtr ar) {
if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
funcScope->setParamSpecs(ar);
if (funcScope->isGenerator()) {
MethodStatementRawPtr orig = getOrigGeneratorFunc();
VariableTablePtr variables = funcScope->getVariables();
Symbol *cont = variables->getSymbol(CONTINUATION_OBJECT_NAME);
cont->setHidden();
getOrigGeneratorFunc()->getFunctionScope()->addUse(
funcScope, BlockScope::UseKindClosure);
getOrigGeneratorFunc()->getFunctionScope()->setContainsBareThis(
orig->getFunctionScope()->addUse(funcScope, BlockScope::UseKindClosure);
orig->getFunctionScope()->setContainsBareThis(
funcScope->containsBareThis(), funcScope->containsRefThis());
getOrigGeneratorFunc()->getFunctionScope()->setContainsThis(
funcScope->containsThis());
orig->getFunctionScope()->setContainsThis(funcScope->containsThis());
if (ExpressionListPtr params = orig->getParams()) {
for (int i = 0; i < params->getCount(); ++i) {
auto param = dynamic_pointer_cast<ParameterExpression>((*params)[i]);
Symbol *gp = variables->addDeclaredSymbol(
param->getName(), ConstructPtr());
gp->setGeneratorParameter();
if (param->isRef()) {
gp->setRefGeneratorParameter();
gp->setReferenced();
}
}
}
if (ClosureExpressionRawPtr closure = orig->getContainingClosure()) {
if (ExpressionListPtr cvars = closure->getClosureVariables()) {
for (int i = 0; i < cvars->getCount(); ++i) {
auto param = dynamic_pointer_cast<ParameterExpression>((*cvars)[i]);
Symbol *gp = variables->addDeclaredSymbol(
param->getName(), ConstructPtr());
gp->setGeneratorParameter();
if (param->isRef()) {
gp->setRefGeneratorParameter();
gp->setReferenced();
}
}
}
}
}
if (funcScope->isSepExtension() ||
Option::IsDynamicFunction(m_method, m_name) || Option::AllDynamic) {
+9
Ver Arquivo
@@ -22,6 +22,7 @@
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(ClosureExpression);
DECLARE_BOOST_TYPES(ModifierExpression);
DECLARE_BOOST_TYPES(ExpressionList);
DECLARE_BOOST_TYPES(StatementList);
@@ -104,6 +105,13 @@ public:
return m_generatorFunc;
}
void setContainingClosure(ClosureExpressionRawPtr exp) {
m_containingClosure = exp;
}
ClosureExpressionRawPtr getContainingClosure() const {
return m_containingClosure;
}
void setClassName(const std::string &name) { m_className = name; }
void setOriginalClassName(const std::string &name) {
m_originalClassName = name;
@@ -127,6 +135,7 @@ protected:
std::string m_docComment;
MethodStatementRawPtr m_origGeneratorFunc;
MethodStatementRawPtr m_generatorFunc;
ClosureExpressionRawPtr m_containingClosure;
ExpressionListPtr m_attrList;
void setSpecialMethod(ClassScopePtr classScope);
+4 -1
Ver Arquivo
@@ -31,10 +31,13 @@ int main(int argc, char** argv) {
return HPHP::execute_program(argc, argv);
}
std::vector<char*> args;
args.insert(args.begin(), argv, argv + argc);
args.push_back(argv[0]);
args.push_back("-vRepo.Authoritative=true");
args.push_back("-vRepo.Local.Mode=r-");
repo = "-vRepo.Local.Path=" + repo;
args.push_back(const_cast<char*>(repo.c_str()));
if (argc > 1) {
args.insert(args.end(), argv + 1, argv + argc);
}
return HPHP::execute_program(args.size(), &args[0]);
}
+2 -1
Ver Arquivo
@@ -345,7 +345,8 @@ vm_decode_function(CVarRef function,
this_ = function.asCObjRef().get();
cls = nullptr;
const HPHP::VM::Func *f = this_->getVMClass()->lookupMethod(invokeStr);
if (f != nullptr && (f->attrs() & HPHP::VM::AttrStatic)) {
if (f != nullptr &&
((f->attrs() & HPHP::VM::AttrStatic) && !f->isClosureBody())) {
// If __invoke is static, invoke it as such
cls = this_->getVMClass();
this_ = nullptr;
+3 -3
Ver Arquivo
@@ -594,11 +594,11 @@ bool ClassInfo::HasAccess(CStrRef className, CStrRef methodName,
clsInfo->hasMethod(methodName, defClass);
if (!methodInfo) return false;
if (methodInfo->attribute & ClassInfo::IsPublic) return true;
CStrRef ctxName = g_vmContext->getContextClassName();
if (ctxName->size() == 0) {
VM::Class* ctx = g_vmContext->getContextClass();
if (!ctx) {
return false;
}
const ClassInfo *ctxClass = ClassInfo::FindClass(ctxName);
const ClassInfo *ctxClass = ClassInfo::FindClass(ctx->nameRef());
bool hasObject = hasCallObject || g_vmContext->getThis();
if (ctxClass) {
return ctxClass->checkAccess(defClass, methodInfo, staticCall, hasObject);
+2 -2
Ver Arquivo
@@ -591,8 +591,8 @@ public:
HPHP::VM::ActRec* getStackFrame();
ObjectData* getThis();
CStrRef getContextClassName();
CStrRef getParentContextClassName();
VM::Class* getContextClass();
VM::Class* getParentContextClass();
CStrRef getContainingFileName();
int getLine();
Array getCallerInfo();
+12 -4
Ver Arquivo
@@ -72,7 +72,13 @@ void raise_recoverable_error(const char *fmt, ...) {
raise_recoverable_error(msg);
}
static int64_t g_notice_counter = 0;
void raise_strict_warning(const std::string &msg) {
if (RuntimeOption::NoticeFrequency <= 0 ||
(g_notice_counter++) % RuntimeOption::NoticeFrequency != 0) {
return;
}
int errnum = ErrorConstants::STRICT;
if (!g_context->errorNeedsHandling(errnum, true,
ExecutionContext::NeverThrow)) {
@@ -84,6 +90,10 @@ void raise_strict_warning(const std::string &msg) {
}
void raise_strict_warning(const char *fmt, ...) {
if (RuntimeOption::NoticeFrequency <= 0 ||
(g_notice_counter++) % RuntimeOption::NoticeFrequency != 0) {
return;
}
std::string msg;
int errnum = ErrorConstants::STRICT;
if (!g_context->errorNeedsHandling(errnum, true,
@@ -117,11 +127,11 @@ void raise_warning(const std::string &msg) {
}
void raise_warning(const char *fmt, ...) {
std::string msg;
if (RuntimeOption::WarningFrequency <= 0 ||
(g_warning_counter++) % RuntimeOption::WarningFrequency != 0) {
return;
}
std::string msg;
int errnum = ErrorConstants::WARNING;
if (!g_context->errorNeedsHandling(errnum, true,
ExecutionContext::NeverThrow)) {
@@ -151,8 +161,6 @@ void raise_debugging(const char *fmt, ...) {
raise_debugging(msg);
}
static int64_t g_notice_counter = 0;
void raise_notice(const std::string &msg) {
if (RuntimeOption::NoticeFrequency <= 0 ||
(g_notice_counter++) % RuntimeOption::NoticeFrequency != 0) {
@@ -169,11 +177,11 @@ void raise_notice(const std::string &msg) {
}
void raise_notice(const char *fmt, ...) {
std::string msg;
if (RuntimeOption::NoticeFrequency <= 0 ||
(g_notice_counter++) % RuntimeOption::NoticeFrequency != 0) {
return;
}
std::string msg;
int errnum = ErrorConstants::NOTICE;
if (!g_context->errorNeedsHandling(errnum, true,
ExecutionContext::NeverThrow)) {
+3
Ver Arquivo
@@ -17,8 +17,11 @@
#ifndef __HPHP_RUNTIME_ERROR_H__
#define __HPHP_RUNTIME_ERROR_H__
#include <cstdarg>
#include <string>
#include "util/base.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
+1 -1
Ver Arquivo
@@ -423,7 +423,7 @@ public:
F(bool, HHIREnableCalleeSavedOpt, true) \
F(bool, HHIREnablePreColoring, true) \
F(bool, HHIREnableCoalescing, true) \
F(bool, HHIREnableMmx, true) \
F(bool, HHIREnableMmx, false) \
F(bool, HHIREnableRefCountOpt, true) \
F(bool, HHIREnableSinking, true) \
F(bool, HHIRGenerateAsserts, debug) \
+9 -2
Ver Arquivo
@@ -14,19 +14,26 @@
+----------------------------------------------------------------------+
*/
#include <runtime/base/util/curl_tls_workarounds.h>
#include <runtime/base/runtime_option.h>
#include <curl/curl.h>
#include <curl/easy.h>
#include <openssl/ssl.h>
#include "runtime/base/util/curl_tls_workarounds.h"
#include "runtime/base/runtime_error.h"
#include "runtime/base/runtime_option.h"
namespace HPHP {
CURLcode curl_tls_workarounds_cb(CURL *curl, void *sslctx, void *parm) {
// Check to see if workarounds are enabled.
if (RuntimeOption::TLSDisableTLS1_2) {
#ifdef SSL_OP_NO_TLSv1_2
SSL_CTX* ctx = (SSL_CTX*)sslctx;
SSL_CTX_set_options(ctx, SSL_CTX_get_options (ctx) | SSL_OP_NO_TLSv1_2);
#else
raise_notice("TLSDisableTLS1_2 enabled, but this version of "
"SSL does not support that option");
#endif
}
return CURLE_OK;
}
+2 -2
Ver Arquivo
@@ -150,8 +150,8 @@ void StringBuffer::release() {
}
void StringBuffer::resize(int size) {
assert(size >= 0 && size < m_cap);
if (size >= 0 && size < m_cap) {
assert(size >= 0 && size <= m_cap);
if (size >= 0 && size <= m_cap) {
m_len = size;
}
}
+2 -2
Ver Arquivo
@@ -623,8 +623,6 @@ static Variant f_hphp_get_iterator(VRefParam iterable, bool isMutable) {
CREATE_VECTOR1(iterable));
}
if (iterable.isObject()) {
CStrRef context = g_vmContext->getContextClassName();
ObjectData *obj = iterable.getObjectData();
Variant iterator;
while (obj->instanceof(SystemLib::s_IteratorAggregateClass)) {
@@ -632,6 +630,8 @@ static Variant f_hphp_get_iterator(VRefParam iterable, bool isMutable) {
if (!iterator.isObject()) break;
obj = iterator.getObjectData();
}
VM::Class*ctx = g_vmContext->getContextClass();
CStrRef context = ctx ? ctx->nameRef() : empty_string;
if (isMutable) {
if (obj->instanceof(SystemLib::s_IteratorClass)) {
throw FatalErrorException("An iterator cannot be used for "
+1 -1
Ver Arquivo
@@ -113,7 +113,7 @@ Variant f_bzdecompress(CStrRef source, int small /* = 0 */) {
/* compression is better then 2:1, need to allocate more memory */
bzs.avail_out = source_len;
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
dest = (char *) Util::safe_realloc(dest, bzs.avail_out + 1);
dest = (char *) Util::safe_realloc(dest, size + bzs.avail_out + 1);
bzs.next_out = dest + size;
}
+2 -1
Ver Arquivo
@@ -37,7 +37,8 @@ static String get_classname(CVarRef class_or_object) {
}
static inline CStrRef ctxClassName() {
return g_vmContext->getContextClassName();
VM::Class* ctx = g_vmContext->getContextClass();
return ctx ? ctx->nameRef() : empty_string;
}
static const VM::Class* get_cls(CVarRef class_or_object) {
+3 -2
Ver Arquivo
@@ -480,7 +480,6 @@ void c_MutableArrayIterator::t___construct(VRefParam array) {
m_valid = mi.advance();
if (!m_valid) mi.~MArrayIter();
} else if (rtv->m_type == KindOfObject) {
CStrRef ctxStr = g_vmContext->getContextClassName();
if (rtv->m_data.pobj->isCollection()) {
raise_error("Collection elements cannot be taken by reference");
}
@@ -489,7 +488,9 @@ void c_MutableArrayIterator::t___construct(VRefParam array) {
if (isIterator) {
raise_error("An iterator cannot be used with foreach by reference");
}
Array iterArray = obj->o_toIterArray(ctxStr, true);
VM::Class* ctx = g_vmContext->getContextClass();
Array iterArray = obj->o_toIterArray(ctx ? ctx->nameRef() : empty_string,
true);
ArrayData* ad = iterArray.detach();
MArrayIter& mi = marr();
(void) new (&mi) MArrayIter(ad);
+41 -72
Ver Arquivo
@@ -54,6 +54,41 @@ int64_t f_connection_timeout() {
return f_connection_status() == k_CONNECTION_TIMEOUT;
}
static VM::Class* getClassByName(const char* name, int len) {
VM::Class* cls = nullptr;
// translate "self" or "parent"
if (len == 4 && !memcmp(name, "self", 4)) {
cls = g_vmContext->getContextClass();
if (!cls) {
throw FatalErrorException("Cannot access self:: "
"when no class scope is active");
}
} else if (len == 6 && !memcmp(name, "parent", 6)) {
cls = g_vmContext->getParentContextClass();
if (!cls) {
throw FatalErrorException("Cannot access parent");
}
} else if (len == 6 && !memcmp(name, "static", 6)) {
CallerFrame cf;
auto ar = cf();
if (ar) {
if (ar->hasThis()) {
cls = ar->getThis()->getVMClass();
} else if (ar->hasClass()) {
cls = ar->getClass();
}
}
if (!cls) {
throw FatalErrorException("Cannot access static:: "
"when no class scope is active");
}
} else {
String className(name, len, CopyString);
cls = VM::Unit::loadClass(className.get());
}
return cls;
}
Variant f_constant(CStrRef name) {
if (!name.get()) return null;
const char *data = name.data();
@@ -63,26 +98,7 @@ Variant f_constant(CStrRef name) {
// class constant
int classNameLen = colon - data;
char *constantName = colon + 2;
String className(data, classNameLen, CopyString);
// translate "self" or "parent"
if (className == "self") {
String this_class = g_vmContext->getContextClassName();
if (this_class.empty()) {
throw FatalErrorException("Cannot access self:: "
"when no class scope is active");
} else {
className = this_class;
}
} else if (className == "parent") {
String parent_class =g_vmContext->getParentContextClassName();
if (parent_class.empty()) {
throw FatalErrorException("Cannot access parent");
} else {
className = parent_class;
}
}
VM::Class* cls = VM::Unit::loadClass(className.get());
VM::Class* cls = getClassByName(data, classNameLen);
if (cls) {
String cnsName(constantName, data + len - constantName, CopyString);
TypedValue* tv = cls->clsCnsGet(cnsName.get());
@@ -123,59 +139,12 @@ bool f_defined(CStrRef name, bool autoload /* = true */) {
// class constant
int classNameLen = colon - data;
char *constantName = colon + 2;
String className(data, classNameLen, CopyString);
// translate "self" or "parent" or "static"
if (className == "self") {
String this_class = g_vmContext->getContextClassName();
if (this_class.empty()) {
throw FatalErrorException("Cannot access self:: "
"when no class scope is active");
} else {
className = this_class;
}
} else if (className == "parent") {
String parent_class = g_vmContext->getParentContextClassName();
if (parent_class.empty()) {
throw FatalErrorException("Cannot access parent");
} else {
className = parent_class;
}
} else if (className == "static") {
CallerFrame cf;
auto ar = cf();
if (ar) {
HPHP::VM::Class* cls;
if (ar->hasThis()) {
cls = ar->getThis()->getVMClass();
} else if (ar->hasClass()) {
cls = ar->getClass();
} else {
cls = NULL;
}
if (cls) {
className = cls->nameRef();
} else {
throw FatalErrorException("Cannot access static:: "
"when no class scope is active");
}
}
}
if (class_exists(className)) { // taking care of volatile class
const ClassInfo *info;
for (String parentClass = className;
!parentClass.empty();
parentClass = info->getParentClass()) {
info = ClassInfo::FindClass(parentClass);
if (!info) {
assert(false);
}
if (info->hasConstant(constantName)) return true;
}
return false;
} else {
return false;
VM::Class* cls = getClassByName(data, classNameLen);
if (cls) {
String cnsName(constantName, data + len - constantName, CopyString);
return cls->clsCnsGet(cnsName.get());
}
return false;
} else {
// system/uniquely defined scalar constant
if (ClassInfo::FindConstant(name)) return true;
+1 -1
Ver Arquivo
@@ -16,7 +16,7 @@ if (!defined('GLOBAL_SYMBOL_REDECLARED_CLASS')) {define('GLOBAL_SYMBOL_REDECLARE
if (!defined('GLOBAL_SYMBOL_REDECLARED_FUNCTION')) {define('GLOBAL_SYMBOL_REDECLARED_FUNCTION', 5);}
if (!defined('GLOBAL_SYMBOL_STATIC_VARIABLE')) {define('GLOBAL_SYMBOL_STATIC_VARIABLE', 1);}
if (!defined('HPHP_TRIM_CHARLIST')) {define('HPHP_TRIM_CHARLIST', ' \n\r\t\v' . "\0" . '');}
if (!defined('HPHP_VERSION')) {define('HPHP_VERSION', '1.0.0');}
if (!defined('HPHP_VERSION')) {define('HPHP_VERSION', '2.0.1');}
if (!defined('INI_SCANNER_NORMAL')) {define('INI_SCANNER_NORMAL', 0);}
if (!defined('INI_SCANNER_RAW')) {define('INI_SCANNER_RAW', 1);}
if (!defined('PHP_VERSION')) {define('PHP_VERSION', '5.3.3.hiphop');}
+9 -32
Ver Arquivo
@@ -1425,46 +1425,22 @@ ObjectData* VMExecutionContext::getThis() {
return nullptr;
}
CStrRef VMExecutionContext::getContextClassName() {
Class* VMExecutionContext::getContextClass() {
VMRegAnchor _;
ActRec* ar = getFP();
assert(ar != nullptr);
if (ar->skipFrame()) {
ar = getPrevVMState(ar);
if (!ar) return empty_string;
}
if (ar->hasThis()) {
return ar->getThis()->o_getClassName();
} else if (ar->hasClass()) {
return ar->getClass()->nameRef();
} else {
return empty_string;
if (!ar) return nullptr;
}
return ar->m_func->cls();
}
CStrRef VMExecutionContext::getParentContextClassName() {
VMRegAnchor _;
ActRec* ar = getFP();
assert(ar != nullptr);
if (ar->skipFrame()) {
ar = getPrevVMState(ar);
if (!ar) return empty_string;
}
if (ar->hasThis()) {
const Class* cls = ar->getThis()->getVMClass();
if (cls->parent() == nullptr) {
return empty_string;
}
return cls->parent()->nameRef();
} else if (ar->hasClass()) {
const Class* cls = ar->getClass();
if (cls->parent() == nullptr) {
return empty_string;
}
return cls->parent()->nameRef();
} else {
return empty_string;
Class* VMExecutionContext::getParentContextClass() {
if (Class* ctx = getContextClass()) {
return ctx->parent();
}
return nullptr;
}
CStrRef VMExecutionContext::getContainingFileName() {
@@ -2056,7 +2032,8 @@ void VMExecutionContext::invokeFunc(TypedValue* retval,
// If this is a method, either this_ or cls must be non-NULL
assert(!f->preClass() || (this_ || cls));
// If this is a static method, this_ must be NULL
assert(!(f->attrs() & HPHP::VM::AttrStatic) || (!this_));
assert(!(f->attrs() & HPHP::VM::AttrStatic && !f->isClosureBody()) ||
(!this_));
// invName should only be non-NULL if we are calling __call or
// __callStatic
assert(!invName || f->name()->isame(s___call.get()) ||
+7 -25
Ver Arquivo
@@ -222,26 +222,6 @@ pathloop:
}
}
ConditionCode cmpOpToCC(Opcode opc) {
switch (opc) {
case OpGt: return CC_G;
case OpGte: return CC_GE;
case OpLt: return CC_L;
case OpLte: return CC_LE;
case OpEq: return CC_E;
case OpNeq: return CC_NE;
case OpSame: return CC_E;
case OpNSame: return CC_NE;
case InstanceOf: return CC_NZ;
case NInstanceOf: return CC_Z;
case InstanceOfBitmask: return CC_NZ;
case NInstanceOfBitmask: return CC_Z;
case IsType: return CC_NZ;
case IsNType: return CC_Z;
default: always_assert(0);
}
}
const char* getContextName(Class* ctx) {
return ctx ? ctx->name()->data() : ":anonymous:";
}
@@ -534,7 +514,7 @@ void CodeGenerator::cgJcc(IRInstruction* inst) {
SSATmp* src1 = inst->getSrc(0);
SSATmp* src2 = inst->getSrc(1);
Opcode opc = inst->getOpcode();
ConditionCode cc = cmpOpToCC(queryJmpToQueryOp(opc));
ConditionCode cc = queryJmpToCC(opc);
Type src1Type = src1->getType();
Type src2Type = src2->getType();
@@ -1467,10 +1447,12 @@ void CodeGenerator::cgInstanceOf(IRInstruction* inst) {
void CodeGenerator::cgNInstanceOf(IRInstruction* inst) {
// TODO(#2058865): having NInstanceOf is no better than InstanceOf
// followed by boolean Not opcode.
emitInstanceCheck(inst, inst->getDst()->getReg());
PhysReg dstReg = inst->getDst()->getReg();
emitInstanceCheck(inst, dstReg);
Reg8 dr((int(dstReg)));
auto& a = m_as;
a. testb (al, al);
a. setz (al);
a. testb (dr, dr);
a. setz (dr);
}
void CodeGenerator::cgJmpInstanceOf(IRInstruction* inst) {
@@ -2251,7 +2233,7 @@ void CodeGenerator::cgExitTrace(IRInstruction* inst) {
// Patch the original jcc;jmp, don't emit another
IRInstruction* jcc = toSmash->getInstruction();
Opcode opc = jcc->getOpcode();
ConditionCode cc = cmpOpToCC(queryJmpToQueryOp(opc));
ConditionCode cc = queryJmpToCC(opc);
uint64_t taken = pc->getValInt();
uint64_t notTaken = notTakenPC->getValInt();
@@ -772,14 +772,10 @@ void HhbcTranslator::emitContDone() {
}
void HhbcTranslator::emitContNext() {
emitInterpOneOrPunt(Type::None);
return;
// Task #2140912: Fix and re-enable this
assert(getCurClass());
SSATmp* cont = m_tb->genLdThis(nullptr);
m_tb->genContPreNext(cont, getExitSlowTrace());
m_tb->genSetPropCell(cont, CONTOFF(m_received), m_tb->genDefUninit());
m_tb->genSetPropCell(cont, CONTOFF(m_received), m_tb->genDefInitNull());
}
void HhbcTranslator::emitContSendImpl(bool raise) {
+47 -1
Ver Arquivo
@@ -629,14 +629,60 @@ inline Opcode queryToJmpOp(Opcode opc) {
}
inline bool isQueryJmpOp(Opcode opc) {
return opc >= JmpGt && opc <= JmpIsNType;
switch (opc) {
case JmpGt:
case JmpGte:
case JmpLt:
case JmpLte:
case JmpEq:
case JmpNeq:
case JmpSame:
case JmpNSame:
case JmpInstanceOf:
case JmpNInstanceOf:
case JmpInstanceOfBitmask:
case JmpNInstanceOfBitmask:
case JmpIsType:
case JmpIsNType:
case JmpZero:
case JmpNZero:
return true;
default:
return false;
}
}
inline Opcode queryJmpToQueryOp(Opcode opc) {
assert(isQueryJmpOp(opc));
assert(opc != JmpZero && opc != JmpNZero);
return Opcode(OpGt + (opc - JmpGt));
}
inline ConditionCode queryJmpToCC(Opcode opc) {
assert(isQueryJmpOp(opc));
switch (opc) {
case JmpGt: return CC_G;
case JmpGte: return CC_GE;
case JmpLt: return CC_L;
case JmpLte: return CC_LE;
case JmpEq: return CC_E;
case JmpNeq: return CC_NE;
case JmpSame: return CC_E;
case JmpNSame: return CC_NE;
case JmpInstanceOf: return CC_NZ;
case JmpNInstanceOf: return CC_Z;
case JmpInstanceOfBitmask: return CC_NZ;
case JmpNInstanceOfBitmask: return CC_Z;
case JmpIsType: return CC_NZ;
case JmpIsNType: return CC_Z;
case JmpZero: return CC_Z;
case JmpNZero: return CC_NZ;
default:
not_reached();
}
}
/*
* Right now branch fusion is too indiscriminate to handle fusing
* with potentially expensive-to-repeat operations. TODO(#2053369)
+1 -4
Ver Arquivo
@@ -23,10 +23,7 @@ namespace HPHP { namespace VM { namespace JIT {
// These are the conditional branches supported for direct branch
// to their target trace at TraceExit, TraceExitType::NormalCc
static bool jccCanBeDirectExit(Opcode opc) {
// JmpGt .. JmpNSame are contiguous and all use cgJcc
return (JmpGt <= opc && opc <= JmpNSame) ||
opc == JmpInstanceOf || opc == JmpNInstanceOf ||
opc == JmpInstanceOfBitmask || opc == JmpNInstanceOfBitmask;
return isQueryJmpOp(opc) && (opc != JmpIsType) && (opc != JmpIsNType);
// TODO(#2053369): JmpIsType, etc
}
+28 -22
Ver Arquivo
@@ -505,28 +505,30 @@ SSATmp* Simplifier::simplifyNot(SSATmp* src) {
} \
} while (0)
#define SIMPLIFY_COMMUTATIVE(OP, NAME) do { \
SIMPLIFY_CONST(OP); \
if (src1->isConst() && !src2->isConst()) { \
return m_tb->gen##NAME(src2, src1); \
} \
IRInstruction* inst1 = src1->getInstruction(); \
IRInstruction* inst2 = src2->getInstruction(); \
if (inst1->getOpcode() == Op##NAME && inst1->getSrc(1)->isConst()) { \
/* (X + C1) + C2 --> X + C3 */ \
if (src2->isConst()) { \
int64_t right = inst1->getSrc(1)->getValInt(); \
right OP##= src2->getValInt(); \
return m_tb->gen##NAME(inst1->getSrc(0), genDefInt(right)); \
} \
/* (X + C1) + (Y + C2) --> X + Y + C3 */ \
if (inst2->getOpcode() == Op##NAME && inst2->getSrc(1)->isConst()) { \
int64_t right = inst1->getSrc(1)->getValInt(); \
right OP##= inst2->getSrc(1)->getValInt(); \
SSATmp* left = m_tb->gen##NAME(inst1->getSrc(0), inst2->getSrc(0)); \
return m_tb->gen##NAME(left, genDefInt(right)); \
} \
} \
#define SIMPLIFY_COMMUTATIVE(OP, NAME) do { \
SIMPLIFY_CONST(OP); \
if (src1->isConst() && !src2->isConst()) { \
return m_tb->gen##NAME(src2, src1); \
} \
if (src1->isA(Type::Int) && src2->isA(Type::Int)) { \
IRInstruction* inst1 = src1->getInstruction(); \
IRInstruction* inst2 = src2->getInstruction(); \
if (inst1->getOpcode() == Op##NAME && inst1->getSrc(1)->isConst()) { \
/* (X + C1) + C2 --> X + C3 */ \
if (src2->isConst()) { \
int64_t right = inst1->getSrc(1)->getValInt(); \
right OP##= src2->getValInt(); \
return m_tb->gen##NAME(inst1->getSrc(0), genDefInt(right)); \
} \
/* (X + C1) + (Y + C2) --> X + Y + C3 */ \
if (inst2->getOpcode() == Op##NAME && inst2->getSrc(1)->isConst()) { \
int64_t right = inst1->getSrc(1)->getValInt(); \
right OP##= inst2->getSrc(1)->getValInt(); \
SSATmp* left = m_tb->gen##NAME(inst1->getSrc(0), inst2->getSrc(0)); \
return m_tb->gen##NAME(left, genDefInt(right)); \
} \
} \
} \
} while (0)
#define SIMPLIFY_DISTRIBUTIVE(OUTOP, INOP, OUTNAME, INNAME) do { \
@@ -766,6 +768,10 @@ SSATmp* Simplifier::simplifyCmp(Opcode opName, SSATmp* src1, SSATmp* src2) {
if (src1->getType() == Type::Obj && src2->getType() == Type::Obj) {
return nullptr;
}
// for arrays, don't simplify Same to Eq
if (src1->getType() == Type::Arr && src2->getType() == Type::Arr) {
return nullptr;
}
// Type is neither a string nor an object - simplify to OpEq/OpNeq
if (opName == OpSame) {
return m_tb->genCmp(OpEq, src1, src2);
@@ -341,7 +341,7 @@ SSATmp* HhbcTranslator::VectorTranslator::getInput(unsigned i) {
// as what Transl::Translator came up with.
auto t = Type::fromRuntimeType(dl.rtt);
if (!val->isA(t)) {
FTRACE(0, "{}: hhir stack has a {} where Translator had a {}\n",
FTRACE(1, "{}: hhir stack has a {} where Translator had a {}\n",
__func__, val->getType().toString(), t.toString());
// They'd better not be completely unrelated types...
assert(t.subtypeOf(val->getType()));
+22 -2
Ver Arquivo
@@ -32,7 +32,11 @@
typedef __sighandler_t *sighandler_t;
# define RIP_REGISTER(v) (v).mc_rip
#else
# define RIP_REGISTER(v) (v).gregs[REG_RIP]
# if defined(__x86_64__)
# define RIP_REGISTER(v) (v).gregs[REG_RIP]
# elif defined(__AARCH64EL__)
# define RIP_REGISTER(v) (v).pc
# endif
#endif
#include <boost/bind.hpp>
@@ -3059,6 +3063,22 @@ struct DepthGuard { bool depthOne() const { return false; } };
#endif
/*
* enterTCHelper does not save callee-saved registers except %rbp. This means
* when we call it from C++, we have to tell gcc to clobber all the other
* callee-saved registers.
*/
#if defined(__x86_64__)
# define CALLEE_SAVED_BARRIER() \
asm volatile("" : : : "rbx", "r12", "r13", "r14", "r15")
#elif defined(__AARCH64EL__)
# define CALLEE_SAVED_BARRIER() \
asm volatile("" : : : "x19", "x20", "x21", "x22", "x23", "x24", "x25", \
"x26", "x27", "x28")
#else
# error What are the callee-saved registers on your system?
#endif
/*
* enterTCHelper
*
@@ -9067,7 +9087,7 @@ TranslatorX64::translateFPushObjMethodD(const Tracelet &t,
}
if (func) {
if (func->attrs() & AttrStatic) {
if (func->attrs() & AttrStatic && !func->isClosureBody()) {
if (func->attrs() & AttrPrivate) {
emitVStackStoreImm(a, i, uintptr_t(curFunc()->cls()) | 1,
thisOff, sz::qword);
+2 -2
Ver Arquivo
@@ -457,7 +457,7 @@ const int64_t k_GRAPHEME_EXTR_MAXBYTES = 1;
const int64_t k_GRAPHEME_EXTR_MAXCHARS = 2;
const int64_t k_HASH_HMAC = 1;
extern const StaticString k_HPHP_TRIM_CHARLIST("\n\r\t\v\000 ",6);
extern const StaticString k_HPHP_VERSION("1.0.0",5);
extern const StaticString k_HPHP_VERSION("2.0.1",5);
const int64_t k_HTML_ENTITIES = 1;
const int64_t k_HTML_SPECIALCHARS = 0;
extern const StaticString k_ICONV_IMPL("glibc",5);
@@ -17963,7 +17963,7 @@ const char *g_class_map[] = {
"GRAPHEME_EXTR_MAXCHARS", (const char*)4, "i:2;",
"HASH_HMAC", (const char*)4, "i:1;",
"HPHP_TRIM_CHARLIST", (const char*)13, "s:6:\"\n\r\t\v\000 \";",
"HPHP_VERSION", (const char*)12, "s:5:\"1.0.0\";",
"HPHP_VERSION", (const char*)12, "s:5:\"2.0.1\";",
"HTML_ENTITIES", (const char*)4, "i:1;",
"HTML_SPECIALCHARS", (const char*)4, "i:0;",
"ICONV_IMPL", (const char*)12, "s:5:\"glibc\";",
+1 -1
Ver Arquivo
@@ -445,7 +445,7 @@ define('GRAPHEME_EXTR_MAXBYTES', 1);
define('GRAPHEME_EXTR_MAXCHARS', 2);
define('HASH_HMAC', 1);
define('HPHP_TRIM_CHARLIST', "\n\r\t\v\000 ");
define('HPHP_VERSION', "1.0.0");
define('HPHP_VERSION', "2.0.1");
define('HTML_ENTITIES', 1);
define('HTML_SPECIALCHARS', 0);
define('ICONV_IMPL', "glibc");
+1 -1
Ver Arquivo
@@ -2670,7 +2670,7 @@ DefineConstant(
DefineConstant(
array(
'name' => "HPHP_VERSION",
'value' => "1.0.0",
'value' => "2.0.1",
));
DefineConstant(
+255
Ver Arquivo
@@ -9659,6 +9659,236 @@ bool TestCodeRun::TestCollectionClasses() {
"bool(false)\n"
);
{
HipHopSyntax w1(this);
MVCRO("<?php\n"
"function f() {\n"
" $v = Vector {'a', 'b', 'c'};\n"
" $m = new Map($v);\n"
" var_dump($m);\n"
" $sm = new StableMap($m);\n"
" var_dump($sm);\n"
"}\n"
"function g() {\n"
" $m = Map {'a' => 1, 2 => 'b'};\n"
" $v = new Vector($m);\n"
" var_dump($v);\n"
"}\n"
"function h() {\n"
" $arr1 = array(11, 22, 33);\n"
" var_dump(new Vector($arr1));\n"
" var_dump(new Map($arr1));\n"
" $arr2 = array('a' => 1, 2 => 'b');\n"
" var_dump(new Vector($arr2));\n"
" var_dump(new StableMap($arr2));\n"
"}\n"
"function gen() {\n"
" yield 42;\n"
" yield 72;\n"
"}\n"
"function j() {\n"
" $v = new Vector(gen());\n"
" var_dump($v);\n"
"}\n"
"f();\n"
"g();\n"
"h();\n"
"j();\n"
,
"object(Map)#2 (3) {\n"
" [0]=>\n"
" string(1) \"a\"\n"
" [1]=>\n"
" string(1) \"b\"\n"
" [2]=>\n"
" string(1) \"c\"\n"
"}\n"
"object(StableMap)#3 (3) {\n"
" [0]=>\n"
" string(1) \"a\"\n"
" [1]=>\n"
" string(1) \"b\"\n"
" [2]=>\n"
" string(1) \"c\"\n"
"}\n"
"object(Vector)#2 (2) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" string(1) \"b\"\n"
"}\n"
"object(Vector)#1 (3) {\n"
" [0]=>\n"
" int(11)\n"
" [1]=>\n"
" int(22)\n"
" [2]=>\n"
" int(33)\n"
"}\n"
"object(Map)#1 (3) {\n"
" [0]=>\n"
" int(11)\n"
" [1]=>\n"
" int(22)\n"
" [2]=>\n"
" int(33)\n"
"}\n"
"object(Vector)#1 (2) {\n"
" [0]=>\n"
" int(1)\n"
" [1]=>\n"
" string(1) \"b\"\n"
"}\n"
"object(StableMap)#1 (2) {\n"
" [\"a\"]=>\n"
" int(1)\n"
" [2]=>\n"
" string(1) \"b\"\n"
"}\n"
"object(Vector)#1 (2) {\n"
" [0]=>\n"
" int(42)\n"
" [1]=>\n"
" int(72)\n"
"}\n"
);
MVCRO("<?hh\n"
"function g((string,int,string) $t) {}\n"
"class C {\n"
" public $t = Tuple {'foo', 42, '!'};\n"
"}\n"
"function f() {\n"
" $t = Tuple {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
" 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
" 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};\n"
" var_dump(count($t));\n"
" var_dump($t->count());\n"
" var_dump($t->isEmpty());\n"
" echo \"==========\\n\";\n"
" $c = new C;\n"
" $t = $c->t;\n"
" var_dump(count($t));\n"
" var_dump($t->count());\n"
" var_dump($t->isEmpty());\n"
" g($t);\n"
" echo \"==========\\n\";\n"
" foreach ($t as $k => $v) {\n"
" var_dump($k, $v);\n"
" }\n"
" echo \"==========\\n\";\n"
" var_dump($t[0], $t[1], $t[2]);\n"
" echo \"==========\\n\";\n"
" var_dump($t->at(0), $t->at(1), $t->at(2));\n"
" echo \"==========\\n\";\n"
" var_dump($t->get(0), $t->get(1), $t->get(2), $t->get(3));\n"
" echo \"==========\\n\";\n"
" var_dump((array)$t);\n"
" echo \"==========\\n\";\n"
" var_dump(serialize($t));\n"
" var_dump(unserialize(serialize($t)));\n"
" echo \"==========\\n\";\n"
" var_dump($t->count());\n"
" echo \"==========\\n\";\n"
" var_dump($t->getIterator() instanceof Iterator);\n"
" var_dump($t->getIterator() instanceof KeyedIterator);\n"
" foreach ($t->getIterator() as $k => $v) {\n"
" var_dump($k, $v);\n"
" }\n"
" echo \"==========\\n\";\n"
" var_dump((array)$t);\n"
" var_dump($t->toArray());\n"
" echo \"==========\\n\";\n"
" var_dump(clone $t);\n"
"}\n"
"f();\n"
,
"int(32)\n"
"int(32)\n"
"bool(false)\n"
"==========\n"
"int(3)\n"
"int(3)\n"
"bool(false)\n"
"==========\n"
"int(0)\n"
"string(3) \"foo\"\n"
"int(1)\n"
"int(42)\n"
"int(2)\n"
"string(1) \"!\"\n"
"==========\n"
"string(3) \"foo\"\n"
"int(42)\n"
"string(1) \"!\"\n"
"==========\n"
"string(3) \"foo\"\n"
"int(42)\n"
"string(1) \"!\"\n"
"==========\n"
"string(3) \"foo\"\n"
"int(42)\n"
"string(1) \"!\"\n"
"NULL\n"
"==========\n"
"array(3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"==========\n"
"string(39) \"V:5:\"Tuple\":3:{s:3:\"foo\";i:42;s:1:\"!\";}\"\n"
"object(Tuple)#6 (3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"==========\n"
"int(3)\n"
"==========\n"
"bool(true)\n"
"bool(true)\n"
"int(0)\n"
"string(3) \"foo\"\n"
"int(1)\n"
"int(42)\n"
"int(2)\n"
"string(1) \"!\"\n"
"==========\n"
"array(3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"array(3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"==========\n"
"object(Tuple)#6 (3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
);
}
return true;
}
@@ -18832,6 +19062,31 @@ bool TestCodeRun::TestClassConstant() {
" var_dump($param->getDefaultValue());"
"}");
MVCR("<?php "
"class W {"
" const FOO = 0;"
"}"
"class X extends W {"
" const FOO = 1;"
" static function foo() {"
" var_dump(constant('self::FOO'));"
" var_dump(constant('parent::FOO'));"
" var_dump(constant('static::FOO'));"
" var_dump(defined('self::FOO'));"
" var_dump(defined('parent::FOO'));"
" var_dump(defined('static::FOO'));"
" var_dump(defined('self::BAR'));"
" var_dump(defined('parent::BAR'));"
" var_dump(defined('static::BAR'));"
" }"
"}"
"class Y extends X {"
" const FOO = 2;"
" const BAR = 1;"
"}"
"X::foo();"
"Y::foo();");
return true;
}
+4
Ver Arquivo
@@ -125,5 +125,9 @@ bool TestExtBzip2::test_bzdecompress() {
ret = f_bzdecompress(ret);
ret = f_bzdecompress(ret);
VS(ret, str);
str = StringUtil::Repeat("x", 1000);
ret = f_bzcompress(str);
ret = f_bzdecompress(ret);
VS(ret, str);
return Count(true);
}
+40
Ver Arquivo
@@ -0,0 +1,40 @@
<?php
class A {
private $c = 1;
function b() {
$a = function () {
var_dump($this);
};
$a();
$a = static function () {
var_dump($this);
};
$a();
}
static function c() {
$a = function () {
var_dump($this);
};
$a();
$a = static function () {
var_dump($this);
};
$a();
}
static function d() {
var_dump(array_map(function($a) { return $a; }, array(1,2,3)));
}
}
(new A)->b();
A::b();
(new A)->c();
A::c();
(new A)->d();
A::d();
+34
Ver Arquivo
@@ -0,0 +1,34 @@
object(A)#1 (1) {
["c":"A":private]=>
int(1)
}
HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 13
NULL
HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 8
NULL
HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 13
NULL
HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 20
NULL
HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 25
NULL
HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 20
NULL
HipHop Notice: Undefined variable: this in hphp/test/vm/closure_static.php on line 25
NULL
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
+8
Ver Arquivo
@@ -0,0 +1,8 @@
<?php
var_dump(iconv_mime_decode(
'=?utf-8?Q?...=20.....=3A=20...=20.....=20....=20'.
'.......=20...=20.....=2C=20....=20.......=E2=80=99s'.
'=20....=20......=20..=20...=E2=80=99s=20....=20.....'.
'=3F=2C=20...=20.......=20..=20.......=20...'.
'=20........?=', 2, 'UTF-8'));
+1
Ver Arquivo
@@ -0,0 +1 @@
string(133) "... .....: ... ..... .... ....... ... ....., .... .......s .... ...... .. ...s .... .....?, ... ....... .. ....... ... ........"
+1 -1
Ver Arquivo
@@ -1 +1 @@
HPHP_VERSION(1.000)
HPHP_VERSION(2.0.1)