Skip to content

Commit c630b82

Browse files
committed
Implement localloc IL instruction
- Add handler for instruction. Add storage pointers to stack frame to allow dealocation on moethod return.
1 parent 577be8f commit c630b82

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

src/CLR/Core/CLR_RT_StackFrame.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ HRESULT CLR_RT_StackFrame::Push(CLR_RT_Thread *th, const CLR_RT_MethodDef_Instan
120120
//
121121
// Initialize generic type context storage to invalid
122122
stack->m_genericTypeSpecStorage.Clear();
123+
124+
// initialize localloc elements
125+
stack->m_localAllocCount = 0;
126+
for (CLR_INT32 i = 0; i < CLR_RT_StackFrame::c_Max_Localloc_Count; i++)
127+
{
128+
stack->m_localAllocs[i] = nullptr;
129+
}
130+
123131
//
124132
#ifndef NANOCLR_NO_IL_INLINE
125133
stack->m_inlineFrame = nullptr;
@@ -323,6 +331,11 @@ bool CLR_RT_StackFrame::PushInline(
323331
m_inlineFrame->m_frame.m_call = m_call;
324332
m_inlineFrame->m_frame.m_evalStack = m_evalStack;
325333
m_inlineFrame->m_frame.m_evalPos = pThis;
334+
m_inlineFrame->m_frame.m_localAllocCount = m_localAllocCount;
335+
for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++)
336+
{
337+
m_inlineFrame->m_frame.m_localAllocs[i] = m_localAllocs[i];
338+
}
326339

327340
// increment the evalPos pointer so that we don't corrupt the real stack
328341
evalPos++;
@@ -338,6 +351,13 @@ bool CLR_RT_StackFrame::PushInline(
338351
m_IPstart = ip;
339352
m_IP = ip;
340353

354+
// initialize localloc for the inline frame
355+
m_localAllocCount = 0;
356+
for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++)
357+
{
358+
m_localAllocs[i] = nullptr;
359+
}
360+
341361
if (md->localsCount)
342362
{
343363
g_CLR_RT_ExecutionEngine.InitializeLocals(m_locals, calleeInst);
@@ -412,6 +432,11 @@ void CLR_RT_StackFrame::RestoreFromInlineStack()
412432
m_IPstart = m_inlineFrame->m_frame.m_IPStart;
413433
m_evalStack = m_inlineFrame->m_frame.m_evalStack;
414434
m_evalStackPos = m_inlineFrame->m_frame.m_evalPos;
435+
m_localAllocCount = m_inlineFrame->m_frame.m_localAllocCount;
436+
for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++)
437+
{
438+
m_localAllocs[i] = m_inlineFrame->m_frame.m_localAllocs[i];
439+
}
415440
}
416441

417442
void CLR_RT_StackFrame::RestoreStack(CLR_RT_InlineFrame &frame)
@@ -424,6 +449,11 @@ void CLR_RT_StackFrame::RestoreStack(CLR_RT_InlineFrame &frame)
424449
m_evalStack = frame.m_evalStack;
425450
m_evalStackPos = frame.m_evalPos;
426451
m_evalStackEnd -= m_call.target->localsCount;
452+
m_localAllocCount = frame.m_localAllocCount;
453+
for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++)
454+
{
455+
m_localAllocs[i] = frame.m_localAllocs[i];
456+
}
427457
}
428458

429459
void CLR_RT_StackFrame::SaveStack(CLR_RT_InlineFrame &frame)
@@ -435,6 +465,11 @@ void CLR_RT_StackFrame::SaveStack(CLR_RT_InlineFrame &frame)
435465
frame.m_IPStart = m_IPstart;
436466
frame.m_evalPos = m_evalStackPos;
437467
frame.m_evalStack = m_evalStack;
468+
frame.m_localAllocCount = m_localAllocCount;
469+
for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++)
470+
{
471+
frame.m_localAllocs[i] = m_localAllocs[i];
472+
}
438473
}
439474
#endif
440475

