Skip to content

Commit a8db2b3

Browse files
committed
[MERGE #2293 @leirocks] some write barrier fixes
Merge pull request #2293 from leirocks:wb3 - false poisitive on EntryPointInfo->jsMethod after native address reuse in recycler - false poisitive in arena allocator cacheBlockEnd reused in leaf block in recycler (sharing same page allocator) - overload ChangeToAssign in JIT code, check all posible assign for write barrier - missing barriers in various location
2 parents 2a34df5 + ee6913a commit a8db2b3

File tree

79 files changed

+5740
-5311
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+5740
-5311
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,13 @@ endif(CLR_CMAKE_PLATFORM_XPLAT)
292292
if(ENABLE_FULL_LTO_SH)
293293
unset(DENABLE_FULL_LTO_SH CACHE)
294294
add_compile_options(-flto)
295+
set (CMAKE_SHARED_LINKER_FLAGS "-flto")
296+
set (CMAKE_EXE_LINKER_FLAGS "-flto")
295297
elseif(ENABLE_THIN_LTO_SH)
296298
unset(ENABLE_THIN_LTO_SH CACHE)
297299
add_compile_options(-flto=thin)
300+
set (CMAKE_SHARED_LINKER_FLAGS "-flto=thin")
301+
set (CMAKE_EXE_LINKER_FLAGS "-flto=thin")
298302
endif()
299303

300304
if(CMAKE_BUILD_TYPE STREQUAL Debug)

bin/ch/ch.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ HRESULT ExecuteTest(const char* fileName)
615615
HRESULT ExecuteTestWithMemoryCheck(char* fileName)
616616
{
617617
HRESULT hr = E_FAIL;
618+
#ifdef _WIN32 // looks on linux it always leak ThreadContextTLSEntry since there's no DllMain
618619
#ifdef CHECK_MEMORY_LEAK
619620
// Always check memory leak, unless user specified the flag already
620621
if (!ChakraRTInterface::IsEnabledCheckMemoryFlag())
@@ -626,6 +627,7 @@ HRESULT ExecuteTestWithMemoryCheck(char* fileName)
626627
// We will re-enable it if there is no unhandled exceptions
627628
ChakraRTInterface::SetEnableCheckMemoryLeakOutput(false);
628629
#endif
630+
#endif
629631

630632
#ifdef _WIN32
631633
__try

lib/Backend/BailOut.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,7 @@ BailOutRecord::BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptF
14941494

14951495
newInstance->m_reader.Create(executeFunction);
14961496

1497-
generator->SetFrame(newInstance);
1497+
generator->SetFrame(newInstance, varSizeInBytes);
14981498
}
14991499
}
15001500
else

lib/Backend/Func.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
143143
, m_forInEnumeratorArrayOffset(-1)
144144
, argInsCount(0)
145145
, m_globalObjTypeSpecFldInfoArray(nullptr)
146+
#ifdef RECYCLER_WRITE_BARRIER_JIT
146147
, m_lowerer(nullptr)
148+
#endif
147149
{
148150

149151
Assert(this->IsInlined() == !!runtimeInfo);

lib/Backend/JITTimeConstructorCache.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ JITTimeConstructorCache::Clone(JitArenaAllocator* allocator) const
5151
BVSparse<JitArenaAllocator>*
5252
JITTimeConstructorCache::GetGuardedPropOps() const
5353
{
54-
return (BVSparse<JitArenaAllocator>*)m_data.guardedPropOps;
54+
return (BVSparse<JitArenaAllocator>*)(m_data.guardedPropOps & ~(intptr_t)1);
5555
}
5656

5757
void
@@ -60,6 +60,7 @@ JITTimeConstructorCache::EnsureGuardedPropOps(JitArenaAllocator* allocator)
6060
if (GetGuardedPropOps() == nullptr)
6161
{
6262
m_data.guardedPropOps = (intptr_t)Anew(allocator, BVSparse<JitArenaAllocator>, allocator);
63+
m_data.guardedPropOps |= 1; // tag it to prevent false positive after the arena address reuse in recycler
6364
}
6465
}
6566

lib/Backend/Lower.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,34 @@ Lowerer::Lower()
101101

102102
this->LowerRange(m_func->m_headInstr, m_func->m_tailInstr, defaultDoFastPath, loopFastPath);
103103

104+
#if DBG
105+
// TODO: (leish)(swb) implement for arm
106+
#if defined(_M_IX86) || defined(_M_AMD64)
107+
if (CONFIG_FLAG(ForceSoftwareWriteBarrier) && CONFIG_FLAG(RecyclerVerifyMark))
108+
{
109+
// find out all write barrier setting instr, call Recycler::WBSetBit for verification purpose
110+
// should do this in LowererMD::GenerateWriteBarrier, however, can't insert call instruction there
111+
FOREACH_INSTR_EDITING(instr, instrNext, m_func->m_headInstr)
112+
if (instr->m_src1 && instr->m_src1->IsAddrOpnd())
113+
{
114+
IR::AddrOpnd* addrOpnd = instr->m_src1->AsAddrOpnd();
115+
if (addrOpnd->GetAddrOpndKind() == IR::AddrOpndKindWriteBarrierCardTable)
116+
{
117+
auto& leaInstr = instr->m_prev->m_prev;
118+
auto& shrInstr = instr->m_prev;
119+
Assert(leaInstr->m_opcode == Js::OpCode::LEA);
120+
Assert(shrInstr->m_opcode == Js::OpCode::SHR);
121+
m_lowererMD.LoadHelperArgument(shrInstr, leaInstr->m_dst);
122+
IR::Instr* instrCall = IR::Instr::New(Js::OpCode::Call, m_func);
123+
shrInstr->InsertBefore(instrCall);
124+
m_lowererMD.ChangeToHelperCall(instrCall, IR::HelperWriteBarrierSetVerifyBit);
125+
}
126+
}
127+
NEXT_INSTR_EDITING
128+
}
129+
#endif
130+
#endif
131+
104132
this->m_func->ClearCloneMap();
105133

106134
if (m_func->HasAnyStackNestedFunc())
@@ -14530,7 +14558,7 @@ IR::Instr *Lowerer::InsertMove(IR::Opnd *dst, IR::Opnd *src, IR::Instr *const in
1453014558
}
1453114559
else
1453214560
{
14533-
LowererMD::ChangeToAssign(instr);
14561+
LowererMD::ChangeToAssignNoBarrierCheck(instr);
1453414562
}
1453514563

1453614564
return instr;

lib/Backend/Lower.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,15 @@ class Lowerer
5757
, m_int64RegPairMap(nullptr)
5858
#endif
5959
{
60+
#ifdef RECYCLER_WRITE_BARRIER_JIT
6061
m_func->m_lowerer = this;
62+
#endif
6163
}
6264
~Lowerer()
6365
{
66+
#ifdef RECYCLER_WRITE_BARRIER_JIT
6467
m_func->m_lowerer = nullptr;
68+
#endif
6569
}
6670

6771
void Lower();

