hphp/runtime/vm/jit/ir-opcode.cpp (868 lines of code) (raw):
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present 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 "hphp/runtime/vm/jit/ir-opcode.h"
#include "hphp/runtime/base/string-data.h"
#include "hphp/runtime/vm/jit/cfg.h"
#include "hphp/runtime/vm/jit/extra-data.h"
#include "hphp/runtime/vm/jit/ir-instruction.h"
#include "hphp/runtime/vm/jit/ir-unit.h"
#include "hphp/runtime/vm/jit/ssa-tmp.h"
#include "hphp/runtime/vm/jit/print.h"
#include "hphp/runtime/vm/jit/type.h"
#include "hphp/runtime/vm/runtime.h"
#include "hphp/util/trace.h"
namespace HPHP::jit {
///////////////////////////////////////////////////////////////////////////////
TRACE_SET_MOD(hhir);
#define NF 0
#define PRc ProducesRC
#define CRc ConsumesRC
#define T Terminal
#define B Branch
#define P Passthrough
#define LA LayoutAgnostic
#define LP (LayoutPreserving|LayoutAgnostic)
#define ND 0
#define D(n) HasDest
#define DofS(n) HasDest
#define DRefineS(n) HasDest
#define DParam(t) HasDest
#define DLdObjCls HasDest
#define DAllocObj HasDest
#define DBespokeElem HasDest
#define DBespokeElemUninit HasDest
#define DBespokePosKey HasDest
#define DBespokePosVal HasDest
#define DVecElem HasDest
#define DDictElem HasDest
#define DModified(n) HasDest
#define DArrLikeSet HasDest
#define DArrLikeUnset HasDest
#define DArrLikeAppend HasDest
#define DKeysetElem HasDest
#define DEscalateToVanilla HasDest
#define DVecKey HasDest
#define DFirstElem HasDest
#define DLastElem HasDest
#define DFirstKey HasDest
#define DLastKey HasDest
#define DLoggingArrLike HasDest
#define DStructDict HasDest
#define DCol HasDest
#define DMulti NaryDest
#define DSetElem HasDest
#define DPtrToParam HasDest
#define DBuiltin HasDest
#define DCall HasDest
#define DGenIter HasDest
#define DSubtract(n,t) HasDest
#define DUnion(...) HasDest
#define DMemoKey HasDest
#define DLvalOfPtr HasDest
#define DTypeCnsClsName HasDest
#define DVerifyParamFail HasDest
#define DPropLval HasDest
#define DElemLval HasDest
#define DElemLvalPos HasDest
#define DCOW HasDest
#define DStructTypeBound HasDest
namespace {
template<Opcode op, uint64_t flags>
struct op_flags {
static constexpr uint64_t value =
(OpHasExtraData<op>::value ? HasExtra : 0) | flags;
static_assert(!(value & ProducesRC) ||
(value & (HasDest | NaryDest)) == HasDest,
"ProducesRC instructions must have exactly one dest");
};
}
OpInfo g_opInfo[] = {
#define O(name, dsts, srcs, flags) \
{ #name, \
op_flags<name, dsts | flags>::value \
},
IR_OPCODES
#undef O
{ 0 }
};
#undef NF
#undef C
#undef E
#undef PRc
#undef CRc
#undef Er
#undef T
#undef B
#undef P
#undef K
#undef ND
#undef D
#undef DofS
#undef DRefineS
#undef DParam
#undef DLdObjCls
#undef DBespokeElemUninit
#undef DBespokeElem
#undef DBespokePosKey
#undef DBespokePosVal
#undef DVecElem
#undef DDictElem
#undef DKeysetElem
#undef DEscalateToVanilla
#undef DVecFirstElem
#undef DVecLastElem
#undef DVecKey
#undef DDictFirstElem
#undef DDictLastElem
#undef DDictFirstKey
#undef DDictLastKey
#undef DKeysetFirstElem
#undef DKeysetLastElem
#undef DLoggingArrLike
#undef DStructDict
#undef DCol
#undef DAllocObj
#undef DMulti
#undef DSetElem
#undef DPtrToParam
#undef DBuiltin
#undef DCall
#undef DGenIter
#undef DSubtract
#undef DUnion
#undef DMemoKey
#undef DLvalOfPtr
#undef DTypeCnsClsName
#undef DVerifyParamFail
#undef DPropLval
#undef DElemLval
#undef DElemLvalPos
#undef DCOW
#undef DStructTypeBound
///////////////////////////////////////////////////////////////////////////////
bool isGuardOp(Opcode opc) {
switch (opc) {
case CheckLoc:
case CheckStk:
case CheckType:
case CheckMBase:
return true;
default:
return false;
}
}
Optional<Opcode> negateCmpOp(Opcode opc) {
switch (opc) {
case GtBool: return LteBool;
case GteBool: return LtBool;
case LtBool: return GteBool;
case LteBool: return GtBool;
case EqBool: return NeqBool;
case NeqBool: return EqBool;
case GtInt: return LteInt;
case GteInt: return LtInt;
case LtInt: return GteInt;
case LteInt: return GtInt;
case EqInt: return NeqInt;
case NeqInt: return EqInt;
// Due to NaN only equality comparisons with doubles can be negated.
case EqDbl: return NeqDbl;
case NeqDbl: return EqDbl;
case GtStr: return LteStr;
case GteStr: return LtStr;
case LtStr: return GteStr;
case LteStr: return GtStr;
case EqStr: return NeqStr;
case NeqStr: return EqStr;
case SameStr: return NSameStr;
case NSameStr: return SameStr;
// Objects can contain a property with NaN, so only equality comparisons can
// be negated.
case EqObj: return NeqObj;
case NeqObj: return EqObj;
case SameObj: return NSameObj;
case NSameObj: return SameObj;
// Arrays/vec/dicts can contain an element with NaN, so only equality
// comparisons can be negated.
case EqArrLike: return NeqArrLike;
case NeqArrLike: return EqArrLike;
case SameArrLike: return NSameArrLike;
case NSameArrLike: return SameArrLike;
case GtRes: return LteRes;
case GteRes: return LtRes;
case LtRes: return GteRes;
case LteRes: return GtRes;
case EqRes: return NeqRes;
case NeqRes: return EqRes;
default: return std::nullopt;
}
}
bool opcodeMayRaise(Opcode opc) {
switch (opc) {
case IsTypeStruct:
return RuntimeOption::EvalIsExprEnableUnresolvedWarning ||
RuntimeOption::EvalIsVecNotices ||
RuntimeOption::EvalWarnOnImplicitCoercionOfEnumValue;
case AddNewElemKeyset:
case AFWHPrepareChild:
case AKExistsObj:
case AllocObj:
case AllocObjReified:
case ArrayMarkLegacyShallow:
case ArrayMarkLegacyRecursive:
case ArrayUnmarkLegacyShallow:
case ArrayUnmarkLegacyRecursive:
case BaseG:
case BespokeAppend:
case BespokeElem:
case BespokeGetThrow:
case BespokeSet:
case BespokeUnset:
case Call:
case CallBuiltin:
case CGetElem:
case CGetProp:
case CGetPropQ:
case CheckClsMethFunc:
case CheckClsReifiedGenericMismatch:
case CheckFunReifiedGenericMismatch:
case CheckInOutMismatch:
case CheckReadonlyMismatch:
case CheckStackOverflow:
case CheckSurpriseAndStack:
case CheckSurpriseFlagsEnter:
case Clone:
case CmpArrLike:
case CmpObj:
case CmpRes:
case ConcatIntStr:
case ConcatStr3:
case ConcatStr4:
case ConcatStrInt:
case ConcatStrStr:
case ConstructInstance:
case ContEnter:
case ConvArrLikeToDict:
case ConvArrLikeToKeyset:
case ConvArrLikeToVec:
case ConvTVToBool:
case ConvTVToDbl:
case ConvTVToInt:
case ConvTVToStr:
case ConvObjToBool:
case ConvObjToDbl:
case ConvObjToDict:
case ConvObjToInt:
case ConvObjToKeyset:
case ConvObjToStr:
case ConvObjToVec:
case Count:
case CreateAAWH:
case DictGet:
case DictSet:
case ElemDictD:
case ElemDictU:
case ElemDX:
case ElemUX:
case ElemX:
case EqArrLike:
case EqObj:
case GetMemoKey:
case GtArrLike:
case GteArrLike:
case GteObj:
case GteRes:
case GtObj:
case GtRes:
case HandleRequestSurprise:
case IncDecElem:
case IncDecProp:
case InitClsCns:
case InitProps:
case InitSProps:
case InitSubClsCns:
case InterpOne:
case IssetElem:
case IssetProp:
case IterInit:
case IterInitK:
case IterNext:
case IterNextK:
case KeysetGet:
case LdCls:
case LdClsCached:
case LdClsCtor:
case LdClsPropAddrOrNull:
case LdClsPropAddrOrRaise:
case LdFunc:
case LdFuncCached:
case LdGblAddr:
case LdGblAddrDef:
case LdObjMethodD:
case LdObjMethodS:
case LdTypeCns:
case LdTypeCnsClsName:
case LdTypeCnsNoThrow:
case LookupClsCns:
case LookupClsCtxCns:
case LookupClsMethod:
case LookupClsMethodCache:
case LookupClsMethodFCache:
case LookupCnsE:
case LookupFuncCached:
case LtArrLike:
case LteArrLike:
case LteObj:
case LteRes:
case LtObj:
case LtRes:
case MapGet:
case MapSet:
case NativeImpl:
case NeqArrLike:
case NeqObj:
case NewKeysetArray:
case NSameArrLike:
case OODeclExists:
case OrdStrIdx:
case OutlineSetOp:
case PrintBool:
case PrintInt:
case PrintStr:
case ProfileSubClsCns:
case PropDX:
case PropQ:
case PropTypeRedefineCheck:
case PropX:
case RaiseCoeffectsCallViolation:
case RaiseCoeffectsFunParamCoeffectRulesViolation:
case RaiseCoeffectsFunParamTypeViolation:
case RaiseError:
case RaiseErrorOnInvalidIsAsExpressionType:
case RaiseForbiddenDynCall:
case RaiseForbiddenDynConstruct:
case RaiseNotice:
case RaiseStrToClassNotice:
case RaiseTooManyArg:
case ThrowUndefPropException:
case ThrowUninitLoc:
case RaiseWarning:
case RecordReifiedGenericsAndGetTSList:
case ResolveTypeStruct:
case ReturnHook:
case SameArrLike:
case SetElem:
case SetNewElem:
case SetNewElemDict:
case SetNewElemKeyset:
case SetNewElemVec:
case SetOpTV:
case SetOpElem:
case SetOpProp:
case SetProp:
case SetRange:
case SetRangeRev:
case StringGet:
case SuspendHookAwaitEF:
case SuspendHookAwaitEG:
case SuspendHookAwaitR:
case SuspendHookCreateCont:
case SuspendHookYield:
case ThrowAsTypeStructException:
case ThrowArrayIndexException:
case ThrowArrayKeyException:
case ThrowCallReifiedFunctionWithoutGenerics:
case ThrowDivisionByZeroException:
case ThrowHasThisNeedStatic:
case ThrowInOutMismatch:
case ThrowReadonlyMismatch:
case ThrowInvalidArrayKey:
case ThrowInvalidOperation:
case ThrowLateInitPropError:
case ThrowMissingArg:
case ThrowMissingThis:
case ThrowCannotModifyReadonlyCollection:
case ThrowLocalMustBeValueTypeException:
case ThrowMustBeEnclosedInReadonly:
case ThrowMustBeMutableException:
case ThrowMustBeReadonlyException:
case ThrowMustBeValueTypeException:
case ThrowOutOfBounds:
case ThrowParameterWrongType:
case UnsetElem:
case UnsetProp:
case VectorSet:
case VerifyParamCallable:
case VerifyParamCls:
case VerifyParamFail:
case VerifyParamFailHard:
case VerifyProp:
case VerifyPropAll:
case VerifyPropCls:
case VerifyPropCoerce:
case VerifyPropCoerceAll:
case VerifyPropFail:
case VerifyPropFailHard:
case VerifyReifiedLocalType:
case VerifyReifiedReturnType:
case VerifyRetCallable:
case VerifyRetCls:
case VerifyRetFail:
case VerifyRetFailHard:
return true;
case AbsDbl:
case AddDbl:
case AddInt:
case AddIntO:
case AddNewElemVec:
case AddOffset:
case AdvanceDictPtrIter:
case AdvanceVecPtrIter:
case AFWHBlockOn:
case AFWHPushTailFrame:
case AKExistsDict:
case AKExistsKeyset:
case AllocBespokeStructDict:
case AllocInitROM:
case AllocStructDict:
case AllocVec:
case AndInt:
case AssertLoc:
case AssertMBase:
case AssertNonNull:
case AssertStk:
case AssertType:
case AsyncFuncRet:
case AsyncFuncRetPrefetch:
case AsyncFuncRetSlow:
case AsyncGenRetR:
case AsyncGenYieldR:
case AsyncSwitchFast:
case BeginCatch:
case BeginInlining:
case BespokeEscalateToVanilla:
case BespokeGet:
case BespokeIterFirstPos:
case BespokeIterLastPos:
case BespokeIterEnd:
case BespokeIterGetKey:
case BespokeIterGetVal:
case Ceil:
case CheckArrayCOW:
case CheckCold:
case CheckDictKeys:
case CheckDictOffset:
case CheckFuncNeedsCoverage:
case CheckInit:
case CheckInitMem:
case CheckIter:
case CheckKeysetOffset:
case CheckLoc:
case CheckMBase:
case CheckMissingKeyInArrLike:
case CheckMROProp:
case CheckNonNull:
case CheckNullptr:
case CheckRange:
case CheckRDSInitialized:
case CheckSmashableClass:
case CheckStk:
case CheckSubClsCns:
case CheckSurpriseFlags:
case CheckType:
case CheckTypeMem:
case CheckVecBounds:
case ChrInt:
case ClassHasAttr:
case CmpBool:
case CmpDbl:
case CmpInt:
case CmpStr:
case ColIsEmpty:
case ColIsNEmpty:
case Conjure:
case ConjureUse:
case ConstructClosure:
case ContArIncIdx:
case ContArIncKey:
case ContArUpdateIdx:
case ContCheckNext:
case ContValid:
case ConvBoolToDbl:
case ConvBoolToInt:
case ConvDblToBool:
case ConvDblToInt:
case ConvDblToStr:
case ConvFuncPrologueFlagsToARFlags:
case ConvIntToBool:
case ConvIntToDbl:
case ConvIntToStr:
case ConvPtrToLval:
case ConvResToDbl:
case ConvResToInt:
case ConvStrToBool:
case ConvStrToDbl:
case ConvStrToInt:
case CopyArray:
case CountCollection:
case CountDict:
case CountKeyset:
case CountVec:
case CountWHNotDone:
case CreateAFWH:
case CreateAGen:
case CreateAGWH:
case CreateGen:
case CreateSSWH:
case DbgAssertFunc:
case DbgAssertRefCount:
case DbgCheckLocalsDecRefd:
case DbgTraceCall:
case DbgTrashFrame:
case DbgTrashMem:
case DbgTrashStk:
case DblAsBits:
case DebugBacktrace:
case DecRef:
case ReleaseShallow:
case DecReleaseCheck:
case DecRefNZ:
case DefConst:
case DefFP:
case DefFrameRelSP:
case DefFuncEntryFP:
case DefFuncPrologueCallee:
case DefFuncPrologueCtx:
case DefFuncPrologueFlags:
case DefFuncPrologueNumArgs:
case DefLabel:
case DefRegSP:
case DictFirst:
case DictFirstKey:
case DictGetK:
case DictGetQuiet:
case DictIdx:
case DictIsset:
case DictLast:
case DictLastKey:
case DirFromFilepath:
case DivDbl:
case DivInt:
case StVMFP:
case StVMSP:
case StVMPC:
case StVMReturnAddr:
case ElemDictK:
case EndBlock:
case EndCatch:
case EndGuards:
case EndInlining:
case EnterPrologue:
case EnterTCUnwind:
case EnterTranslation:
case EqArrayDataPtr:
case EqBool:
case EqCls:
case EqLazyCls:
case EqDbl:
case EqFunc:
case EqInt:
case EqPtrIter:
case EqRes:
case EqStr:
case EqStrPtr:
case ExitPrologue:
case ExtendsClass:
case FinishMemberOp:
case Floor:
case FuncCred:
case FuncHasAttr:
case GenericRetDecRefs:
case LoadBCSP:
case GetDictPtrIter:
case GetMemoKeyScalar:
case GetTime:
case GetTimeNs:
case GetVecPtrIter:
case GtBool:
case GtDbl:
case GteBool:
case GteDbl:
case GteInt:
case GteStr:
case GtInt:
case GtStr:
case HasReifiedGenerics:
case HasToString:
case IncCallCounter:
case IncProfCounter:
case IncRef:
case IncStat:
case InitDictElem:
case InitFrame:
case InitObjMemoSlots:
case InitObjProps:
case InitStructElem:
case InitStructPositions:
case InitThrowableFileAndLine:
case InitVecElem:
case InitVecElemLoop:
case InlineCall:
case InstanceOf:
case InstanceOfBitmask:
case InstanceOfIface:
case InstanceOfIfaceVtable:
case InterfaceSupportsArrLike:
case InterfaceSupportsDbl:
case InterfaceSupportsInt:
case InterfaceSupportsStr:
case InterpOneCF:
case IsCol:
case IsFunReifiedGenericsMatched:
case IsNType:
case IsNTypeMem:
case IsLegacyArrLike:
case IsType:
case IsTypeMem:
case IsTypeStructCached:
case IsWaitHandle:
case IterFree:
case Jmp:
case JmpNZero:
case JmpPlaceholder:
case JmpSSwitchDest:
case JmpSwitchDest:
case JmpZero:
case KeysetFirst:
case KeysetGetK:
case KeysetGetQuiet:
case KeysetIdx:
case KeysetIsset:
case KeysetLast:
case KillActRec:
case KillIter:
case KillLoc:
case LdAFWHActRec:
case LdARFlags:
case LdBindAddr:
case LdClosureCls:
case LdClosureThis:
case LdClsCachedSafe:
case LdClsCns:
case LdClsCnsVecLen:
case LdClsFromClsMeth:
case LdClsFromRClsMeth:
case LdClsInitData:
case LdClsInitElem:
case LdClsMethod:
case LdClsMethodCacheCls:
case LdClsMethodCacheFunc:
case LdClsMethodFCacheFunc:
case LdClsName:
case LdCns:
case LdColDict:
case LdColVec:
case LdContActRec:
case LdContArKey:
case LdContArValue:
case LdContField:
case LdContResumeAddr:
case LdFrameCls:
case LdFrameThis:
case LdFuncCls:
case LdARFunc:
case LdFuncFromClsMeth:
case LdFuncFromRClsMeth:
case LdFuncFromRFunc:
case LdFuncInOutBits:
case LdFuncName:
case LdFuncNumParams:
case LdFuncRequiredCoeffects:
case LdFuncVecLen:
case LdGenericsFromRClsMeth:
case LdGenericsFromRFunc:
case LdIfaceMethod:
case LdImplicitContext:
case LdInitPropAddr:
case LdInitRDSAddr:
case LdIterBase:
case LdIterEnd:
case LdIterPos:
case LdLazyCls:
case LdLazyClsName:
case LdLoc:
case LdLocAddr:
case LdLocForeign:
case LdMBase:
case LdMem:
case LdMethCallerName:
case LdMIStateTempBaseAddr:
case LdObjClass:
case LdObjInvoke:
case LdOutAddr:
case LdPairElem:
case LdPropAddr:
case LdPtrIterKey:
case LdPtrIterVal:
case LdRDSAddr:
case LdResolvedTypeCns:
case LdResolvedTypeCnsClsName:
case LdResolvedTypeCnsNoCheck:
case LdRetVal:
case LdSmashable:
case LdSmashableFunc:
case LdSSwitchDest:
case LdStk:
case LdStkAddr:
case LdStrLen:
case LdSubClsCns:
case LdTVAux:
case LdTVFromRDS:
case LdUnitPerRequestFilepath:
case LdUnwinderValue:
case LdMonotypeDictTombstones:
case LdMonotypeDictKey:
case LdMonotypeDictVal:
case LdMonotypeVecElem:
case LdVecElem:
case LdVecElemAddr:
case LdVectorSize:
case LdWHNotDone:
case LdWHResult:
case LdWHState:
case LIterInit:
case LIterInitK:
case LIterNext:
case LIterNextK:
case LockObj:
case LogArrayReach:
case LogGuardFailure:
case LookupClsRDS:
case LookupSPropSlot:
case Lshr:
case LtBool:
case LtDbl:
case LteBool:
case LteDbl:
case LteInt:
case LteStr:
case LtInt:
case LtStr:
case MapIsset:
case MarkRDSAccess:
case MarkRDSInitialized:
case MemoGetInstanceCache:
case MemoGetInstanceValue:
case MemoGetStaticCache:
case MemoGetStaticValue:
case MemoGetLSBCache:
case MemoGetLSBValue:
case MemoSetInstanceCache:
case MemoSetInstanceValue:
case MemoSetStaticCache:
case MemoSetStaticValue:
case MemoSetLSBCache:
case MemoSetLSBValue:
case MethodExists:
case Mod:
case Mov:
case MulDbl:
case MulInt:
case MulIntO:
case NeqBool:
case NeqDbl:
case NeqInt:
case NeqRes:
case NeqStr:
case NewClsMeth:
case NewRClsMeth:
case NewCol:
case NewColFromArray:
case NewDictArray:
case NewInstanceRaw:
case NewLoggingArray:
case NewPair:
case NewRFunc:
case NewStructDict:
case NewBespokeStructDict:
case NInstanceOfBitmask:
case Nop:
case NSameObj:
case NSameStr:
case OrdStr:
case OrInt:
case PairIsset:
case ProfileArrayCOW:
case ProfileArrLikeProps:
case ProfileCall:
case ProfileDecRef:
case ProfileDictAccess:
case ProfileGlobal:
case ProfileInstanceCheck:
case ProfileIsTypeStruct:
case ProfileKeysetAccess:
case ProfileMethod:
case ProfileProp:
case ProfileSwitchDest:
case ProfileType:
case RBTraceEntry:
case RBTraceMsg:
case RecordFuncCall:
case ReqBindJmp:
case ReqInterpBBNoTranslate:
case ReqRetranslate:
case ReqRetranslateOpt:
case ReserveVecNewElem:
case RestoreErrorLevel:
case RetCtrl:
case SameObj:
case SameStr:
case Select:
case Shl:
case Shr:
case Sqrt:
case StArResumeAddr:
case StClsInitElem:
case StClosureArg:
case StContArKey:
case StContArState:
case StContArValue:
case StFrameCtx:
case StFrameFunc:
case StFrameMeta:
case StImplicitContext:
case StImplicitContextWH:
case StIterBase:
case StIterEnd:
case StIterPos:
case StIterType:
case StLoc:
case StLocMeta:
case StLocRange:
case StMBase:
case StMem:
case StMemMeta:
case StOutValue:
case StrictlyIntegerConv:
case StringIsset:
case StructDictAddNextSlot:
case StructDictElemAddr:
case StructDictSlot:
case StructDictTypeBoundCheck:
case StructDictUnset:
case StMROProp:
case StPtrAt:
case StTypeAt:
case StStk:
case StStkMeta:
case StStkRange:
case StVMRegState:
case StTVInRDS:
case SubDbl:
case SubInt:
case SubIntO:
case Unreachable:
case UnwindCheckSideExit:
case VecFirst:
case VecLast:
case VectorIsset:
case VoidPtrAsDataType:
case XorBool:
case XorInt:
case ZeroErrorLevel:
return false;
}
not_reached();
}
///////////////////////////////////////////////////////////////////////////////
}