|
| 1 | +diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp |
| 2 | +index ad1fd83fe9..bcc818f25b 100644 |
| 3 | +--- a/src/jit/flowgraph.cpp |
| 4 | ++++ b/src/jit/flowgraph.cpp |
| 5 | +@@ -8016,45 +8016,46 @@ GenTree* Compiler::fgCreateMonitorTree(unsigned lvaMonAcquired, unsigned lvaThis |
| 6 | + { |
| 7 | + GenTree* retNode = block->lastStmt()->gtStmtExpr; |
| 8 | + GenTree* retExpr = retNode->gtOp.gtOp1; |
| 9 | + |
| 10 | + if (retExpr != nullptr) |
| 11 | + { |
| 12 | + // have to insert this immediately before the GT_RETURN so we transform: |
| 13 | + // ret(...) -> |
| 14 | + // ret(comma(comma(tmp=...,call mon_exit), tmp) |
| 15 | + // |
| 16 | + // |
| 17 | + // Before morph stage, it is possible to have a case of GT_RETURN(TYP_LONG, op1) where op1's type is |
| 18 | + // TYP_STRUCT (of 8-bytes) and op1 is call node. See the big comment block in impReturnInstruction() |
| 19 | + // for details for the case where info.compRetType is not the same as info.compRetNativeType. For |
| 20 | + // this reason pass compMethodInfo->args.retTypeClass which is guaranteed to be a valid class handle |
| 21 | + // if the return type is a value class. Note that fgInsertCommFormTemp() in turn uses this class handle |
| 22 | + // if the type of op1 is TYP_STRUCT to perform lvaSetStruct() on the new temp that is created, which |
| 23 | + // in turn passes it to VM to know the size of value type. |
| 24 | + GenTree* temp = fgInsertCommaFormTemp(&retNode->gtOp.gtOp1, info.compMethodInfo->args.retTypeClass); |
| 25 | + |
| 26 | +- GenTree* lclVar = retNode->gtOp.gtOp1->gtOp.gtOp2; |
| 27 | ++ GenTree* lclVar = retNode->gtOp.gtOp1->gtOp.gtOp2; |
| 28 | + |
| 29 | + // The return can't handle all of the trees that could be on the right-hand-side of an assignment, |
| 30 | + // especially in the case of a struct. Therefore, we need to propagate GTF_DONT_CSE. |
| 31 | +- // If we don't, assertion propagation may, e.g., change a return of a local to a return of "CNS_INT struct 0", |
| 32 | ++ // If we don't, assertion propagation may, e.g., change a return of a local to a return of "CNS_INT struct |
| 33 | ++ // 0", |
| 34 | + // which downstream phases can't handle. |
| 35 | + lclVar->gtFlags |= (retExpr->gtFlags & GTF_DONT_CSE); |
| 36 | + retNode->gtOp.gtOp1->gtOp.gtOp2 = gtNewOperNode(GT_COMMA, retExpr->TypeGet(), tree, lclVar); |
| 37 | + } |
| 38 | + else |
| 39 | + { |
| 40 | + // Insert this immediately before the GT_RETURN |
| 41 | + fgInsertStmtNearEnd(block, tree); |
| 42 | + } |
| 43 | + } |
| 44 | + else |
| 45 | + { |
| 46 | + fgInsertStmtAtEnd(block, tree); |
| 47 | + } |
| 48 | + |
| 49 | + return tree; |
| 50 | + } |
| 51 | + |
| 52 | + // Convert a BBJ_RETURN block in a synchronized method to a BBJ_ALWAYS. |
| 53 | + // We've previously added a 'try' block around the original program code using fgAddSyncMethodEnterExit(). |
0 commit comments