Comparar commits
5 Commits
HHVM-2.2
...
HPHP-2.0.0
| Autor | SHA1 | Data | |
|---|---|---|---|
| 8b23419a37 | |||
| af5623b4fc | |||
| b51003b5aa | |||
| 5f019f5b43 | |||
| 35e347efa5 |
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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.0');}
|
||||
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');}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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.0",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.0\";",
|
||||
"HTML_ENTITIES", (const char*)4, "i:1;",
|
||||
"HTML_SPECIALCHARS", (const char*)4, "i:0;",
|
||||
"ICONV_IMPL", (const char*)12, "s:5:\"glibc\";",
|
||||
|
||||
@@ -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.0");
|
||||
define('HTML_ENTITIES', 1);
|
||||
define('HTML_SPECIALCHARS', 0);
|
||||
define('ICONV_IMPL', "glibc");
|
||||
|
||||
@@ -2670,7 +2670,7 @@ DefineConstant(
|
||||
DefineConstant(
|
||||
array(
|
||||
'name' => "HPHP_VERSION",
|
||||
'value' => "1.0.0",
|
||||
'value' => "2.0.0",
|
||||
));
|
||||
|
||||
DefineConstant(
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
HPHP_VERSION(1.000)
|
||||
HPHP_VERSION(2.0.0)
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário