Special case some bytecode ops in getStackValue
Some bytecode ops, such as CGetL3, would munch the types of the things on the stack above the new cell that was pushed because getStackValue assumes all stack outputs from interpOne are on top of the stack. The result is that the top of the stack would contain the output type, and the two things below it would not get any type (unknown). This usually isn't a problem, but if we fail enough in type prediction we might get around to InterpOneing these ops.
Esse commit está contido em:
@@ -324,8 +324,8 @@ struct CheckDefinedClsData : IRExtraData {
|
||||
* Offset and stack deltas for InterpOne.
|
||||
*/
|
||||
struct InterpOneData : IRExtraData {
|
||||
InterpOneData(Offset o, int64_t pop, int64_t push)
|
||||
: bcOff(o), cellsPopped(pop), cellsPushed(push) {}
|
||||
InterpOneData(Offset o, int64_t pop, int64_t push, Op op)
|
||||
: bcOff(o), cellsPopped(pop), cellsPushed(push), opcode(op) {}
|
||||
|
||||
// Offset of the instruction to interpret, in the Unit indicated by
|
||||
// the current Marker.
|
||||
@@ -335,6 +335,10 @@ struct InterpOneData : IRExtraData {
|
||||
// instruction, respectively. Includes ActRecs.
|
||||
int64_t cellsPopped;
|
||||
int64_t cellsPushed;
|
||||
|
||||
// Opcode, in case we need to fix the stack differently. Some byte-
|
||||
// code instructions modify things below the top of the stack.
|
||||
Op opcode;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -3539,7 +3539,9 @@ void HhbcTranslator::emitInterpOne(Type outType, int popped) {
|
||||
|
||||
void HhbcTranslator::emitInterpOne(Type outType, int popped, int pushed) {
|
||||
auto sp = spillStack();
|
||||
gen(InterpOne, outType, InterpOneData(bcOff(), popped, pushed),
|
||||
Unit *u = curFunc()->unit();
|
||||
gen(InterpOne, outType, InterpOneData(bcOff(), popped, pushed,
|
||||
u->getOpcode(bcOff())),
|
||||
m_tb->fp(), sp);
|
||||
assert(m_stackDeficit == 0);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "hphp/runtime/base/memory/smart_containers.h"
|
||||
#include "hphp/runtime/base/type_conversions.h"
|
||||
#include "hphp/runtime/vm/jit/tracebuilder.h"
|
||||
#include "hphp/runtime/vm/hhbc.h"
|
||||
#include "hphp/runtime/vm/runtime.h"
|
||||
|
||||
namespace HPHP {
|
||||
@@ -132,8 +133,27 @@ StackValueInfo getStackValue(SSATmp* sp, uint32_t index) {
|
||||
auto const& extra = *inst->extra<InterpOne>();
|
||||
int64_t spAdjustment = extra.cellsPopped - extra.cellsPushed;
|
||||
Type resultType = inst->typeParam();
|
||||
if (index == 0 && !resultType.equals(Type::None)) {
|
||||
return StackValueInfo { resultType };
|
||||
switch (extra.opcode) {
|
||||
// some instructions are kinda funny and mess with the stack
|
||||
// in places other than the top
|
||||
case Op::CGetL2:
|
||||
if (index == 1) return StackValueInfo { resultType };
|
||||
if (index == 0) return getStackValue(prevSp, index);
|
||||
break;
|
||||
case Op::CGetL3:
|
||||
if (index == 2) return StackValueInfo { resultType };
|
||||
if (index < 2) return getStackValue(prevSp, index);
|
||||
break;
|
||||
case Op::UnpackCont:
|
||||
if (index == 0) return StackValueInfo { Type::Cell };
|
||||
if (index == 1) return StackValueInfo { Type::Int };
|
||||
break;
|
||||
|
||||
default:
|
||||
if (index == 0 && !resultType.equals(Type::None)) {
|
||||
return StackValueInfo { resultType };
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// If the index we're looking for is a cell pushed by the InterpOne (other
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário