void* FixupMapUnitTest::reader(void* that) { FixupMap* m = (FixupMap*)that; const StringData* sd = StringData::GetStaticString("test"); // ar2: a mock actrec, requires a Func, which can't be builtin. Unit u; Func f(u, 1, 1, 1, 0, 0, sd, AttrNone, true, NULL, 0, false); ActRec ar2; ar2.m_savedRip = 0xdeadbeef; ar2.m_savedRbp = 0; ar2.m_func = &f; for (int i = 1; i < kNumToCheck; i++) { // ar1(i) -> ar2(DONTCARE) -> NULL ActRec ar1; ar1.m_savedRbp = (uint64_t)&ar2; ar1.m_savedRip = i; FixupMap::VMRegs vmr = { 0, 0, 0 }; while (!m->getFrameRegs(&ar1, 0, &vmr)) { // Has to succeed eventually. } ASSERT(vmr.m_pc == u.entry() + i * kPcMul); ASSERT(vmr.m_fp == &ar2); ASSERT(vmr.m_sp == (TypedValue*)&ar2 - i * kSpMul); } return NULL; }
void emitCheckSurpriseFlagsEnter(CodeBlock& mainCode, CodeBlock& stubsCode, bool inTracelet, FixupMap& fixupMap, Fixup fixup) { Asm a { mainCode }; Asm astubs { stubsCode }; emitTestSurpriseFlags(a); a. jnz (stubsCode.frontier()); astubs. movq (rVmFp, argNumToRegName[0]); if (false) { // typecheck const ActRec* ar = nullptr; functionEnterHelper(ar); } emitCall(astubs, (TCA)&functionEnterHelper); if (inTracelet) { fixupMap.recordSyncPoint(stubsCode.frontier(), fixup.m_pcOffset, fixup.m_spOffset); } else { // If we're being called while generating a func prologue, we // have to record the fixup directly in the fixup map instead of // going through the pending fixup path like normal. fixupMap.recordFixup(stubsCode.frontier(), fixup); } astubs. jmp (mainCode.frontier()); }
/* * We've taken a few risks in the name of performance. In debug builds, * exercise a few million racy reads/writes to make sure we don't publish * partial TCAs. */ void* FixupMapUnitTest::writer(void* that) { // Give the readers time to wind up. usleep(1000); FixupMap* m = (FixupMap*)that; for (int i = 1; i < kNumToCheck; i++) { Fixup fxp(kPcMul * i, kSpMul * i); m->recordFixup(TCA(uintptr_t(i)), fxp); } return NULL; }
void TestEITFixups::test64BitEnum(void) { QVERIFY(EITFixUp::kFixUnitymedia != EITFixUp::kFixNone); QVERIFY(EITFixUp::kFixATV != EITFixUp::kFixNone); QVERIFY(EITFixUp::kFixDisneyChannel != EITFixUp::kFixNone); #if 0 QCOMPARE(QString::number(EITFixUp::kFixUnitymedia), QString::number(EITFixUp::kFixNone)); #endif #if 0 // needs some casting around FixupValue theFixup = EITFixUp::kFixUnitymedia; QCOMPARE(EITFixUp::kFixUnitymedia, theFixup); #endif // this is likely what happens somewhere in the fixup pipeline QCOMPARE((FixupValue)((uint32_t)EITFixUp::kFixUnitymedia), (FixupValue)EITFixUp::kFixNone); FixupMap fixes; fixes[0xFFFFull<<32] = EITFixUp::kFixDisneyChannel; fixes[0xFFFFull<<32] |= EITFixUp::kFixATV; FixupValue fix; fix = EITFixUp::kFixGenericDVB; fix |= fixes.value(0xFFFFull<<32); QCOMPARE(fix, EITFixUp::kFixGenericDVB | EITFixUp::kFixDisneyChannel | EITFixUp::kFixATV); QVERIFY(EITFixUp::kFixATV & fix); // did kFixGreekCategories = 1<<31 cause issues? #if 0 QCOMPARE(QString::number(1<<31, 16), QString::number(1u<<31, 16)); #endif // two different flags, fixed version QVERIFY(!(1ull<<31 & 1ull<<32)); // oops, this is true, so setting the old kFixGreekCategories also set all flags following it QVERIFY(1<<31 & 1ull<<32); }