Rename typedef Var to Ref (its a reference)

And, several helper functions with the prefix "var" were changed
to the prefix "ref".  I reworded the bytecode spec; the flavor letter
for PHP references is still 'V', but I reworded parts of it to use
the term 'pointer' instead of 'reference' in places where reference
was too overloaded.  Renamed 'var' to 'ref' throughout.
Esse commit está contido em:
Edwin Smith
2013-07-21 14:40:44 -07:00
commit de Sara Golemon
commit 1140d2f313
7 arquivos alterados com 121 adições e 118 exclusões
+72 -71
Ver Arquivo
@@ -100,26 +100,27 @@ Values
HHBC instructions may push and pop values on the current frame's evaluation
stack and they may read and write values to the current frame's local
variables. Values come in three flavors: cells, vars, and classrefs.
variables. Values come in three flavors: cells, refs, and classrefs.
A "cell" is a structure that contains a type identifier and either data (for
non-refcounted types) or a reference to data (for refcounted types). When a
cell containing a reference is duplicated, the new cell will point to the same
data as the original cell. When a cell containing a reference is duplicated or
non-refcounted types) or a pointer to data (for refcounted types). When a
cell containing a pointer is duplicated, the new cell will point to the same
data as the original cell. When a cell containing a pointer is duplicated or
discarded, the execution engine is responsible for honoring the data's refcount
logic.
A "var" is a structure that contains a reference to a cell. When a var is
duplicated, the new var will point to the same cell as the original var. When
a var is duplicated or destroyed, the execution engine is responsible for
honoring the cell's refcount logic.
A "ref" is a structure that contains a pointer to a cell container. When a
ref is duplicated, the new ref will point to the same container as the
original ref. When a ref is duplicated or destroyed, the execution engine is
responsible for honoring the containers's refcount logic. When the container
is destroyed, the cell it contains is also destroyed.
A "classref" is a structure that contains a reference to a class. When a
classref is pushed onto the stack or popped of the stack, no refcounting is
required.
Values on the evaluation stack may be any of the three flavors listed above.
Values stored in local variables may only be cells or vars.
Values stored in local variables may only be cells or refs.
Functions
@@ -529,7 +530,7 @@ parameters being passed.
Flavor descriptors
------------------
Any given value on the stack must either be a cell, var, or classref at run
Any given value on the stack must either be a cell, ref, or classref at run
time. However, at bytecode generation time the specific flavor of a value on
the stack is not always known. HipHop bytecode uses symbols called "flavor
descriptors" to precisely describe what is known at bytecode generation about
@@ -542,12 +543,12 @@ for each of the instruction's inputs.
Here is a description of each flavor descriptor:
C - cell; specifies that the value must be a cell at run time
V - var; specifies that the value must be a var at run time
V - ref; specifies that the value must be a ref at run time
A - classref; specifies that the value must be a classref at run time
R - return value; specifies that the value may be a cell or a var at run
R - return value; specifies that the value may be a cell or a ref at run
time; this flavor descriptor is used for return values from function
calls
F - function argument; specifies that the value may be a cell or a var at run
F - function argument; specifies that the value may be a cell or a ref at run
time; this flavor descriptor is used for parameter values that are
about to be passed into a function
@@ -600,7 +601,7 @@ instruction must be empty.
exactly one value and the flavor descriptor of the value must be cell.
Likewise, before executing the RetV instruction, the evaluation stack must
contain exactly one value and the flavor descriptor of the value must be the
var. Finally, before executing the Unwind instruction, the evaluation stack
ref. Finally, before executing the Unwind instruction, the evaluation stack
must be empty.
6) The code for the primary function body and fault funclets must be laid out
@@ -718,7 +719,7 @@ location descriptors is given below:
S - static property; location is the static property whose class is given by
a classref and whose name is given by value of a cell.
C - cell; location is a temporary value given by a cell.
R - return value; location is a temporary value given by a cell or a var
R - return value; location is a temporary value given by a cell or a ref
There are several groups of similarly named instructions where the name of each
instruction ends with a different location descriptor (for example, Set*). Each
@@ -798,27 +799,27 @@ Dup [C:<T>] -> [C:<T> C:<T>]
Box [C:<T>] -> [V:<T>]
Box. Creates a new var, sets the new var to point at a copy of cell $1, and
pushes the var onto the stack.
Box. Creates a new ref, sets the new ref to point at a copy of cell $1, and
pushes the ref onto the stack.
Unbox [V:<T>] -> [C:<T>]
Unbox. Creates a copy of the cell that var $1 points to, and pushes the cell
Unbox. Creates a copy of the cell that ref $1 points to, and pushes the cell
onto the stack.
BoxR [R:<T>] -> [V:<T>]
Box. If $1 is a var at run time, this instruction does nothing.
Box. If $1 is a ref at run time, this instruction does nothing.
If $1 is a cell at run time, this instruction creates a new var, sets the new
var to point at a copy of cell $1, and pushes the var onto the stack.
If $1 is a cell at run time, this instruction creates a new ref, sets the new
ref to point at a copy of cell $1, and pushes the ref onto the stack.
UnboxR [R:<T>] -> [C:<T>]
Unbox. If $1 is a cell at run time, this instruction does nothing.
If $1 is a var at run time, this instruction creates a copy of the cell that
var $1 points to, and pushes the cell onto the stack.
If $1 is a ref at run time, this instruction creates a copy of the cell that
ref $1 points to, and pushes the cell onto the stack.
2. Literal and constant instructions
@@ -1247,35 +1248,35 @@ CGetS [C A] -> [C]
VGetL <local variable id> [] -> [V]
Get local as var. This instruction boxes the local variable given by %1 if
necessary and pushes it onto the stack as a var. If the given local variable
Get local as ref. This instruction boxes the local variable given by %1 if
necessary and pushes it onto the stack as a ref. If the given local variable
is not defined, this instruction defines it, sets it to null, boxes it, and
pushes a the value of the local variable onto the stack as a var.
pushes a the value of the local variable onto the stack as a ref.
VGetN [C] -> [V]
Get local as var. This instruction first computes x = (string)$1. Next, this
Get local as ref. This instruction first computes x = (string)$1. Next, this
instruction boxes the local variable named x (if the local is a cell) and
pushes its value onto the stack as a var. If there is no local variable
pushes its value onto the stack as a ref. If there is no local variable
defined named x, this instruction defines a local variable named x, sets it
to null, boxes it, and pushes the value of the local variable onto the stack
as a var.
as a ref.
VGetG [C] -> [V]
Get global as var. This instruction first computes x = (string)$1. Next, this
Get global as ref. This instruction first computes x = (string)$1. Next, this
instruction boxes the global variable named x (if the local is a cell) and
pushes its value onto the stack as a var. If there is no global variable
pushes its value onto the stack as a ref. If there is no global variable
defined named x, this instruction defines a global variable named x, sets it
to null, boxes it, and pushes the value of the global variable onto the stack
as a var.
as a ref.
VGetS [C A] -> [V]
Get static property as var. This instruction first checks if class $1 has a
Get static property as ref. This instruction first checks if class $1 has a
visible and accessible static property named (string)$2. If it doesn't, this
instruction throws a fatal error. Otherwise, this instruction boxes the
static property and pushes it onto the stack as a var.
static property and pushes it onto the stack as a ref.
AGetC [C] -> [A]
AGetL <local variable id> [] -> [A]
@@ -1736,12 +1737,12 @@ FPushCufSafe <num params> [C C] -> [C C]
CufSafeArray [C C R] -> [C]
Pops 3 elements from the stack, and pushes array($2, $1), preserving
references.
refs.
CufSafeReturn [C C R] -> [R]
Pops 3 elements from the stack, and pushes $2 ? $1 : $3, preserving
references.
refs.
FPassC <param id> [C] -> [F]
FPassCW <param id> [C] -> [F]
@@ -1759,7 +1760,7 @@ FPassV <param id> [V] -> [F]
FPI pass parameter. If parameter %1 is pass by value, this instruction will
unbox $1 and push it onto the stack as a cell. If parameter %1 is pass by
reference, this instruction will push $1 onto the stack as a var.
reference, this instruction will push $1 onto the stack as a ref.
FPassR <param id> [R] -> [F]
@@ -1827,32 +1828,32 @@ instructions. Operations are not considered instructions; they do not have
opcodes associated with them.
Operations can produce and consume intermediate values called "bases". A "base"
is a structure that contains either a cell or a var or a reference to a memory
location that is occupied by a cell or a var. Bases are never pushed onto the
is a structure that contains either a cell or a ref or a reference to a memory
location that is occupied by a cell or a ref. Bases are never pushed onto the
evaluation stack.
For operations that create a base, the operation descriptions specify whether
the base created "contains" a value or "references" a location. In the former
case, the base created contains a cell or a var. In the latter case, the base
created contains a reference to a memory location occupied by a cell or a var.
case, the base created contains a cell or a ref. In the latter case, the base
created contains a reference to a memory location occupied by a cell or a ref.
When a base that contains a cell is destroyed, if the cell references data then
When a base that contains a cell is destroyed, if the cell points to data then
the execution engine is responsible for honoring the data's refcount logic.
Likewise when a base that contains a var is destroyed, the execution engine is
responsible for honoring the refcount logic of the cell referenced by the var.
When a base that contains a reference to a memory location occupied by a cell
or a var is destroyed, no refcounting is required.
Likewise when a base that contains a ref is destroyed, the execution engine is
responsible for honoring the refcount logic of the cell container pointed to by
the ref. When a base that contains a reference to a memory location occupied
by a cell or a ref is destroyed, no refcounting is required.
Some operations that take a base as input can modify that base as part of the
work performed by the operation. Such operations are said to "set" the base to
a new value. When a base that contains a cell or a reference to a memory
location occupied by a cell is set to a new value, the new value overwrites the
previous value contained in the cell (honoring the data refcount logic if the
previous value was a refcounted type). When a base that contains a var or a
reference to a memory location occupied by a var is set to the new value, the
new value is written into the cell referenced by the var, overwriting the
previous value contained in that cell (honoring the data refcount logic if the
previous value was a refcounted type). Note that for bases that contain a
previous value was a refcounted type). When a base that contains a ref or a
reference to a memory location occupied by a ref is set to the new value, the
new value is written into the cell container referenced by the ref, overwriting
the previous cell in that container (honoring the data refcount logic if the
previous cell was a refcounted type). Note that for bases that contain a
reference to a memory location, "setting" the base does not change which memory
location the base references.
@@ -2334,7 +2335,7 @@ CGetElemL <local variable id> [B] -> [C]
VGetElemC [C B] -> [V]
VGetElemL <local variable id> [B] -> [V]
Get element as var.
Get element as ref.
These instructions first load a value into x and a base into y, as
given by the following table:
@@ -2345,21 +2346,21 @@ VGetElemL <local variable id> [B] -> [V]
VGetElemL | %1 | $1
If y is an array, this operation retrieves the element at index x from
array y and pushes it onto the stack as a var. If there is no element at
array y and pushes it onto the stack as a ref. If there is no element at
index x, this operation creates a new element at index x, and pushes it
onto the stack as a var.
onto the stack as a ref.
If y is an object that implements the ArrayAccess interface, this operation
pushes y->offsetGet(x) onto the stack as a var.
pushes y->offsetGet(x) onto the stack as a ref.
If y is a non-empty string or an object that does not implement the
ArrayAccess interface, this operation throws a fatal error.
If y is null, false, or the empty string, this operation sets y to a new
empty array. Then this operation retrieves the element at index x from array
y and pushes it onto the stack as a var. If there is no element at index x,
y and pushes it onto the stack as a ref. If there is no element at index x,
this operation creates a new element at index x, and pushes it onto the
stack as a var.
stack as a ref.
If y is true, integer, or double, this operation raises a warning and
pushes null onto the stack.
@@ -2568,12 +2569,12 @@ BindElemL <local variable id> [V B] -> [V]
referred to by %1.
If $1 is an array, this operation executes $1[x] =& $2 and pushes $2
onto the stack as a var.
onto the stack as a ref.
If $1 is an object, this operation throws a fatal error.
If $1 is null, false, or the empty string, this operation sets $1 to a new
empty array, executes $1[x] =& $2, and pushes $2 onto the stack as a var.
empty array, executes $1[x] =& $2, and pushes $2 onto the stack as a ref.
If $1 is a non-empty string, this operation throws a fatal error.
@@ -2607,20 +2608,20 @@ UnsetElemL <local variable id> [B] -> []
VGetNewElem [B] -> [V]
Get new element as var.
Get new element as ref.
If $1 is an array, this operation creates a new element with the next
available numeric key in array $1 and pushes it onto the stack as a var.
available numeric key in array $1 and pushes it onto the stack as a ref.
If $1 is an object that implements the ArrayAccess interface, this operation
pushes $1->offsetGet($2) onto the stack as a var.
pushes $1->offsetGet($2) onto the stack as a ref.
If $1 is a non-empty string or an object that does not implement the
ArrayAccess interface, this operation throws a fatal error.
If $1 is null, false, or the empty string, this operation first sets $1 to a
new empty array. Then it creates a new element with the next available
numeric key in array $1 and pushes it onto the stack as a var.
numeric key in array $1 and pushes it onto the stack as a ref.
If $1 is true, integer, or double, this operation raises a warning and
pushes null onto the stack.
@@ -2731,7 +2732,7 @@ CGetPropL <local variable id> [B] -> [C]
VGetPropC [C B] -> [V]
VGetPropL <local variable id> [B] -> [V]
Get property as var.
Get property as ref.
These instructions first load a value into x and a base into y, as
given by the following table:
@@ -2744,10 +2745,10 @@ VGetPropL <local variable id> [B] -> [V]
If y is an object that does not have an eligible __get method, this
operation first checks if y has a visible property named x. If it
does not, this operation will create a new property named x and push
it onto the stack as a var. Otherwise this operation continues to
it onto the stack as a ref. Otherwise this operation continues to
check if the property named x is accessible. If it the property
named x is accessible this operation pushes it onto the stack as a
var, otherwise this operation throws a fatal error.
ref, otherwise this operation throws a fatal error.
If y is an object has an eligible __get method, this operation
checks if y has a visible and accessible property named x. If it
@@ -3079,7 +3080,7 @@ CGetM <loc-desc/M-vector> [C..C] -> [C]
VGetM <loc-desc/M-vector> [C..C] -> [V]
Get member as var.
Get member as ref.
location Base* member intermediate final
descriptor operation code operation operation
@@ -3353,10 +3354,10 @@ MIterInitK <iterator id> <rel offset> <local id> <local id> [V] -> []
transfer control to the location specified by %2.
If the iterator specified by %1 is a mutable array iterator, these
instructions store the current value in %3 as a var.
instructions store the current value in %3 as a ref.
If the iterator specified by %1 is a mutable default class iterator, these
instructions store the current property in %3 as a var.
instructions store the current property in %3 as a ref.
For the MIterInitK version, the following also happens:
@@ -3436,10 +3437,10 @@ MIterNextK <iterator id> <rel offset> <local id> <local id> [] -> []
If the specified iterator is not at the end, retrieve the key and value:
If the iterator specified by %1 is a mutable array iterator, these
instructions store the new current value in %3 as a var.
instructions store the new current value in %3 as a ref.
If the iterator specified by %1 is a mutable default class iterator, these
instructions store the new current property in %3 as a var.
instructions store the new current property in %3 as a ref.
For the MIterNextK version, the following also happens:
+1 -1
Ver Arquivo
@@ -491,7 +491,7 @@ private:
bool initIterator(PC& pc, PC& origPc, Iter* it,
Offset offset, Cell* c1);
bool initIteratorM(PC& pc, PC& origPc, Iter* it,
Offset offset, Var* v1, TypedValue* val, TypedValue* key);
Offset offset, Ref* r1, TypedValue* val, TypedValue* key);
void jmpSurpriseCheck(Offset o);
template<Op op> void jmpOpImpl(PC& pc);
#define O(name, imm, pusph, pop, flags) \
+5 -3
Ver Arquivo
@@ -132,13 +132,15 @@ private:
/*
* These may be used to provide a little more self-documentation about
* whether typed values must be cells (not KindOfRef) or var (must be
* whether typed values must be cells (not KindOfRef) or ref (must be
* KindOfRef).
*
* See bytecode.specification for details.
* See bytecode.specification for details. Note that in
* bytecode.specification, refs are abbreviated as "V".
*
*/
typedef TypedValue Cell;
typedef TypedValue Var;
typedef TypedValue Ref;
/*
* A TypedNum is a TypedValue that is either KindOfDouble or
+4 -4
Ver Arquivo
@@ -79,10 +79,10 @@ bool tvIsPlausible(const TypedValue* tv) {
return cellIsPlausible(tv);
}
bool varIsPlausible(const Var* var) {
assert(var);
assert(var->m_type == KindOfRef);
return tvIsPlausible(var);
bool refIsPlausible(const Ref* ref) {
assert(ref);
assert(ref->m_type == KindOfRef);
return tvIsPlausible(ref);
}
inline void tvUnboxIfNeeded(TypedValue *tv) {
+14 -14
Ver Arquivo
@@ -36,7 +36,7 @@ class Variant;
*/
bool tvIsPlausible(const TypedValue*);
bool cellIsPlausible(const Cell*);
bool varIsPlausible(const Var*);
bool refIsPlausible(const Ref*);
/*
* Returns: true if the supplied TypedValue is KindOfDouble or
@@ -211,8 +211,8 @@ inline void cellCopy(const Cell& fr, Cell& to) {
assert(cellIsPlausible(&fr));
tvCopy(fr, to);
}
inline void varCopy(const Var& fr, Var& to) {
assert(varIsPlausible(&fr));
inline void refCopy(const Ref& fr, Ref& to) {
assert(refIsPlausible(&fr));
tvCopy(fr, to);
}
@@ -236,13 +236,13 @@ inline void cellDup(const Cell& fr, Cell& to) {
}
/*
* Duplicate a Var from one location to another.
* Duplicate a Ref from one location to another.
*
* This has the same effects as tvDup(fr, to), but is slightly more
* efficient because we don't need to check the type tag.
*/
inline void varDup(const Var& fr, Var& to) {
assert(varIsPlausible(&fr));
inline void refDup(const Ref& fr, Ref& to) {
assert(refIsPlausible(&fr));
to.m_data.num = fr.m_data.num;
to.m_type = KindOfRef;
tvIncRefNotShared(&to);
@@ -339,7 +339,7 @@ inline void tvBind(TypedValue* fr, TypedValue* to) {
assert(fr->m_type == KindOfRef);
DataType oldType = to->m_type;
uint64_t oldDatum = to->m_data.num;
varDup(*fr, *to);
refDup(*fr, *to);
tvRefcountedDecRefHelper(oldType, oldDatum);
}
@@ -423,15 +423,15 @@ inline const Variant& cellAsCVarRef(const Cell& cell) {
}
// Assumes 'tv' is live
inline Variant& varAsVariant(Var& var) {
assert(varIsPlausible(&var));
return *(Variant*)(&var);
inline Variant& refAsVariant(Ref& ref) {
assert(refIsPlausible(&ref));
return *(Variant*)(&ref);
}
// Assumes 'tv' is live
inline const Variant& varAsCVarRef(const Var& var) {
assert(varIsPlausible(&var));
return *(const Variant*)(&var);
inline const Variant& refAsCVarRef(const Ref& ref) {
assert(refIsPlausible(&ref));
return *(const Variant*)(&ref);
}
inline bool tvIsStronglyBound(const TypedValue* tv) {
@@ -448,7 +448,7 @@ inline void tvDupFlattenVars(const TypedValue* fr, TypedValue* to,
fr = fr->m_data.pref->tv();
cellDup(*fr, *to);
} else {
varDup(*fr, *to);
refDup(*fr, *to);
}
}
+21 -21
Ver Arquivo
@@ -3486,16 +3486,16 @@ inline void OPTBLD_INLINE VMExecutionContext::iopAddElemC(PC& pc) {
inline void OPTBLD_INLINE VMExecutionContext::iopAddElemV(PC& pc) {
NEXT();
Var* v1 = m_stack.topV();
Ref* r1 = m_stack.topV();
Cell* c2 = m_stack.indC(1);
Cell* c3 = m_stack.indC(2);
if (c3->m_type != KindOfArray) {
raise_error("AddElemV: $3 must be an array");
}
if (c2->m_type == KindOfInt64) {
cellAsVariant(*c3).asArrRef().set(c2->m_data.num, ref(tvAsCVarRef(v1)));
cellAsVariant(*c3).asArrRef().set(c2->m_data.num, ref(tvAsCVarRef(r1)));
} else {
cellAsVariant(*c3).asArrRef().set(tvAsCVarRef(c2), ref(tvAsCVarRef(v1)));
cellAsVariant(*c3).asArrRef().set(tvAsCVarRef(c2), ref(tvAsCVarRef(r1)));
}
m_stack.popV();
m_stack.popC();
@@ -3514,12 +3514,12 @@ inline void OPTBLD_INLINE VMExecutionContext::iopAddNewElemC(PC& pc) {
inline void OPTBLD_INLINE VMExecutionContext::iopAddNewElemV(PC& pc) {
NEXT();
Var* v1 = m_stack.topV();
Ref* r1 = m_stack.topV();
Cell* c2 = m_stack.indC(1);
if (c2->m_type != KindOfArray) {
raise_error("AddNewElemV: $2 must be an array");
}
cellAsVariant(*c2).asArrRef().append(ref(tvAsCVarRef(v1)));
cellAsVariant(*c2).asArrRef().append(ref(tvAsCVarRef(r1)));
m_stack.popV();
}
@@ -4373,7 +4373,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopCGetG(PC& pc) {
if (val->m_type != KindOfRef) { \
tvBox(val); \
} \
varDup(*val, *output); \
refDup(*val, *output); \
} else { \
tvReadCell(val, output); \
} \
@@ -4417,7 +4417,7 @@ static inline void vgetl_body(TypedValue* fr, TypedValue* to) {
inline void OPTBLD_INLINE VMExecutionContext::iopVGetL(PC& pc) {
NEXT();
DECODE_HA(local);
Var* to = m_stack.allocV();
Ref* to = m_stack.allocV();
TypedValue* fr = frame_local(m_fp, local);
vgetl_body(fr, to);
}
@@ -4462,7 +4462,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopVGetM(PC& pc) {
if (base->m_type != KindOfRef) {
tvBox(base);
}
varDup(*base, *tv1);
refDup(*base, *tv1);
} else {
tvWriteNull(tv1);
tvBox(tv1);
@@ -5008,7 +5008,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopIncDecM(PC& pc) {
inline void OPTBLD_INLINE VMExecutionContext::iopBindL(PC& pc) {
NEXT();
DECODE_HA(local);
Var* fr = m_stack.topV();
Ref* fr = m_stack.topV();
TypedValue* to = frame_local(m_fp, local);
tvBind(fr, to);
}
@@ -5717,7 +5717,7 @@ void VMExecutionContext::iopFPassM(PC& pc) {
if (base->m_type != KindOfRef) {
tvBox(base);
}
varDup(*base, *tv1);
refDup(*base, *tv1);
} else {
tvWriteNull(tv1);
tvBox(tv1);
@@ -6128,18 +6128,18 @@ inline void OPTBLD_INLINE VMExecutionContext::iopWIterInitK(PC& pc) {
inline bool VMExecutionContext::initIteratorM(PC& pc, PC& origPc, Iter* it,
Offset offset, Var* v1,
Offset offset, Ref* r1,
TypedValue *val,
TypedValue *key) {
bool hasElems = false;
TypedValue* rtv = v1->m_data.pref->tv();
TypedValue* rtv = r1->m_data.pref->tv();
if (rtv->m_type == KindOfArray) {
hasElems = new_miter_array_key(it, v1->m_data.pref, val, key);
hasElems = new_miter_array_key(it, r1->m_data.pref, val, key);
} else if (rtv->m_type == KindOfObject) {
Class* ctx = arGetContextClass(g_vmContext->getFP());
hasElems = new_miter_object(it, v1->m_data.pref, ctx, val, key);
hasElems = new_miter_object(it, r1->m_data.pref, ctx, val, key);
} else {
hasElems = new_miter_other(it, v1->m_data.pref);
hasElems = new_miter_other(it, r1->m_data.pref);
}
if (!hasElems) {
@@ -6156,11 +6156,11 @@ inline void OPTBLD_INLINE VMExecutionContext::iopMIterInit(PC& pc) {
DECODE_IA(itId);
DECODE(Offset, offset);
DECODE_HA(val);
Var* v1 = m_stack.topV();
assert(v1->m_type == KindOfRef);
Ref* r1 = m_stack.topV();
assert(r1->m_type == KindOfRef);
Iter* it = frame_iter(m_fp, itId);
TypedValue* tv1 = frame_local(m_fp, val);
initIteratorM(pc, origPc, it, offset, v1, tv1, nullptr);
initIteratorM(pc, origPc, it, offset, r1, tv1, nullptr);
}
inline void OPTBLD_INLINE VMExecutionContext::iopMIterInitK(PC& pc) {
@@ -6170,12 +6170,12 @@ inline void OPTBLD_INLINE VMExecutionContext::iopMIterInitK(PC& pc) {
DECODE(Offset, offset);
DECODE_HA(val);
DECODE_HA(key);
Var* v1 = m_stack.topV();
assert(v1->m_type == KindOfRef);
Ref* r1 = m_stack.topV();
assert(r1->m_type == KindOfRef);
Iter* it = frame_iter(m_fp, itId);
TypedValue* tv1 = frame_local(m_fp, val);
TypedValue* tv2 = frame_local(m_fp, key);
initIteratorM(pc, origPc, it, offset, v1, tv1, tv2);
initIteratorM(pc, origPc, it, offset, r1, tv1, tv2);
}
inline void OPTBLD_INLINE VMExecutionContext::iopIterNext(PC& pc) {
+4 -4
Ver Arquivo
@@ -746,10 +746,10 @@ public:
return (Cell*)m_top;
}
inline Var* ALWAYS_INLINE allocV() {
inline Ref* ALWAYS_INLINE allocV() {
assert(m_top != m_elms);
m_top--;
return (Var*)m_top;
return (Ref*)m_top;
}
inline TypedValue* ALWAYS_INLINE allocTV() {
@@ -777,10 +777,10 @@ public:
return (Cell*)m_top;
}
inline Var* ALWAYS_INLINE topV() {
inline Ref* ALWAYS_INLINE topV() {
assert(m_top != m_base);
assert(m_top->m_type == KindOfRef);
return (Var*)m_top;
return (Ref*)m_top;
}
inline TypedValue* ALWAYS_INLINE topTV() {