summaryrefslogtreecommitdiff
path: root/src/jit/gcencode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/gcencode.cpp')
-rw-r--r--src/jit/gcencode.cpp102
1 files changed, 74 insertions, 28 deletions
diff --git a/src/jit/gcencode.cpp b/src/jit/gcencode.cpp
index dcca19ebe8..4c300ac15f 100644
--- a/src/jit/gcencode.cpp
+++ b/src/jit/gcencode.cpp
@@ -1318,6 +1318,8 @@ size_t GCInfo::gcInfoBlockHdrSave(
header->syncStartOffset = INVALID_SYNC_OFFSET;
header->syncEndOffset = INVALID_SYNC_OFFSET;
+#ifndef UNIX_X86_ABI
+ // JIT is responsible for synchronization on funclet-based EH model that x86/Linux uses.
if (compiler->info.compFlags & CORINFO_FLG_SYNCH)
{
assert(compiler->syncStartEmitCookie != NULL);
@@ -1332,6 +1334,7 @@ size_t GCInfo::gcInfoBlockHdrSave(
// synchronized methods can't have more than 1 epilog
assert(header->epilogCount <= 1);
}
+#endif
header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET;
@@ -2424,7 +2427,9 @@ DONE_VLT:
assert((codeDelta & 0x7) == codeDelta);
*dest++ = 0xB0 | (BYTE)codeDelta;
+#ifndef UNIX_X86_ABI
assert(!compiler->isFramePointerUsed());
+#endif
/* Remember the new 'last' offset */
@@ -3844,13 +3849,15 @@ struct InterruptibleRangeReporter
}
};
-void GCInfo::gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder,
- unsigned codeSize,
- unsigned prologSize,
- MakeRegPtrMode mode)
+void GCInfo::gcMakeRegPtrTable(
+ GcInfoEncoder* gcInfoEncoder, unsigned codeSize, unsigned prologSize, MakeRegPtrMode mode, unsigned* callCntRef)
{
GCENCODER_WITH_LOGGING(gcInfoEncoderWithLog, gcInfoEncoder);
+ const bool noTrackedGCSlots =
+ (compiler->opts.MinOpts() && !compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) &&
+ !JitConfig.JitMinOptsTrackGCrefs());
+
if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS)
{
m_regSlotMap = new (compiler->getAllocator()) RegSlotMap(compiler->getAllocator());
@@ -3961,14 +3968,25 @@ void GCInfo::gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder,
{
stackSlotBase = GC_FRAMEREG_REL;
}
- StackSlotIdKey sskey(varDsc->lvStkOffs, (stackSlotBase == GC_FRAMEREG_REL), flags);
- GcSlotId varSlotId;
- if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS)
+ if (noTrackedGCSlots)
{
- if (!m_stackSlotMap->Lookup(sskey, &varSlotId))
+ // No need to hash/lookup untracked GC refs; just grab a new Slot Id.
+ if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS)
{
- varSlotId = gcInfoEncoderWithLog->GetStackSlotId(varDsc->lvStkOffs, flags, stackSlotBase);
- m_stackSlotMap->Set(sskey, varSlotId);
+ gcInfoEncoderWithLog->GetStackSlotId(varDsc->lvStkOffs, flags, stackSlotBase);
+ }
+ }
+ else
+ {
+ StackSlotIdKey sskey(varDsc->lvStkOffs, (stackSlotBase == GC_FRAMEREG_REL), flags);
+ GcSlotId varSlotId;
+ if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS)
+ {
+ if (!m_stackSlotMap->Lookup(sskey, &varSlotId))
+ {
+ varSlotId = gcInfoEncoderWithLog->GetStackSlotId(varDsc->lvStkOffs, flags, stackSlotBase);
+ m_stackSlotMap->Set(sskey, varSlotId);
+ }
}
}
}
@@ -4204,9 +4222,24 @@ void GCInfo::gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder,
{
if (gcCallDescList != nullptr)
{
- for (CallDsc* call = gcCallDescList; call != nullptr; call = call->cdNext)
+ if (noTrackedGCSlots)
{
- numCallSites++;
+ // We have the call count from the previous run.
+ numCallSites = *callCntRef;
+
+ // If there are no calls, tell the world and bail.
+ if (numCallSites == 0)
+ {
+ gcInfoEncoderWithLog->DefineCallSites(nullptr, nullptr, 0);
+ return;
+ }
+ }
+ else
+ {
+ for (CallDsc* call = gcCallDescList; call != nullptr; call = call->cdNext)
+ {
+ numCallSites++;
+ }
}
pCallSites = new (compiler, CMK_GC) unsigned[numCallSites];
pCallSiteSizes = new (compiler, CMK_GC) BYTE[numCallSites];
@@ -4216,17 +4249,8 @@ void GCInfo::gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder,
// Now consider every call.
for (CallDsc* call = gcCallDescList; call != nullptr; call = call->cdNext)
{
- if (mode == MAKE_REG_PTR_MODE_DO_WORK)
- {
- pCallSites[callSiteNum] = call->cdOffs - call->cdCallInstrSize;
- pCallSiteSizes[callSiteNum] = call->cdCallInstrSize;
- callSiteNum++;
- }
-
- unsigned nextOffset;
-
// Figure out the code offset of this entry.
- nextOffset = call->cdOffs;
+ unsigned nextOffset = call->cdOffs;
// As far as I (DLD, 2010) can determine by asking around, the "call->u1.cdArgMask"
// and "cdArgCnt" cases are to handle x86 situations in which a call expression is nested as an
@@ -4251,13 +4275,35 @@ void GCInfo::gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder,
assert(call->cdOffs >= call->cdCallInstrSize);
// call->cdOffs is actually the offset of the instruction *following* the call, so subtract
// the call instruction size to get the offset of the actual call instruction...
- unsigned callOffset = call->cdOffs - call->cdCallInstrSize;
- // Record that these registers are live before the call...
- gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, callOffset, regMask, GC_SLOT_LIVE, byrefRegMask, nullptr);
- // ...and dead after.
- gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, call->cdOffs, regMask, GC_SLOT_DEAD, byrefRegMask,
- nullptr);
+ unsigned callOffset = nextOffset - call->cdCallInstrSize;
+
+ if (noTrackedGCSlots && regMask == 0)
+ {
+ // No live GC refs in regs at the call -> don't record the call.
+ }
+ else
+ {
+ // Append an entry for the call if doing the real thing.
+ if (mode == MAKE_REG_PTR_MODE_DO_WORK)
+ {
+ pCallSites[callSiteNum] = callOffset;
+ pCallSiteSizes[callSiteNum] = call->cdCallInstrSize;
+ }
+ callSiteNum++;
+
+ // Record that these registers are live before the call...
+ gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, callOffset, regMask, GC_SLOT_LIVE, byrefRegMask,
+ nullptr);
+ // ...and dead after.
+ gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, nextOffset, regMask, GC_SLOT_DEAD, byrefRegMask,
+ nullptr);
+ }
}
+ // Make sure we've recorded the expected number of calls
+ assert(mode != MAKE_REG_PTR_MODE_DO_WORK || numCallSites == callSiteNum);
+ // Return the actual recorded call count to the caller
+ *callCntRef = callSiteNum;
+
// OK, define the call sites.
if (mode == MAKE_REG_PTR_MODE_DO_WORK)
{