lib/Backend/LowerMDShared.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,17 @@ IR::Instr* LowererMD::ChangeToHelperCallMem(IR::Instr * instr, IR::JnHelperMeth
756756
///----------------------------------------------------------------------------
757757

758758
IR::Instr *
759-
LowererMD::ChangeToAssign(IR::Instr * instr)
759+
LowererMD::ChangeToAssignNoBarrierCheck(IR::Instr * instr)
760760
{
761761
return ChangeToAssign(instr, instr->GetDst()->GetType());
762762
}
763763

764+
IR::Instr *
765+
LowererMD::ChangeToAssign(IR::Instr * instr)
766+
{
767+
return ChangeToWriteBarrierAssign(instr, instr->m_func);
768+
}
769+
764770
IR::Instr *
765771
LowererMD::ChangeToAssign(IR::Instr * instr, IRType type)
766772
{
@@ -4712,7 +4718,7 @@ LowererMD::GenerateLoadPolymorphicInlineCacheSlot(IR::Instr * instrLdSt, IR::Reg
47124718
instrLdSt->InsertBefore(instr);
47134719
}
47144720

4715-
void
4721+
IR::Instr *
47164722
LowererMD::ChangeToWriteBarrierAssign(IR::Instr * assignInstr, const Func* func)
47174723
{
47184724
#ifdef RECYCLER_WRITE_BARRIER_JIT
@@ -4747,17 +4753,19 @@ LowererMD::ChangeToWriteBarrierAssign(IR::Instr * assignInstr, const Func* func)
47474753
}
47484754
#endif
47494755

4750-
ChangeToAssign(assignInstr);
4756+
IR::Instr * instr = ChangeToAssignNoBarrierCheck(assignInstr);
47514757

47524758
// Now insert write barrier if necessary
47534759
#ifdef RECYCLER_WRITE_BARRIER_JIT
47544760
if (isPossibleBarrieredDest
47554761
&& assignInstr->m_opcode == Js::OpCode::MOV // ignore SSE instructions like MOVSD
47564762
&& assignInstr->GetSrc1()->IsWriteBarrierTriggerableValue())
47574763
{
4758-
func->GetTopFunc()->m_lowerer->GetLowererMD()->GenerateWriteBarrier(assignInstr);
4764+
LowererMD::GenerateWriteBarrier(assignInstr);
47594765
}
47604766
#endif
4767+
4768+
return instr;
47614769
}
47624770

47634771
void
@@ -4826,18 +4834,6 @@ LowererMD::GenerateWriteBarrier(IR::Instr * assignInstr)
48264834
IR::RegOpnd * indexOpnd = IR::RegOpnd::New(TyMachPtr, assignInstr->m_func);
48274835
IR::Instr * loadIndexInstr = IR::Instr::New(Js::OpCode::LEA, indexOpnd, assignInstr->GetDst(), assignInstr->m_func);
48284836
assignInstr->InsertBefore(loadIndexInstr);
4829-
4830-
#if DBG
4831-
// CALL Recycler::WBSetBitJIT
4832-
if (CONFIG_FLAG(ForceSoftwareWriteBarrier) && CONFIG_FLAG(RecyclerVerifyMark))
4833-
{
4834-
this->LoadHelperArgument(assignInstr, indexOpnd);
4835-
IR::Instr* instrCall = IR::Instr::New(Js::OpCode::Call, m_func);
4836-
assignInstr->InsertBefore(instrCall);
4837-
this->ChangeToHelperCall(instrCall, IR::HelperWriteBarrierSetVerifyBit);
4838-
}
4839-
#endif
4840-
48414837
IR::Instr * shiftBitInstr = IR::Instr::New(Js::OpCode::SHR, indexOpnd, indexOpnd,
48424838
IR::IntConstOpnd::New(12 /* 1 << 12 = 4096 */, TyInt8, assignInstr->m_func), assignInstr->m_func);
48434839
assignInstr->InsertBefore(shiftBitInstr);

lib/Backend/LowerMDShared.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class LowererMD
8585
static IR::Instr * CreateAssign(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsertPt, bool generateWriteBarrier = true);
8686

8787
static IR::Instr * ChangeToAssign(IR::Instr * instr);
88+
static IR::Instr * ChangeToAssignNoBarrierCheck(IR::Instr * instr);
8889
static IR::Instr * ChangeToAssign(IR::Instr * instr, IRType type);
8990
static IR::Instr * ChangeToLea(IR::Instr *const instr, bool postRegAlloc = false);
9091
static void ImmedSrcToReg(IR::Instr * instr, IR::Opnd * newOpnd, int srcNum);
@@ -305,7 +306,7 @@ class LowererMD
305306

306307
void GenerateWriteBarrierAssign(IR::IndirOpnd * opndDst, IR::Opnd * opndSrc, IR::Instr * insertBeforeInstr);
307308
void GenerateWriteBarrierAssign(IR::MemRefOpnd * opndDst, IR::Opnd * opndSrc, IR::Instr * insertBeforeInstr);
308-
static void ChangeToWriteBarrierAssign(IR::Instr * assignInstr, const Func* func);
309+
static IR::Instr * ChangeToWriteBarrierAssign(IR::Instr * assignInstr, const Func* func);
309310

310311
static IR::BranchInstr * GenerateLocalInlineCacheCheck(IR::Instr * instrLdSt, IR::RegOpnd * opndType, IR::RegOpnd * opndInlineCache, IR::LabelInstr * labelNext, bool checkTypeWithoutProperty = false);
311312
static IR::BranchInstr * GenerateProtoInlineCacheCheck(IR::Instr * instrLdSt, IR::RegOpnd * opndType, IR::RegOpnd * opndInlineCache, IR::LabelInstr * labelNext);
@@ -398,7 +399,7 @@ class LowererMD
398399

399400
IR::LabelInstr* EmitLoadFloatCommon(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr, bool needLabelHelper);
400401
#ifdef RECYCLER_WRITE_BARRIER
401-
IR::Instr* GenerateWriteBarrier(IR::Instr * assignInstr);
402+
static IR::Instr* GenerateWriteBarrier(IR::Instr * assignInstr);
402403
#endif
403404

404405
// Data

lib/Backend/Sym.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ StackSym::IsArgSlotSym() const
8686
inline bool
8787
StackSym::IsParamSlotSym() const
8888
{
89-
return m_isParamSym;
89+
return m_isParamSym;
9090
}
9191

9292
///----------------------------------------------------------------------------

0 commit comments

Comments
 (0)