Introduce YieldExpression
Unhack the parser and introduce YieldExpression that emits the
equivalent set of opcodes that were emitted by bunch of
expressions/statements generated by parser before.
YieldExpression expects evaluation stack to contain just the value
being yielded, so {,List}AssignmentExpression need to evaluate RHS
first. The previous code had the same behavior.
This will let us consolidate continuation-related opcodes and make
them less tied with continuation objects.
Esse commit está contido em:
@@ -1551,6 +1551,7 @@ ExpressionPtr AliasManager::canonicalizeNode(
|
||||
cur = next;
|
||||
}
|
||||
if (!m_inCall &&
|
||||
!last->is(Expression::KindOfYieldExpression) &&
|
||||
ae->isUnused() && m_accessList.isLast(ae) &&
|
||||
!e->hasAnyContext(Expression::AccessContext |
|
||||
Expression::ObjectContext |
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include <compiler/expression/simple_function_call.h>
|
||||
#include <compiler/expression/static_member_expression.h>
|
||||
#include <compiler/expression/unary_op_expression.h>
|
||||
#include <compiler/expression/yield_expression.h>
|
||||
|
||||
#include <compiler/statement/break_statement.h>
|
||||
#include <compiler/statement/case_statement.h>
|
||||
@@ -2180,6 +2181,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
ReturnStatementPtr r(static_pointer_cast<ReturnStatement>(node));
|
||||
bool retV = false;
|
||||
if (m_curFunc->isGenerator()) {
|
||||
// used by yield break
|
||||
e.ContExit();
|
||||
return false;
|
||||
}
|
||||
@@ -3152,18 +3154,6 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
inputIsAnObject(0);
|
||||
e.UnpackCont();
|
||||
return true;
|
||||
} else if (call->isCompilerCallToFunction("hphp_pack_continuation")) {
|
||||
assert(params && params->getCount() == 3);
|
||||
ExpressionPtr label = (*params)[1];
|
||||
Variant lVar;
|
||||
UNUSED bool isScalar = label->getScalarValue(lVar);
|
||||
assert(isScalar && lVar.isInteger());
|
||||
|
||||
visit((*params)[2]);
|
||||
emitConvertToCell(e);
|
||||
inputIsAnObject(1);
|
||||
e.PackCont(lVar.asInt64Val());
|
||||
return false;
|
||||
} else if (call->isCompilerCallToFunction("hphp_create_continuation")) {
|
||||
assert(params && (params->getCount() == 3 ||
|
||||
params->getCount() == 4));
|
||||
@@ -3176,15 +3166,6 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
bool callGetArgs = params->getCount() == 4;
|
||||
e.CreateCont(callGetArgs, nameStr);
|
||||
return true;
|
||||
} else if (call->isCompilerCallToFunction("hphp_continuation_raised")) {
|
||||
inputIsAnObject(0);
|
||||
e.ContRaised();
|
||||
return false;
|
||||
} else if (
|
||||
call->isCompilerCallToFunction("hphp_continuation_receive")) {
|
||||
inputIsAnObject(0);
|
||||
e.ContReceive();
|
||||
return true;
|
||||
} else if (call->isCompilerCallToFunction("hphp_continuation_done")) {
|
||||
inputIsAnObject(0);
|
||||
e.ContDone();
|
||||
@@ -3836,6 +3817,39 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
|
||||
|
||||
return true;
|
||||
}
|
||||
case Expression::KindOfYieldExpression: {
|
||||
YieldExpressionPtr y(static_pointer_cast<YieldExpression>(node));
|
||||
assert(m_evalStack.size() == 0);
|
||||
|
||||
// evaluate expression passed to yield
|
||||
visit(y->getExpression());
|
||||
emitConvertToCell(e);
|
||||
|
||||
// pack continuation and set the return label
|
||||
assert(m_evalStack.size() == 1);
|
||||
m_metaInfo.addKnownDataType(
|
||||
KindOfObject, false, m_ue.bcPos(), false, 1);
|
||||
e.PackCont(y->getLabel());
|
||||
|
||||
// transfer control
|
||||
assert(m_evalStack.size() == 0);
|
||||
e.ContExit();
|
||||
|
||||
// emit return label
|
||||
StringData* nName = StringData::GetStaticString(
|
||||
YIELD_LABEL_PREFIX + boost::lexical_cast<std::string>(y->getLabel()));
|
||||
Label& lab = m_gotoLabels[nName];
|
||||
lab.set(e);
|
||||
|
||||
// check for exception and retrieve result
|
||||
assert(m_evalStack.size() == 0);
|
||||
m_metaInfo.addKnownDataType(
|
||||
KindOfObject, false, m_ue.bcPos(), false, 0);
|
||||
e.ContReceive();
|
||||
|
||||
assert(m_evalStack.size() == 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4157,11 +4171,15 @@ void EmitterVisitor::emitVGet(Emitter& e) {
|
||||
}
|
||||
|
||||
Id EmitterVisitor::emitVisitAndSetUnnamedL(Emitter& e, ExpressionPtr exp) {
|
||||
Id tempLocal = m_curFunc->allocUnnamedLocal();
|
||||
emitVirtualLocal(tempLocal);
|
||||
visit(exp);
|
||||
emitConvertToCell(e);
|
||||
emitSet(e);
|
||||
|
||||
// HACK: emitVirtualLocal would pollute m_evalStack before visiting exp,
|
||||
// YieldExpression won't be happy
|
||||
Id tempLocal = m_curFunc->allocUnnamedLocal();
|
||||
e.getUnitEmitter().emitOp(OpSetL);
|
||||
e.getUnitEmitter().emitIVA(tempLocal);
|
||||
|
||||
emitPop(e);
|
||||
return tempLocal;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ class Variant;
|
||||
x(ConstantExpression, Const), \
|
||||
x(EncapsListExpression, None), \
|
||||
x(ClosureExpression, None), \
|
||||
x(YieldExpression, None), \
|
||||
x(UserAttribute, None)
|
||||
|
||||
class Expression : public Construct {
|
||||
|
||||
@@ -75,6 +75,7 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
|
||||
case Expression::KindOfAssignmentExpression:
|
||||
case Expression::KindOfExpressionList:
|
||||
case Expression::KindOfIncludeExpression:
|
||||
case Expression::KindOfYieldExpression:
|
||||
return ListAssignment::Regular;
|
||||
|
||||
case Expression::KindOfListAssignment:
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <compiler/expression/yield_expression.h>
|
||||
#include <compiler/analysis/function_scope.h>
|
||||
|
||||
using namespace HPHP;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// constructors/destructors
|
||||
|
||||
YieldExpression::YieldExpression
|
||||
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr exp, int label)
|
||||
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(YieldExpression)),
|
||||
m_exp(exp), m_label(label) {
|
||||
}
|
||||
|
||||
ExpressionPtr YieldExpression::clone() {
|
||||
YieldExpressionPtr exp(new YieldExpression(*this));
|
||||
Expression::deepCopy(exp);
|
||||
exp->m_exp = Clone(m_exp);
|
||||
exp->m_label = m_label;
|
||||
return exp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// parser functions
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static analysis functions
|
||||
|
||||
void YieldExpression::analyzeProgram(AnalysisResultPtr ar) {
|
||||
assert(getFunctionScope() && getFunctionScope()->isGenerator());
|
||||
m_exp->analyzeProgram(ar);
|
||||
}
|
||||
|
||||
ConstructPtr YieldExpression::getNthKid(int n) const {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return m_exp;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return ConstructPtr();
|
||||
}
|
||||
|
||||
int YieldExpression::getKidCount() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void YieldExpression::setNthKid(int n, ConstructPtr cp) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
m_exp = boost::dynamic_pointer_cast<Expression>(cp);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TypePtr YieldExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
|
||||
bool coerce) {
|
||||
m_exp->inferAndCheck(ar, Type::Some, false);
|
||||
return Type::Variant;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// code generation functions
|
||||
|
||||
void YieldExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
|
||||
cg_printf("yield ");
|
||||
m_exp->outputPHP(cg, ar);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| HipHop for PHP |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef __YIELD_EXPRESSION_H__
|
||||
#define __YIELD_EXPRESSION_H__
|
||||
|
||||
#include <compiler/expression/expression.h>
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_BOOST_TYPES(YieldExpression);
|
||||
|
||||
class YieldExpression : public Expression {
|
||||
public:
|
||||
YieldExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
|
||||
ExpressionPtr exp, int label);
|
||||
|
||||
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
|
||||
|
||||
ExpressionPtr getExpression() { return m_exp; }
|
||||
int getLabel() { return m_label; }
|
||||
|
||||
private:
|
||||
ExpressionPtr m_exp;
|
||||
int m_label;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
#endif // __YIELD_EXPRESSION_H__
|
||||
+17459
-17536
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+3335
-3383
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -42,6 +42,7 @@
|
||||
#include <compiler/expression/constant_expression.h>
|
||||
#include <compiler/expression/encaps_list_expression.h>
|
||||
#include <compiler/expression/closure_expression.h>
|
||||
#include <compiler/expression/yield_expression.h>
|
||||
#include <compiler/expression/user_attribute.h>
|
||||
|
||||
#include <compiler/statement/function_statement.h>
|
||||
@@ -115,8 +116,6 @@ extern void create_generator(Parser *_p, Token &out, Token ¶ms,
|
||||
const char *clsname, Token *modifiers,
|
||||
bool getArgs, Token &origGenFunc, bool isHhvm,
|
||||
Token *attr);
|
||||
extern void transform_yield(Parser *_p, Token &stmts, int index,
|
||||
Token *expr, bool assign);
|
||||
extern void transform_yield_break(Parser *_p, Token &out);
|
||||
|
||||
namespace HPHP {
|
||||
@@ -563,7 +562,8 @@ void Parser::onExprListElem(Token &out, Token *exprs, Token &expr) {
|
||||
out->exp = expList;
|
||||
}
|
||||
|
||||
void Parser::onListAssignment(Token &out, Token &vars, Token *expr) {
|
||||
void Parser::onListAssignment(Token &out, Token &vars, Token *expr,
|
||||
bool rhsFirst /* = false */) {
|
||||
ExpressionListPtr el(dynamic_pointer_cast<ExpressionList>(vars->exp));
|
||||
for (int i = 0; i < el->getCount(); i++) {
|
||||
if (dynamic_pointer_cast<FunctionCall>((*el)[i])) {
|
||||
@@ -572,7 +572,7 @@ void Parser::onListAssignment(Token &out, Token &vars, Token *expr) {
|
||||
}
|
||||
out->exp = NEW_EXP(ListAssignment,
|
||||
dynamic_pointer_cast<ExpressionList>(vars->exp),
|
||||
expr ? expr->exp : ExpressionPtr());
|
||||
expr ? expr->exp : ExpressionPtr(), rhsFirst);
|
||||
}
|
||||
|
||||
void Parser::onAListVar(Token &out, Token *list, Token *var) {
|
||||
@@ -601,12 +601,13 @@ void Parser::checkAssignThis(Token &var) {
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::onAssign(Token &out, Token &var, Token &expr, bool ref) {
|
||||
void Parser::onAssign(Token &out, Token &var, Token &expr, bool ref,
|
||||
bool rhsFirst /* = false */) {
|
||||
if (dynamic_pointer_cast<FunctionCall>(var->exp)) {
|
||||
PARSE_ERROR("Can't use return value in write context");
|
||||
}
|
||||
checkAssignThis(var);
|
||||
out->exp = NEW_EXP(AssignmentExpression, var->exp, expr->exp, ref);
|
||||
out->exp = NEW_EXP(AssignmentExpression, var->exp, expr->exp, ref, rhsFirst);
|
||||
}
|
||||
|
||||
void Parser::onAssignNew(Token &out, Token &var, Token &name, Token &args) {
|
||||
@@ -1404,14 +1405,14 @@ bool Parser::setIsGenerator() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Parser::onYield(Token &out, Token *expr, bool assign) {
|
||||
void Parser::onYield(Token &out, Token &expr) {
|
||||
if (!setIsGenerator()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionContext &funcContext = m_funcContexts.back();
|
||||
int index = ++funcContext.numYields;
|
||||
transform_yield(this, out, index, expr, assign);
|
||||
int label = ++funcContext.numYields;
|
||||
out->exp = NEW_EXP(YieldExpression, expr->exp, label);
|
||||
}
|
||||
|
||||
void Parser::onYieldBreak(Token &out) {
|
||||
|
||||
@@ -149,10 +149,12 @@ public:
|
||||
void onObjectProperty(Token &out, Token &base, Token &prop);
|
||||
void onObjectMethodCall(Token &out, Token &base, Token &prop, Token ¶ms);
|
||||
|
||||
void onListAssignment(Token &out, Token &vars, Token *expr);
|
||||
void onListAssignment(Token &out, Token &vars, Token *expr,
|
||||
bool rhsFirst = false);
|
||||
void onAListVar(Token &out, Token *list, Token *var);
|
||||
void onAListSub(Token &out, Token *list, Token &sublist);
|
||||
void onAssign(Token &out, Token &var, Token &expr, bool ref);
|
||||
void onAssign(Token &out, Token &var, Token &expr, bool ref,
|
||||
bool rhsFirst = false);
|
||||
void onAssignNew(Token &out, Token &var, Token &name, Token &args);
|
||||
void onNewObject(Token &out, Token &name, Token &args);
|
||||
void onUnaryOpExp(Token &out, Token &operand, int op, bool front);
|
||||
@@ -209,7 +211,7 @@ public:
|
||||
void onBreak(Token &out, Token *expr);
|
||||
void onContinue(Token &out, Token *expr);
|
||||
void onReturn(Token &out, Token *expr, bool checkYield = true);
|
||||
void onYield(Token &out, Token *expr, bool assign);
|
||||
void onYield(Token &out, Token &expr);
|
||||
void onYieldBreak(Token &out);
|
||||
void onGlobal(Token &out, Token &expr);
|
||||
void onGlobalVar(Token &out, Token *exprs, Token &expr);
|
||||
|
||||
@@ -3643,12 +3643,6 @@ PackCont <label id> [C] -> []
|
||||
continuation as the result of the current iteration and the continuation's
|
||||
label is set to <label id>.
|
||||
|
||||
ContRaised [] -> []
|
||||
|
||||
Check for continuation exception. If the continuation in local 0 has a
|
||||
pending exception, this instruction will throw that exception. Otherwise, it
|
||||
does nothing.
|
||||
|
||||
ContReceive [] -> [C]
|
||||
|
||||
Receive continuation value. If the continuation in local 0 has a pending
|
||||
|
||||
@@ -77,29 +77,6 @@ DefineFunction(
|
||||
'taint_observer' => false,
|
||||
));
|
||||
|
||||
DefineFunction(
|
||||
array(
|
||||
'name' => 'hphp_pack_continuation',
|
||||
'return' => array(
|
||||
'type' => null,
|
||||
),
|
||||
'args' => array(
|
||||
array(
|
||||
'name' => 'continuation',
|
||||
'type' => Object,
|
||||
),
|
||||
array(
|
||||
'name' => 'label',
|
||||
'type' => Int64,
|
||||
),
|
||||
array(
|
||||
'name' => 'value',
|
||||
'type' => Variant,
|
||||
),
|
||||
),
|
||||
'taint_observer' => false,
|
||||
));
|
||||
|
||||
DefineFunction(
|
||||
array(
|
||||
'name' => 'hphp_unpack_continuation',
|
||||
@@ -389,22 +366,6 @@ DefineFunction(
|
||||
),
|
||||
));
|
||||
|
||||
DefineFunction(
|
||||
array(
|
||||
'name' => 'raised',
|
||||
'return' => array(
|
||||
'type' => null,
|
||||
),
|
||||
));
|
||||
|
||||
DefineFunction(
|
||||
array(
|
||||
'name' => 'receive',
|
||||
'return' => array(
|
||||
'type' => Variant,
|
||||
),
|
||||
));
|
||||
|
||||
DefineFunction(
|
||||
array(
|
||||
'name' => 'getOrigFuncName',
|
||||
|
||||
@@ -40,11 +40,6 @@ p_Continuation f_hphp_create_continuation(CStrRef clsname,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void f_hphp_pack_continuation(CObjRef continuation,
|
||||
int64_t label, CVarRef value) {
|
||||
throw_fatal("Invalid call hphp_pack_continuation");
|
||||
}
|
||||
|
||||
void f_hphp_unpack_continuation(CObjRef continuation) {
|
||||
throw_fatal("Invalid call hphp_unpack_continuation");
|
||||
}
|
||||
@@ -168,14 +163,6 @@ void c_Continuation::t_raised() {
|
||||
}
|
||||
}
|
||||
|
||||
Variant c_Continuation::t_receive() {
|
||||
if (m_should_throw) {
|
||||
m_should_throw = false;
|
||||
throw_exception(m_received);
|
||||
}
|
||||
return m_received;
|
||||
}
|
||||
|
||||
String c_Continuation::t_getorigfuncname() {
|
||||
String called_class;
|
||||
if (actRec()->hasThis()) {
|
||||
|
||||
@@ -95,63 +95,6 @@ TypedValue* fg_hphp_create_continuation(HPHP::VM::ActRec *ar) {
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void HPHP::f_hphp_pack_continuation(HPHP::Object const&, long, HPHP::Variant const&)
|
||||
_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE
|
||||
|
||||
continuation => rdi
|
||||
label => rsi
|
||||
value => rdx
|
||||
*/
|
||||
|
||||
void fh_hphp_pack_continuation(Value* continuation, long label, TypedValue* value) asm("_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE");
|
||||
|
||||
TypedValue * fg1_hphp_pack_continuation(TypedValue* rv, HPHP::VM::ActRec* ar, int64_t count) __attribute__((noinline,cold));
|
||||
TypedValue * fg1_hphp_pack_continuation(TypedValue* rv, HPHP::VM::ActRec* ar, int64_t count) {
|
||||
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
|
||||
rv->m_data.num = 0LL;
|
||||
rv->m_type = KindOfNull;
|
||||
if ((args-1)->m_type != KindOfInt64) {
|
||||
tvCastToInt64InPlace(args-1);
|
||||
}
|
||||
if ((args-0)->m_type != KindOfObject) {
|
||||
tvCastToObjectInPlace(args-0);
|
||||
}
|
||||
fh_hphp_pack_continuation((Value*)(args-0), (long)(args[-1].m_data.num), (args-2));
|
||||
return rv;
|
||||
}
|
||||
|
||||
TypedValue* fg_hphp_pack_continuation(HPHP::VM::ActRec *ar) {
|
||||
TypedValue rv;
|
||||
int64_t count = ar->numArgs();
|
||||
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
|
||||
if (count == 3LL) {
|
||||
if ((args-1)->m_type == KindOfInt64 && (args-0)->m_type == KindOfObject) {
|
||||
rv.m_data.num = 0LL;
|
||||
rv.m_type = KindOfNull;
|
||||
fh_hphp_pack_continuation((Value*)(args-0), (long)(args[-1].m_data.num), (args-2));
|
||||
frame_free_locals_no_this_inl(ar, 3);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
} else {
|
||||
fg1_hphp_pack_continuation(&rv, ar, count);
|
||||
frame_free_locals_no_this_inl(ar, 3);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
}
|
||||
} else {
|
||||
throw_wrong_arguments_nr("hphp_pack_continuation", count, 3, 3, 1);
|
||||
}
|
||||
rv.m_data.num = 0LL;
|
||||
rv.m_type = KindOfNull;
|
||||
frame_free_locals_no_this_inl(ar, 3);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
return &ar->m_r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void HPHP::f_hphp_unpack_continuation(HPHP::Object const&)
|
||||
_ZN4HPHP26f_hphp_unpack_continuationERKNS_6ObjectE
|
||||
@@ -833,79 +776,6 @@ TypedValue* tg_12Continuation_raise(HPHP::VM::ActRec *ar) {
|
||||
return &ar->m_r;
|
||||
}
|
||||
|
||||
/*
|
||||
void HPHP::c_Continuation::t_raised()
|
||||
_ZN4HPHP14c_Continuation8t_raisedEv
|
||||
|
||||
this_ => rdi
|
||||
*/
|
||||
|
||||
void th_12Continuation_raised(ObjectData* this_) asm("_ZN4HPHP14c_Continuation8t_raisedEv");
|
||||
|
||||
TypedValue* tg_12Continuation_raised(HPHP::VM::ActRec *ar) {
|
||||
TypedValue rv;
|
||||
int64_t count = ar->numArgs();
|
||||
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
|
||||
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
|
||||
if (this_) {
|
||||
if (count == 0LL) {
|
||||
rv.m_data.num = 0LL;
|
||||
rv.m_type = KindOfNull;
|
||||
th_12Continuation_raised((this_));
|
||||
frame_free_locals_inl(ar, 0);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
} else {
|
||||
throw_toomany_arguments_nr("Continuation::raised", 0, 1);
|
||||
}
|
||||
} else {
|
||||
throw_instance_method_fatal("Continuation::raised");
|
||||
}
|
||||
rv.m_data.num = 0LL;
|
||||
rv.m_type = KindOfNull;
|
||||
frame_free_locals_inl(ar, 0);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
return &ar->m_r;
|
||||
}
|
||||
|
||||
/*
|
||||
HPHP::Variant HPHP::c_Continuation::t_receive()
|
||||
_ZN4HPHP14c_Continuation9t_receiveEv
|
||||
|
||||
(return value) => rax
|
||||
_rv => rdi
|
||||
this_ => rsi
|
||||
*/
|
||||
|
||||
TypedValue* th_12Continuation_receive(TypedValue* _rv, ObjectData* this_) asm("_ZN4HPHP14c_Continuation9t_receiveEv");
|
||||
|
||||
TypedValue* tg_12Continuation_receive(HPHP::VM::ActRec *ar) {
|
||||
TypedValue rv;
|
||||
int64_t count = ar->numArgs();
|
||||
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
|
||||
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
|
||||
if (this_) {
|
||||
if (count == 0LL) {
|
||||
th_12Continuation_receive((&(rv)), (this_));
|
||||
if (rv.m_type == KindOfUninit) rv.m_type = KindOfNull;
|
||||
frame_free_locals_inl(ar, 0);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
} else {
|
||||
throw_toomany_arguments_nr("Continuation::receive", 0, 1);
|
||||
}
|
||||
} else {
|
||||
throw_instance_method_fatal("Continuation::receive");
|
||||
}
|
||||
rv.m_data.num = 0LL;
|
||||
rv.m_type = KindOfNull;
|
||||
frame_free_locals_inl(ar, 0);
|
||||
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
|
||||
return &ar->m_r;
|
||||
return &ar->m_r;
|
||||
}
|
||||
|
||||
/*
|
||||
HPHP::String HPHP::c_Continuation::t_getorigfuncname()
|
||||
_ZN4HPHP14c_Continuation17t_getorigfuncnameEv
|
||||
|
||||
@@ -30,17 +30,6 @@ args => r8
|
||||
|
||||
Value* fh_hphp_create_continuation(Value* _rv, Value* clsname, Value* funcname, Value* origFuncName, Value* args) asm("_ZN4HPHP26f_hphp_create_continuationERKNS_6StringES2_S2_RKNS_5ArrayE");
|
||||
|
||||
/*
|
||||
void HPHP::f_hphp_pack_continuation(HPHP::Object const&, long, HPHP::Variant const&)
|
||||
_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE
|
||||
|
||||
continuation => rdi
|
||||
label => rsi
|
||||
value => rdx
|
||||
*/
|
||||
|
||||
void fh_hphp_pack_continuation(Value* continuation, long label, TypedValue* value) asm("_ZN4HPHP24f_hphp_pack_continuationERKNS_6ObjectElRKNS_7VariantE");
|
||||
|
||||
/*
|
||||
void HPHP::f_hphp_unpack_continuation(HPHP::Object const&)
|
||||
_ZN4HPHP26f_hphp_unpack_continuationERKNS_6ObjectE
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace HPHP {
|
||||
FORWARD_DECLARE_CLASS_BUILTIN(Continuation);
|
||||
FORWARD_DECLARE_CLASS_BUILTIN(ContinuationWaitHandle);
|
||||
p_Continuation f_hphp_create_continuation(CStrRef clsname, CStrRef funcname, CStrRef origFuncName, CArrRef args = null_array);
|
||||
void f_hphp_pack_continuation(CObjRef continuation, int64_t label, CVarRef value);
|
||||
void f_hphp_unpack_continuation(CObjRef continuation);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -63,7 +62,6 @@ class c_Continuation : public ExtObjectData {
|
||||
public: void t_send(CVarRef v);
|
||||
public: void t_raise(CVarRef v);
|
||||
public: void t_raised();
|
||||
public: Variant t_receive();
|
||||
public: String t_getorigfuncname();
|
||||
public: Variant t___clone();
|
||||
|
||||
|
||||
@@ -191,7 +191,6 @@ TypedValue* fg_get_object_vars(VM::ActRec *ar);
|
||||
TypedValue* fg_call_user_method_array(VM::ActRec *ar);
|
||||
TypedValue* fg_call_user_method(VM::ActRec *ar);
|
||||
TypedValue* fg_hphp_create_continuation(VM::ActRec *ar);
|
||||
TypedValue* fg_hphp_pack_continuation(VM::ActRec *ar);
|
||||
TypedValue* fg_hphp_unpack_continuation(VM::ActRec *ar);
|
||||
TypedValue* fg_ctype_alnum(VM::ActRec *ar);
|
||||
TypedValue* fg_ctype_alpha(VM::ActRec *ar);
|
||||
@@ -2415,8 +2414,6 @@ TypedValue* tg_12Continuation_rewind(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_valid(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_send(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_raise(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_raised(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_receive(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation_getOrigFuncName(VM::ActRec *ar);
|
||||
TypedValue* tg_12Continuation___clone(VM::ActRec *ar);
|
||||
VM::Instance* new_DummyContinuation_Instance(VM::Class*);
|
||||
@@ -3024,7 +3021,7 @@ TypedValue* tg_9XMLWriter_endDTD(VM::ActRec *ar);
|
||||
TypedValue* tg_9XMLWriter_flush(VM::ActRec *ar);
|
||||
TypedValue* tg_9XMLWriter_outputMemory(VM::ActRec *ar);
|
||||
|
||||
const long long hhbc_ext_funcs_count = 2209;
|
||||
const long long hhbc_ext_funcs_count = 2208;
|
||||
const HhbcExtFuncInfo hhbc_ext_funcs[] = {
|
||||
{ "apache_note", fg_apache_note, (void *)&fh_apache_note },
|
||||
{ "apache_request_headers", fg_apache_request_headers, (void *)&fh_apache_request_headers },
|
||||
@@ -3194,7 +3191,6 @@ const HhbcExtFuncInfo hhbc_ext_funcs[] = {
|
||||
{ "call_user_method_array", fg_call_user_method_array, (void *)&fh_call_user_method_array },
|
||||
{ "call_user_method", fg_call_user_method, (void *)&fh_call_user_method },
|
||||
{ "hphp_create_continuation", fg_hphp_create_continuation, (void *)&fh_hphp_create_continuation },
|
||||
{ "hphp_pack_continuation", fg_hphp_pack_continuation, (void *)&fh_hphp_pack_continuation },
|
||||
{ "hphp_unpack_continuation", fg_hphp_unpack_continuation, (void *)&fh_hphp_unpack_continuation },
|
||||
{ "ctype_alnum", fg_ctype_alnum, (void *)&fh_ctype_alnum },
|
||||
{ "ctype_alpha", fg_ctype_alpha, (void *)&fh_ctype_alpha },
|
||||
@@ -5468,7 +5464,7 @@ static const HhbcExtMethodInfo hhbc_ext_methods_TupleIterator[] = {
|
||||
{ "rewind", tg_13TupleIterator_rewind }
|
||||
};
|
||||
|
||||
static const long long hhbc_ext_method_count_Continuation = 19;
|
||||
static const long long hhbc_ext_method_count_Continuation = 17;
|
||||
static const HhbcExtMethodInfo hhbc_ext_methods_Continuation[] = {
|
||||
{ "__construct", tg_12Continuation___construct },
|
||||
{ "update", tg_12Continuation_update },
|
||||
@@ -5485,8 +5481,6 @@ static const HhbcExtMethodInfo hhbc_ext_methods_Continuation[] = {
|
||||
{ "valid", tg_12Continuation_valid },
|
||||
{ "send", tg_12Continuation_send },
|
||||
{ "raise", tg_12Continuation_raise },
|
||||
{ "raised", tg_12Continuation_raised },
|
||||
{ "receive", tg_12Continuation_receive },
|
||||
{ "getOrigFuncName", tg_12Continuation_getOrigFuncName },
|
||||
{ "__clone", tg_12Continuation___clone }
|
||||
};
|
||||
|
||||
@@ -7066,19 +7066,11 @@ inline void OPTBLD_INLINE VMExecutionContext::iopPackCont(PC& pc) {
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContReceive(PC& pc) {
|
||||
NEXT();
|
||||
c_Continuation* cont = frame_continuation(m_fp);
|
||||
Variant val = cont->t_receive();
|
||||
|
||||
TypedValue* tv = m_stack.allocTV();
|
||||
tvWriteUninit(tv);
|
||||
tvAsVariant(tv) = val;
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContRaised(PC& pc) {
|
||||
NEXT();
|
||||
c_Continuation* cont = frame_continuation(m_fp);
|
||||
cont->t_raised();
|
||||
TypedValue* tv = m_stack.allocTV();
|
||||
tvDup(cont->m_received.asTypedValue(), tv);
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContDone(PC& pc) {
|
||||
|
||||
@@ -556,7 +556,6 @@ enum SetOpOp {
|
||||
O(ContExit, NA, NOV, NOV, CF) \
|
||||
O(UnpackCont, NA, NOV, ONE(CV), NF) \
|
||||
O(PackCont, ONE(IVA), ONE(CV), NOV, NF) \
|
||||
O(ContRaised, NA, NOV, NOV, NF) \
|
||||
O(ContReceive, NA, NOV, ONE(CV), NF) \
|
||||
O(ContDone, NA, NOV, NOV, NF) \
|
||||
O(ContNext, NA, NOV, NOV, NF) \
|
||||
|
||||
@@ -752,11 +752,6 @@ void HhbcTranslator::emitContReceive() {
|
||||
push(value);
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitContRaised() {
|
||||
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
|
||||
m_tb->genContRaiseCheck(cont, getExitSlowTrace());
|
||||
}
|
||||
|
||||
void HhbcTranslator::emitContDone() {
|
||||
SSATmp* cont = m_tb->genLdAssertedLoc(0, Type::Obj);
|
||||
m_tb->genStRaw(cont, RawMemSlot::ContDone, m_tb->genDefConst(true));
|
||||
|
||||
@@ -346,7 +346,6 @@ struct HhbcTranslator {
|
||||
void emitUnpackCont();
|
||||
void emitPackCont(int64_t labelId);
|
||||
void emitContReceive();
|
||||
void emitContRaised();
|
||||
void emitContDone();
|
||||
void emitContNext();
|
||||
void emitContSendImpl(bool raise);
|
||||
|
||||
@@ -633,11 +633,6 @@ void TranslatorX64::irTranslateContReceive(const Tracelet& t,
|
||||
HHIR_EMIT(ContReceive);
|
||||
}
|
||||
|
||||
void TranslatorX64::irTranslateContRaised(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
HHIR_EMIT(ContRaised);
|
||||
}
|
||||
|
||||
void TranslatorX64::irTranslateContDone(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
HHIR_EMIT(ContDone);
|
||||
|
||||
@@ -7499,11 +7499,6 @@ void TranslatorX64::translateContReceive(const Tracelet& t,
|
||||
emitCopyToStack(a, i, r(rScratch), -1 * (int)sizeof(Cell));
|
||||
}
|
||||
|
||||
void TranslatorX64::translateContRaised(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
emitContRaiseCheck(a, i);
|
||||
}
|
||||
|
||||
void TranslatorX64::translateContEnter(const Tracelet& t,
|
||||
const NormalizedInstruction& i) {
|
||||
// We're about to execute the generator body, which uses regs
|
||||
@@ -12383,7 +12378,6 @@ bool TranslatorX64::dumpTCData() {
|
||||
SUPPORTED_OP(PackCont) \
|
||||
SUPPORTED_OP(ContDone) \
|
||||
SUPPORTED_OP(ContReceive) \
|
||||
SUPPORTED_OP(ContRaised) \
|
||||
SUPPORTED_OP(ContNext) \
|
||||
SUPPORTED_OP(ContSend) \
|
||||
SUPPORTED_OP(ContRaise) \
|
||||
|
||||
@@ -593,7 +593,6 @@ MINSTRS
|
||||
CASE(UnpackCont) \
|
||||
CASE(PackCont) \
|
||||
CASE(ContReceive) \
|
||||
CASE(ContRaised) \
|
||||
CASE(ContDone) \
|
||||
CASE(ContNext) \
|
||||
CASE(ContSend) \
|
||||
|
||||
@@ -1201,7 +1201,6 @@ static const struct {
|
||||
{ OpContExit, {None, None, OutNone, 0 }},
|
||||
{ OpUnpackCont, {Local, Stack1, OutInt64, 1 }},
|
||||
{ OpPackCont, {Local|Stack1, None, OutNone, -1 }},
|
||||
{ OpContRaised, {Local, None, OutNone, 0 }},
|
||||
{ OpContReceive, {Local, Stack1, OutUnknown, 1 }},
|
||||
{ OpContDone, {Local, None, OutNone, 0 }},
|
||||
{ OpContNext, {None, None, OutNone, 0 }},
|
||||
@@ -1960,7 +1959,6 @@ void Translator::getInputs(Tracelet& t,
|
||||
case OpUnpackCont:
|
||||
case OpPackCont:
|
||||
case OpContReceive:
|
||||
case OpContRaised:
|
||||
case OpContDone:
|
||||
case OpContSend:
|
||||
case OpContRaise:
|
||||
|
||||
@@ -7146,14 +7146,6 @@ const char *g_class_map[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(const char *)0x10006040, "hphp_pack_continuation", "", (const char*)0, (const char*)0,
|
||||
"/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-pack-continuation.php )\n *\n *\n * @continuation\n * object\n * @label int\n * @value mixed\n */",
|
||||
(const char *)-1, (const char *)0x2000, "continuation", "", (const char *)0x40, "", "", NULL,
|
||||
(const char *)0x2000, "label", "", (const char *)0xa, "", "", NULL,
|
||||
(const char *)0x2000, "value", "", (const char *)0xffffffff, "", "", NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(const char *)0x10006040, "hphp_unpack_continuation", "", (const char*)0, (const char*)0,
|
||||
"/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-unpack-continuation.php )\n *\n *\n * @continuation\n * object\n */",
|
||||
(const char *)-1, (const char *)0x2000, "continuation", "", (const char *)0x40, "", "", NULL,
|
||||
@@ -22029,16 +22021,6 @@ const char *g_class_map[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(const char *)0x10006040, "raised", "", (const char*)0, (const char*)0,
|
||||
"/**\n * ( excerpt from http://php.net/manual/en/continuation.raised.php )\n *\n *\n */",
|
||||
(const char *)-1, NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(const char *)0x10006040, "receive", "", (const char*)0, (const char*)0,
|
||||
"/**\n * ( excerpt from http://php.net/manual/en/continuation.receive.php )\n *\n *\n * @return mixed\n */",
|
||||
(const char *)0xffffffff, NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(const char *)0x10006040, "getOrigFuncName", "", (const char*)0, (const char*)0,
|
||||
"/**\n * ( excerpt from http://php.net/manual/en/continuation.getorigfuncname.php\n * )\n *\n *\n * @return string\n */",
|
||||
(const char *)0x14, NULL,
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
|
||||
#if EXT_TYPE == 0
|
||||
"hphp_create_continuation", S(999), "Continuation", S(0), "clsname", T(String), NULL, S(0), NULL, S(0), "funcname", T(String), NULL, S(0), NULL, S(0), "origFuncName", T(String), NULL, S(0), NULL, S(0), "args", T(Array), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-create-continuation.php )\n *\n *\n * @clsname string\n * @funcname string\n * @origFuncName\n * string\n * @args map\n *\n * @return Continuation\n *\n */",
|
||||
"hphp_pack_continuation", T(Void), S(0), "continuation", T(Object), NULL, S(0), NULL, S(0), "label", T(Int64), NULL, S(0), NULL, S(0), "value", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-pack-continuation.php )\n *\n *\n * @continuation\n * object\n * @label int\n * @value mixed\n */",
|
||||
"hphp_unpack_continuation", T(Void), S(0), "continuation", T(Object), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.hphp-unpack-continuation.php )\n *\n *\n * @continuation\n * object\n */",
|
||||
|
||||
#elif EXT_TYPE == 1
|
||||
|
||||
#elif EXT_TYPE == 2
|
||||
"Continuation", "", "iterator","awaitable",NULL, "__construct", T(Void), S(0), "func", T(Int64), NULL, S(0), NULL, S(0), "extra", T(Int64), NULL, S(0), NULL, S(0), "isMethod", T(Boolean), NULL, S(0), NULL, S(0), "origFuncName", T(String), NULL, S(0), NULL, S(0), "obj", T(Variant), "N;", S(2), "null", S(0), "args", T(Array), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.construct.php )\n *\n *\n * @func int\n * @extra int\n * @isMethod bool\n * @origFuncName\n * string\n * @obj mixed\n * @args map\n */", S(16384),"update", T(Void), S(0), "label", T(Int64), NULL, S(0), NULL, S(0), "value", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.update.php )\n *\n *\n * @label int\n * @value mixed\n */", S(16384),"done", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.done.php )\n *\n *\n */", S(16384),"getWaitHandle", T(Object), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getwaithandle.php )\n *\n * Start this continuation to the current scheduler context and return the\n * wait handle.\n *\n * @return object\n */", S(16384),"getLabel", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getlabel.php )\n *\n *\n * @return int\n */", S(16384),"num_args", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.num-args.php )\n *\n *\n * @return int\n */", S(16384),"get_args", T(Array), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-args.php )\n *\n *\n * @return vector\n */", S(16384),"get_arg", T(Variant), S(0), "id", T(Int64), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-arg.php )\n *\n *\n * @id int\n *\n * @return mixed\n */", S(16384),"current", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.current.php )\n *\n *\n * @return mixed\n */", S(16384),"key", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.key.php )\n *\n *\n * @return int\n */", S(16384),"next", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.next.php )\n *\n *\n */", S(16384),"rewind", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.rewind.php )\n *\n *\n */", S(16384),"valid", T(Boolean), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.valid.php )\n *\n *\n * @return bool\n */", S(16384),"send", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.send.php )\n *\n *\n * @v mixed\n */", S(16384),"raise", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.raise.php )\n *\n *\n * @v mixed\n */", S(16384),"raised", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.raised.php )\n *\n *\n */", S(16384),"receive", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.receive.php )\n *\n *\n * @return mixed\n */", S(16384),"getOrigFuncName", T(String), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getorigfuncname.php\n * )\n *\n *\n * @return string\n */", S(16384),"__clone", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.clone.php )\n *\n *\n * @return mixed\n */", S(16384),NULL,NULL,NULL,
|
||||
"Continuation", "", "iterator","awaitable",NULL, "__construct", T(Void), S(0), "func", T(Int64), NULL, S(0), NULL, S(0), "extra", T(Int64), NULL, S(0), NULL, S(0), "isMethod", T(Boolean), NULL, S(0), NULL, S(0), "origFuncName", T(String), NULL, S(0), NULL, S(0), "obj", T(Variant), "N;", S(2), "null", S(0), "args", T(Array), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.construct.php )\n *\n *\n * @func int\n * @extra int\n * @isMethod bool\n * @origFuncName\n * string\n * @obj mixed\n * @args map\n */", S(16384),"update", T(Void), S(0), "label", T(Int64), NULL, S(0), NULL, S(0), "value", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.update.php )\n *\n *\n * @label int\n * @value mixed\n */", S(16384),"done", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.done.php )\n *\n *\n */", S(16384),"getWaitHandle", T(Object), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getwaithandle.php )\n *\n * Start asynchronous execution of this Continuation and return the wait\n * handle\n *\n * @return object\n */", S(16384),"getLabel", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getlabel.php )\n *\n *\n * @return int\n */", S(16384),"num_args", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.num-args.php )\n *\n *\n * @return int\n */", S(16384),"get_args", T(Array), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-args.php )\n *\n *\n * @return vector\n */", S(16384),"get_arg", T(Variant), S(0), "id", T(Int64), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.get-arg.php )\n *\n *\n * @id int\n *\n * @return mixed\n */", S(16384),"current", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.current.php )\n *\n *\n * @return mixed\n */", S(16384),"key", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.key.php )\n *\n *\n * @return int\n */", S(16384),"next", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.next.php )\n *\n *\n */", S(16384),"rewind", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.rewind.php )\n *\n *\n */", S(16384),"valid", T(Boolean), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.valid.php )\n *\n *\n * @return bool\n */", S(16384),"send", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.send.php )\n *\n *\n * @v mixed\n */", S(16384),"raise", T(Void), S(0), "v", T(Variant), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.raise.php )\n *\n *\n * @v mixed\n */", S(16384),"getOrigFuncName", T(String), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.getorigfuncname.php\n * )\n *\n *\n * @return string\n */", S(16384),"__clone", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/continuation.clone.php )\n *\n *\n * @return mixed\n */", S(16384),NULL,NULL,NULL,
|
||||
S(16416), "/**\n * ( excerpt from http://php.net/manual/en/class.continuation.php )\n *\n *\n */", "DummyContinuation", "", "iterator",NULL, "__construct", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.construct.php\n * )\n *\n *\n */", S(16384),"current", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.current.php )\n *\n *\n * @return mixed\n */", S(16384),"key", T(Int64), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.key.php )\n *\n *\n * @return int\n */", S(16384),"next", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.next.php )\n *\n *\n */", S(16384),"rewind", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.rewind.php )\n *\n *\n */", S(16384),"valid", T(Boolean), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/dummycontinuation.valid.php )\n *\n *\n * @return bool\n */", S(16384),NULL,NULL,NULL,
|
||||
S(16384), "/**\n * ( excerpt from http://php.net/manual/en/class.dummycontinuation.php )\n *\n * Represents an invalid continuation which will fatal when used.\n *\n */",
|
||||
#endif
|
||||
|
||||
@@ -675,10 +675,7 @@ bool TestParserStmt::TestYieldStatement() {
|
||||
"case 1:\n"
|
||||
"goto " YIELD_LABEL_PREFIX "1;\n"
|
||||
"}\n"
|
||||
"hphp_pack_continuation($" CONTINUATION_OBJECT_NAME ", 1, 123);\n"
|
||||
"return;\n"
|
||||
YIELD_LABEL_PREFIX "1:\n"
|
||||
"hphp_continuation_raised();\n"
|
||||
"yield 123;\n"
|
||||
"hphp_continuation_done();\n"
|
||||
"}\n"
|
||||
"function foo() {\n"
|
||||
@@ -700,14 +697,8 @@ bool TestParserStmt::TestYieldStatement() {
|
||||
"case 1:\n"
|
||||
"goto " YIELD_LABEL_PREFIX "1;\n"
|
||||
"}\n"
|
||||
"hphp_pack_continuation($" CONTINUATION_OBJECT_NAME ", 1, 123);\n"
|
||||
"return;\n"
|
||||
YIELD_LABEL_PREFIX "1:\n"
|
||||
"hphp_continuation_raised();\n"
|
||||
"hphp_pack_continuation($" CONTINUATION_OBJECT_NAME ", 2, 456);\n"
|
||||
"return;\n"
|
||||
YIELD_LABEL_PREFIX "2:\n"
|
||||
"hphp_continuation_raised();\n"
|
||||
"yield 123;\n"
|
||||
"yield 456;\n"
|
||||
"hphp_continuation_done();\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
|
||||
+16
-75
@@ -149,33 +149,6 @@ static void prepare_continuation_call(Parser* _p, Token& rhs, const char* cname)
|
||||
_p->onCall(rhs, false, fname, empty, NULL, true);
|
||||
}
|
||||
|
||||
static void on_yield_assign(Parser *_p, Token &out, Token &var, Token *expr) {
|
||||
Token yield; _p->onYield(yield, expr, true);
|
||||
Token rhs; prepare_continuation_call(_p, rhs, "receive");
|
||||
Token assign; _p->onAssign(assign, var, rhs, 0);
|
||||
Token stmt; _p->onExpStatement(stmt, assign);
|
||||
|
||||
Token stmts0; _p->onStatementListStart(stmts0);
|
||||
Token stmts1; _p->addStatement(stmts1, stmts0, yield);
|
||||
Token stmts2; _p->addStatement(stmts2, stmts1, stmt);
|
||||
|
||||
_p->finishStatement(out, stmts2); out = 1;
|
||||
}
|
||||
|
||||
static void on_yield_list_assign(Parser *_p, Token &out, Token &var,
|
||||
Token *expr) {
|
||||
Token yield; _p->onYield(yield, expr, true);
|
||||
Token rhs; prepare_continuation_call(_p, rhs, "receive");
|
||||
Token assign; _p->onListAssignment(assign, var, &rhs);
|
||||
Token stmt; _p->onExpStatement(stmt, assign);
|
||||
|
||||
Token stmts0; _p->onStatementListStart(stmts0);
|
||||
Token stmts1; _p->addStatement(stmts1, stmts0, yield);
|
||||
Token stmts2; _p->addStatement(stmts2, stmts1, stmt);
|
||||
|
||||
_p->finishStatement(out, stmts2); out = 1;
|
||||
}
|
||||
|
||||
void prepare_generator(Parser *_p, Token &stmt, Token ¶ms, int count) {
|
||||
// 1. add prologue and epilogue to original body and store it back to "stmt"
|
||||
{
|
||||
@@ -315,50 +288,6 @@ void create_generator(Parser *_p, Token &out, Token ¶ms,
|
||||
}
|
||||
}
|
||||
|
||||
void transform_yield(Parser *_p, Token &stmts, int index,
|
||||
Token *expr, bool assign) {
|
||||
// hphp_pack_continuation(v___cont__, label, value)
|
||||
Token update;
|
||||
{
|
||||
Token name; name.setText(CONTINUATION_OBJECT_NAME);
|
||||
Token var; _p->onSynthesizedVariable(var, name);
|
||||
Token param0; _p->onCallParam(param0, NULL, var, false);
|
||||
|
||||
Token snum; snum.setText(boost::lexical_cast<std::string>(index));
|
||||
Token num; _p->onScalar(num, T_LNUMBER, snum);
|
||||
Token param1; _p->onCallParam(param1, ¶m0, num, false);
|
||||
|
||||
Token param2; _p->onCallParam(param2, ¶m1, *expr, false);
|
||||
|
||||
Token cname; cname.setText("hphp_pack_continuation");
|
||||
Token call; _p->onCall(call, false, cname, param2, NULL, true);
|
||||
_p->onExpStatement(update, call);
|
||||
}
|
||||
|
||||
// return
|
||||
Token ret; _p->onReturn(ret, NULL, false);
|
||||
|
||||
// __yield__N:
|
||||
Token lname; lname.setText(YIELD_LABEL_PREFIX +
|
||||
boost::lexical_cast<std::string>(index));
|
||||
Token label; _p->onLabel(label, lname);
|
||||
_p->addLabel(lname.text(), _p->getLocation(), &label);
|
||||
|
||||
Token stmts0; _p->onStatementListStart(stmts0);
|
||||
Token stmts1; _p->addStatement(stmts1, stmts0, update);
|
||||
Token stmts2; _p->addStatement(stmts2, stmts1, ret);
|
||||
Token stmts3; _p->addStatement(stmts3, stmts2, label);
|
||||
|
||||
if (assign) {
|
||||
_p->finishStatement(stmts, stmts3); stmts = 1;
|
||||
} else {
|
||||
Token fcall; prepare_continuation_call(_p, fcall, "raised");
|
||||
Token fstmt; _p->onExpStatement(fstmt, fcall);
|
||||
Token stmts4; _p->addStatement(stmts4, stmts3, fstmt);
|
||||
_p->finishStatement(stmts, stmts4); stmts = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void transform_yield_break(Parser *_p, Token &out) {
|
||||
// hphp_continuation_done()
|
||||
Token mcall; prepare_continuation_call(_p, mcall, "done");
|
||||
@@ -1061,10 +990,6 @@ statement:
|
||||
| T_RETURN ';' { _p->onReturn($$, NULL);}
|
||||
| T_RETURN expr ';' { _p->onReturn($$, &$2);}
|
||||
| T_YIELD T_BREAK ';' { _p->onYieldBreak($$);}
|
||||
| T_YIELD expr ';' { _p->onYield($$, &$2, false);}
|
||||
| variable '=' T_YIELD expr ';' { on_yield_assign(_p, $$, $1, &$4);}
|
||||
| T_LIST '(' assignment_list ')'
|
||||
'=' T_YIELD expr ';' { on_yield_list_assign(_p, $$, $3, &$7);}
|
||||
| T_GLOBAL global_var_list ';' { _p->onGlobal($$, $2);}
|
||||
| T_STATIC static_var_list ';' { _p->onStatic($$, $2);}
|
||||
| T_ECHO expr_list ';' { _p->onEcho($$, $2, 0);}
|
||||
@@ -1095,6 +1020,9 @@ statement:
|
||||
_p->getLocation(),
|
||||
&$$); }
|
||||
| expr ';' { _p->onExpStatement($$, $1);}
|
||||
| yield_expr ';' { _p->onExpStatement($$, $1);}
|
||||
| yield_assign_expr ';' { _p->onExpStatement($$, $1);}
|
||||
| yield_list_assign_expr ';' { _p->onExpStatement($$, $1);}
|
||||
| ident ':' { _p->onLabel($$, $1);
|
||||
_p->addLabel($1.text(),
|
||||
_p->getLocation(),
|
||||
@@ -1639,6 +1567,19 @@ for_expr:
|
||||
| { $$.reset();}
|
||||
;
|
||||
|
||||
yield_expr:
|
||||
T_YIELD expr { _p->onYield($$, $2);}
|
||||
;
|
||||
|
||||
yield_assign_expr:
|
||||
variable '=' yield_expr { _p->onAssign($$, $1, $3, 0, true);}
|
||||
;
|
||||
|
||||
yield_list_assign_expr:
|
||||
T_LIST '(' assignment_list ')'
|
||||
'=' yield_expr { _p->onListAssignment($$, $3, &$6, true);}
|
||||
;
|
||||
|
||||
expr:
|
||||
expr_no_variable { $$ = $1;}
|
||||
| variable { $$ = $1;}
|
||||
|
||||
@@ -247,6 +247,10 @@ void ParserBase::popLabelInfo() {
|
||||
|
||||
for (unsigned int i = 0; i < info.gotos.size(); i++) {
|
||||
const GotoInfo &gotoInfo = info.gotos[i];
|
||||
if (gotoInfo.label.find(YIELD_LABEL_PREFIX) == 0) {
|
||||
labels.erase(gotoInfo.label);
|
||||
continue;
|
||||
}
|
||||
LabelMap::const_iterator iter = info.labels.find(gotoInfo.label);
|
||||
if (iter == info.labels.end()) {
|
||||
invalidateGoto(gotoInfo.stmt, UndefLabel);
|
||||
@@ -255,10 +259,6 @@ void ParserBase::popLabelInfo() {
|
||||
continue;
|
||||
}
|
||||
const LabelStmtInfo &labelInfo = iter->second;
|
||||
if (gotoInfo.label.find(YIELD_LABEL_PREFIX) == 0) {
|
||||
labels.erase(gotoInfo.label);
|
||||
continue;
|
||||
}
|
||||
int labelScopeId = labelInfo.scopeId;
|
||||
bool found = false;
|
||||
for (int j = gotoInfo.scopes.size() - 1; j >= 0; j--) {
|
||||
|
||||
+17459
-17536
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+3335
-3383
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -246,8 +246,9 @@ struct Parser : ParserBase {
|
||||
X(base, prop, params);
|
||||
}
|
||||
|
||||
void onListAssignment(Token &out, Token &vars, Token *expr) {
|
||||
X(vars, expr);
|
||||
void onListAssignment(Token &out, Token &vars, Token *expr,
|
||||
bool rhsFirst = false) {
|
||||
X(vars, expr, rhsFirst);
|
||||
}
|
||||
|
||||
void onAListVar(Token &out, Token *list, Token *var) {
|
||||
@@ -258,8 +259,9 @@ struct Parser : ParserBase {
|
||||
X(list, sublist);
|
||||
}
|
||||
|
||||
void onAssign(Token& out, Token& var, Token& expr, bool ref) {
|
||||
X(var, expr, ref);
|
||||
void onAssign(Token& out, Token& var, Token& expr, bool ref,
|
||||
bool rhsFirst = false) {
|
||||
X(var, expr, ref, rhsFirst);
|
||||
}
|
||||
|
||||
void onAssignNew(Token &out, Token &var, Token &name, Token &args) {
|
||||
@@ -439,8 +441,8 @@ struct Parser : ParserBase {
|
||||
X(expr, checkYield);
|
||||
}
|
||||
|
||||
void onYield(Token &out, Token *expr, bool assign) {
|
||||
X(expr, assign);
|
||||
void onYield(Token &out, Token &expr) {
|
||||
X(expr);
|
||||
}
|
||||
|
||||
void onYieldBreak(Token &out) { X(); }
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário