private static bool FindFirstPassHandler(object exception, uint idxStart, ref StackFrameIterator frameIter, out uint tryRegionIdx, out byte *pHandler) { pHandler = null; tryRegionIdx = MaxTryRegionIdx; EHEnum ehEnum; byte * pbMethodStartAddress; if (!InternalCalls.RhpEHEnumInitFromStackFrameIterator(ref frameIter, &pbMethodStartAddress, &ehEnum)) { return(false); } byte *pbControlPC = frameIter.ControlPC; uint codeOffset = (uint)(pbControlPC - pbMethodStartAddress); uint lastTryStart = 0, lastTryEnd = 0; // Search the clauses for one that contains the current offset. RhEHClause ehClause; for (uint curIdx = 0; InternalCalls.RhpEHEnumNext(&ehEnum, &ehClause); curIdx++) { // // Skip to the starting try region. This is used by collided unwinds and rethrows to pickup where // the previous dispatch left off. // if (idxStart != MaxTryRegionIdx) { if (curIdx <= idxStart) { lastTryStart = ehClause._tryStartOffset; lastTryEnd = ehClause._tryEndOffset; continue; } // Now, we continue skipping while the try region is identical to the one that invoked the // previous dispatch. if ((ehClause._tryStartOffset == lastTryStart) && (ehClause._tryEndOffset == lastTryEnd)) { continue; } } RhEHClauseKind clauseKind = ehClause._clauseKind; if (((clauseKind != RhEHClauseKind.RH_EH_CLAUSE_TYPED) && (clauseKind != RhEHClauseKind.RH_EH_CLAUSE_FILTER)) || !ehClause.ContainsCodeOffset(codeOffset)) { continue; } // Found a containing clause. Because of the order of the clauses, we know this is the // most containing. if (clauseKind == RhEHClauseKind.RH_EH_CLAUSE_TYPED) { if (ShouldTypedClauseCatchThisException(exception, (EEType *)ehClause._pTargetType)) { pHandler = ehClause._handlerAddress; tryRegionIdx = curIdx; return(true); } } else { byte *pFilterFunclet = ehClause._filterAddress; bool shouldInvokeHandler = InternalCalls.RhpCallFilterFunclet(exception, pFilterFunclet, frameIter.RegisterSet); if (shouldInvokeHandler) { pHandler = ehClause._handlerAddress; tryRegionIdx = curIdx; return(true); } } } return(false); }
// TODO: temporary to try things out, when working look to see how to refactor with FindFirstPassHandler private static bool FindFirstPassHandlerWasm(object exception, uint idxStart, uint idxTryLandingStart /* the start IL idx of the try region for the landing pad, will use in place of PC */, void *shadowStack, void *exInfo, ref EHClauseIterator clauseIter, out uint tryRegionIdx, out byte *pHandler) { pHandler = (byte *)0; tryRegionIdx = MaxTryRegionIdx; uint lastTryStart = 0, lastTryEnd = 0; RhEHClauseWasm ehClause = new RhEHClauseWasm(); for (uint curIdx = 0; clauseIter.Next(ref ehClause); curIdx++) { // // Skip to the starting try region. This is used by collided unwinds and rethrows to pickup where // the previous dispatch left off. // if (idxStart != MaxTryRegionIdx) { if (curIdx <= idxStart) { lastTryStart = ehClause._tryStartOffset; lastTryEnd = ehClause._tryEndOffset; continue; } // Now, we continue skipping while the try region is identical to the one that invoked the // previous dispatch. if ((ehClause._tryStartOffset == lastTryStart) && (ehClause._tryEndOffset == lastTryEnd)) { continue; } // We are done skipping. This is required to handle empty finally block markers that are used // to separate runs of different try blocks with same native code offsets. idxStart = MaxTryRegionIdx; } EHClauseIterator.RhEHClauseKindWasm clauseKind = ehClause._clauseKind; if (((clauseKind != EHClauseIterator.RhEHClauseKindWasm.RH_EH_CLAUSE_TYPED) && (clauseKind != EHClauseIterator.RhEHClauseKindWasm.RH_EH_CLAUSE_FILTER)) || !ehClause.TryStartsAt(idxTryLandingStart)) { continue; } // Found a containing clause. Because of the order of the clauses, we know this is the // most containing. if (clauseKind == EHClauseIterator.RhEHClauseKindWasm.RH_EH_CLAUSE_TYPED) { if (ShouldTypedClauseCatchThisException(exception, (EEType *)ehClause._typeSymbol)) { pHandler = ehClause._handlerAddress; tryRegionIdx = curIdx; return(true); } } else { tryRegionIdx = 0; bool shouldInvokeHandler = InternalCalls.RhpCallFilterFunclet(exception, ehClause._filterAddress, shadowStack); if (shouldInvokeHandler) { pHandler = ehClause._handlerAddress; tryRegionIdx = curIdx; return(true); } } } return(false); }