@@ -1405,9 +1405,38 @@ CallStubHeader *CallStubGenerator::GenerateCallStubForSig(MetaSig &sig)
14051405 }
14061406};
14071407
1408- void CallStubGenerator::ComputeCallStub (MetaSig &sig, PCODE *pRoutines)
1408+ enum class RoutineType
1409+ {
1410+ None,
1411+ GPReg,
1412+ FPReg,
1413+ Stack
1414+ };
1415+
1416+ void CallStubGenerator::TerminateCurrentRoutineIfNotOfNewType (RoutineType type, PCODE *pRoutines)
14091417{
1418+ if ((m_r1 != NoRange) && (type != RoutineType::GPReg))
1419+ {
1420+ pRoutines[m_routineIndex++] = GetGPRegRangeRoutine (m_r1, m_r2);
1421+ m_r1 = NoRange;
1422+ }
1423+ else if (m_x1 != NoRange && type != RoutineType::FPReg)
1424+ {
1425+ pRoutines[m_routineIndex++] = GetFPRegRangeRoutine (m_x1, m_x2);
1426+ m_x1 = NoRange;
1427+ }
1428+ else if (m_s1 != NoRange && type != RoutineType::Stack)
1429+ {
1430+ pRoutines[m_routineIndex++] = GetStackRoutine ();
1431+ pRoutines[m_routineIndex++] = ((int64_t )(m_s2 - m_s1 + 1 ) << 32 ) | m_s1;
1432+ m_s1 = NoRange;
1433+ }
14101434
1435+ return ;
1436+ }
1437+
1438+ void CallStubGenerator::ComputeCallStub (MetaSig &sig, PCODE *pRoutines)
1439+ {
14111440 ArgIterator argIt (&sig);
14121441 int32_t interpreterStackOffset = 0 ;
14131442
@@ -1462,7 +1491,7 @@ void CallStubGenerator::ComputeCallStub(MetaSig &sig, PCODE *pRoutines)
14621491
14631492 // Each entry on the interpreter stack is always aligned to at least 8 bytes, but some arguments are 16 byte aligned
14641493 TypeHandle thArgTypeHandle;
1465- if (argIt.GetArgType (&thArgTypeHandle) == ELEMENT_TYPE_VALUETYPE)
1494+ if (( argIt.GetArgType (&thArgTypeHandle) == ELEMENT_TYPE_VALUETYPE) && thArgTypeHandle. GetSize () > 8 )
14661495 {
14671496 unsigned align = CEEInfo::getClassAlignmentRequirementStatic (thArgTypeHandle);
14681497 if (align < INTERP_STACK_SLOT_SIZE)
@@ -1474,24 +1503,9 @@ void CallStubGenerator::ComputeCallStub(MetaSig &sig, PCODE *pRoutines)
14741503 align = INTERP_STACK_ALIGNMENT;
14751504 }
14761505 assert (align == 8 || align == 16 ); // At the moment, we can only have an 8 or 16 byte alignment requirement here
1477- while (interpreterStackOffset != ALIGN_UP (interpreterStackOffset, align))
1506+ if (interpreterStackOffset != ALIGN_UP (interpreterStackOffset, align))
14781507 {
1479- if (m_r1 != NoRange)
1480- {
1481- pRoutines[m_routineIndex++] = GetGPRegRangeRoutine (m_r1, m_r2);
1482- m_r1 = NoRange;
1483- }
1484- else if (m_x1 != NoRange)
1485- {
1486- pRoutines[m_routineIndex++] = GetFPRegRangeRoutine (m_x1, m_x2);
1487- m_x1 = NoRange;
1488- }
1489- else if (m_s1 != NoRange)
1490- {
1491- pRoutines[m_routineIndex++] = GetStackRoutine ();
1492- pRoutines[m_routineIndex++] = ((int64_t )(m_s2 - m_s1 + 1 ) << 32 ) | m_s1;
1493- m_s1 = NoRange;
1494- }
1508+ TerminateCurrentRoutineIfNotOfNewType (RoutineType::None, pRoutines);
14951509
14961510 interpreterStackOffset += INTERP_STACK_SLOT_SIZE;
14971511 pRoutines[m_routineIndex++] = (PCODE)InjectInterpStackAlign;
@@ -1500,6 +1514,8 @@ void CallStubGenerator::ComputeCallStub(MetaSig &sig, PCODE *pRoutines)
15001514#endif
15011515 }
15021516
1517+ assert (interpreterStackOffset == ALIGN_UP (interpreterStackOffset, align));
1518+
15031519 interpStackSlotSize = ALIGN_UP (thArgTypeHandle.GetSize (), align);
15041520 }
15051521 interpreterStackOffset += interpStackSlotSize;
@@ -1568,19 +1584,7 @@ void CallStubGenerator::ComputeCallStub(MetaSig &sig, PCODE *pRoutines)
15681584
15691585 // All arguments were processed, but there is likely a pending ranges to store.
15701586 // Process such a range if any.
1571- if (m_r1 != NoRange)
1572- {
1573- pRoutines[m_routineIndex++] = GetGPRegRangeRoutine (m_r1, m_r2);
1574- }
1575- else if (m_x1 != NoRange)
1576- {
1577- pRoutines[m_routineIndex++] = GetFPRegRangeRoutine (m_x1, m_x2);
1578- }
1579- else if (m_s1 != NoRange)
1580- {
1581- pRoutines[m_routineIndex++] = GetStackRoutine ();
1582- pRoutines[m_routineIndex++] = ((int64_t )(m_s2 - m_s1 + 1 ) << 32 ) | m_s1;
1583- }
1587+ TerminateCurrentRoutineIfNotOfNewType (RoutineType::None, pRoutines);
15841588
15851589 ReturnType returnType = GetReturnType (&argIt);
15861590
@@ -1601,30 +1605,15 @@ void CallStubGenerator::ProcessArgument(ArgIterator *pArgIt, ArgLocDesc& argLocD
16011605{
16021606 LIMITED_METHOD_CONTRACT;
16031607
1604- // Check if we have a range of registers or stack arguments that we need to store because the current argument
1605- // terminates it.
1606- if ((argLocDesc.m_cGenReg == 0 ) && (m_r1 != NoRange))
1607- {
1608- // No GP register is used to pass the current argument, but we already have a range of GP registers,
1609- // store the routine for the range
1610- pRoutines[m_routineIndex++] = GetGPRegRangeRoutine (m_r1, m_r2);
1611- m_r1 = NoRange;
1612- }
1613- else if (((argLocDesc.m_cFloatReg == 0 )) && (m_x1 != NoRange))
1614- {
1615- // No floating point register is used to pass the current argument, but we already have a range of FP registers,
1616- // store the routine for the range
1617- pRoutines[m_routineIndex++] = GetFPRegRangeRoutine (m_x1, m_x2);
1618- m_x1 = NoRange;
1619- }
1620- else if ((argLocDesc.m_byteStackSize == 0 ) && (m_s1 != NoRange))
1621- {
1622- // No stack argument is used to pass the current argument, but we already have a range of stack arguments,
1623- // store the routine for the range
1624- pRoutines[m_routineIndex++] = GetStackRoutine ();
1625- pRoutines[m_routineIndex++] = ((int64_t )(m_s2 - m_s1 + 1 ) << 32 ) | m_s1;
1626- m_s1 = NoRange;
1627- }
1608+ RoutineType argType = RoutineType::None;
1609+ if (argLocDesc.m_cGenReg != 0 )
1610+ argType = RoutineType::GPReg;
1611+ else if (argLocDesc.m_cFloatReg != 0 )
1612+ argType = RoutineType::FPReg;
1613+ else if (argLocDesc.m_byteStackSize != 0 )
1614+ argType = RoutineType::Stack;
1615+
1616+ TerminateCurrentRoutineIfNotOfNewType (argType, pRoutines);
16281617
16291618 if (argLocDesc.m_cGenReg != 0 )
16301619 {
0 commit comments