@@ -822,6 +857,13 @@ void CLR_RT_StackFrame::Pop()
822857
{
823858
NATIVE_PROFILE_CLR_CORE();
824859

860+
// Clear localloc references before popping
861+
m_localAllocCount = 0;
862+
for (CLR_INT32 i = 0; i < c_Max_Localloc_Count; i++)
863+
{
864+
m_localAllocs[i] = nullptr;
865+
}
866+
825867
#if defined(NANOCLR_PROFILE_NEW_CALLS)
826868
{
827869
//

src/CLR/Core/Interpreter.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4204,6 +4204,41 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
42044204

42054205
//----------------------------------------------------------------------------------------------------------//
42064206

4207+
OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT)
4208+
{
4209+
CLR_UINT32 size = evalPos[0].NumericByRef().u4;
4210+
4211+
evalPos--;
4212+
CHECKSTACK(stack, evalPos);
4213+
4214+
// Create the byte array
4215+
CLR_RT_HeapBlock tempArray;
4216+
CLR_RT_TypeDef_Index byteType = g_CLR_RT_WellKnownTypes.UInt8;
4217+
4218+
NANOCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(tempArray, size, byteType));
4219+
4220+
CLR_RT_ProtectFromGC gc(tempArray);
4221+
CLR_RT_HeapBlock_Array *array = tempArray.DereferenceArray();
4222+
4223+
// store pointer for allocated array, if enough room
4224+
// In localloc:
4225+
if (stack->m_localAllocCount >= CLR_RT_StackFrame::c_Max_Localloc_Count)
4226+
{
4227+
NANOCLR_SET_AND_LEAVE(CLR_E_STACK_OVERFLOW);
4228+
}
4229+
4230+
stack->m_localAllocs[stack->m_localAllocCount++] = array;
4231+
4232+
evalPos++;
4233+
CHECKSTACK(stack, evalPos);
4234+
4235+
// deviating from ECMA-335: we return the array reference instead of a raw pointer
4236+
evalPos[0].SetObjectReference(array);
4237+
break;
4238+
}
4239+
4240+
//----------------------------------------------------------------------------------------------------------//
4241+
42074242
//////////////////////////////////////////////////////////////////////////////////////////
42084243
//
42094244
// These opcodes do nothing...
@@ -4224,7 +4259,6 @@ HRESULT CLR_RT_Thread::Execute_IL(CLR_RT_StackFrame &stackArg)
42244259
OPDEF(CEE_INITBLK, "initblk", PopI + PopI + PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT)
42254260
OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL)
42264261
OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT)
4227-
OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT)
42284262
OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT)
42294263
OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT)
42304264
OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT)

src/CLR/Include/nanoCLR_Runtime.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,9 @@ struct CLR_RT_HeapCluster : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELO
25292529

25302530
//--//
25312531

2532+
// maximum number of local allocations per stack frame
2533+
#define MAX_LOCALALLOC_COUNT 4
2534+
25322535
#ifndef NANOCLR_NO_IL_INLINE
25332536
struct CLR_RT_InlineFrame
25342537
{
@@ -2539,6 +2542,8 @@ struct CLR_RT_InlineFrame
25392542
CLR_RT_MethodDef_Instance m_call;
25402543
CLR_PMETADATA m_IP;
25412544
CLR_PMETADATA m_IPStart;
2545+
CLR_UINT8 m_localAllocCount;
2546+
CLR_RT_HeapBlock_Array *m_localAllocs[MAX_LOCALALLOC_COUNT];
25422547
};
25432548

25442549
struct CLR_RT_InlineBuffer
@@ -2562,6 +2567,9 @@ struct CLR_RT_StackFrame : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOC
25622567
static const int c_OverheadForNewObjOrInteropMethod = 2;
25632568
static const int c_MinimumStack = 10;
25642569

2570+
// max mumber of local allocations per stack frame
2571+
static const int c_Max_Localloc_Count = MAX_LOCALALLOC_COUNT;
2572+
25652573
static const CLR_UINT32 c_MethodKind_Native = 0x00000000;
25662574
static const CLR_UINT32 c_MethodKind_Interpreted = 0x00000001;
25672575
static const CLR_UINT32 c_UNUSED_00000002 = 0x00000002; // c_MethodKind_Jitted
@@ -2663,6 +2671,9 @@ struct CLR_RT_StackFrame : public CLR_RT_HeapBlock_Node // EVENT HEAP - NO RELOC
26632671
bool m_fNativeProfiled;
26642672
#endif
26652673

2674+
CLR_UINT8 m_localAllocCount;
2675+
CLR_RT_HeapBlock_Array *m_localAllocs[c_Max_Localloc_Count];
2676+
26662677
CLR_RT_HeapBlock m_extension[1];
26672678

26682679
////////////////////////////////////////

0 commit comments

Comments
 (0)