Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / objectalloc.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                         ObjectAllocator                                   XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #ifdef _MSC_VER
16 #pragma hdrstop
17 #endif
18
19 //===============================================================================
20
21 //------------------------------------------------------------------------
22 // DoPhase: Run analysis (if object stack allocation is enabled) and then
23 //          morph each GT_ALLOCOBJ node either into an allocation helper
24 //          call or stack allocation.
25 // Notes:
26 //    Runs only if Compiler::optMethodFlags has flag OMF_HAS_NEWOBJ set.
27 void ObjectAllocator::DoPhase()
28 {
29     if ((comp->optMethodFlags & OMF_HAS_NEWOBJ) == 0)
30     {
31         return;
32     }
33
34     if (IsObjectStackAllocationEnabled())
35     {
36         DoAnalysis();
37     }
38
39     MorphAllocObjNodes();
40 }
41
42 //------------------------------------------------------------------------
43 // DoAnalysis: Walk over basic blocks of the method and detect all local
44 //             variables that can be allocated on the stack.
45 //
46 // Assumptions:
47 //    Must be run after the dominators have been computed (we need this
48 //    information to detect loops).
49 void ObjectAllocator::DoAnalysis()
50 {
51     assert(m_IsObjectStackAllocationEnabled);
52     assert(comp->fgDomsComputed);
53     // TODO-ObjectStackAllocation
54     NYI("DoAnalysis");
55 }
56
57 //------------------------------------------------------------------------
58 // MorphAllocObjNodes: Morph each GT_ALLOCOBJ node either into an
59 //                     allocation helper call or stack allocation.
60 //
61 // Notes:
62 //    Runs only over the blocks having bbFlags BBF_HAS_NEWOBJ set.
63 void ObjectAllocator::MorphAllocObjNodes()
64 {
65     BasicBlock* block;
66
67     foreach_block(comp, block)
68     {
69         const bool basicBlockHasNewObj = (block->bbFlags & BBF_HAS_NEWOBJ) == BBF_HAS_NEWOBJ;
70 #ifndef DEBUG
71         if (!basicBlockHasNewObj)
72         {
73             continue;
74         }
75 #endif // DEBUG
76
77         for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
78         {
79             GenTree* stmtExpr = stmt->gtStmtExpr;
80             GenTree* op2      = nullptr;
81
82             bool canonicalAllocObjFound = false;
83
84             if (stmtExpr->OperGet() == GT_ASG && stmtExpr->TypeGet() == TYP_REF)
85             {
86                 op2 = stmtExpr->gtGetOp2();
87
88                 if (op2->OperGet() == GT_ALLOCOBJ)
89                 {
90                     canonicalAllocObjFound = true;
91                 }
92             }
93
94             if (canonicalAllocObjFound)
95             {
96                 assert(basicBlockHasNewObj);
97                 //------------------------------------------------------------------------
98                 // We expect the following expression tree at this point
99                 //  *  GT_STMT   void  (top level)
100                 //      |  /--*  GT_ALLOCOBJ   ref
101                 //      \--*  GT_ASG    ref
102                 //         \--*  GT_LCL_VAR    ref
103                 //------------------------------------------------------------------------
104
105                 GenTree* op1 = stmtExpr->gtGetOp1();
106
107                 assert(op1->OperGet() == GT_LCL_VAR);
108                 assert(op1->TypeGet() == TYP_REF);
109                 assert(op2 != nullptr);
110                 assert(op2->OperGet() == GT_ALLOCOBJ);
111
112                 GenTreeAllocObj* asAllocObj = op2->AsAllocObj();
113                 unsigned int     lclNum     = op1->AsLclVar()->GetLclNum();
114
115                 if (IsObjectStackAllocationEnabled() && CanAllocateLclVarOnStack(lclNum))
116                 {
117                     op2 = MorphAllocObjNodeIntoStackAlloc(asAllocObj, block, stmt);
118                 }
119                 else
120                 {
121                     op2 = MorphAllocObjNodeIntoHelperCall(asAllocObj);
122                 }
123
124                 // Propagate flags of op2 to its parent.
125                 stmtExpr->gtOp.gtOp2 = op2;
126                 stmtExpr->gtFlags |= op2->gtFlags & GTF_ALL_EFFECT;
127             }
128 #ifdef DEBUG
129             else
130             {
131                 // We assume that GT_ALLOCOBJ nodes are always present in the
132                 // canonical form.
133                 comp->fgWalkTreePre(&stmt->gtStmtExpr, AssertWhenAllocObjFoundVisitor);
134             }
135 #endif // DEBUG
136         }
137     }
138 }
139
140 //------------------------------------------------------------------------
141 // MorphAllocObjNodeIntoHelperCall: Morph a GT_ALLOCOBJ node into an
142 //                                  allocation helper call.
143 //
144 // Arguments:
145 //    allocObj - GT_ALLOCOBJ that will be replaced by helper call.
146 //
147 // Return Value:
148 //    Address of helper call node (can be the same as allocObj).
149 //
150 // Notes:
151 //    Must update parents flags after this.
152 GenTree* ObjectAllocator::MorphAllocObjNodeIntoHelperCall(GenTreeAllocObj* allocObj)
153 {
154     assert(allocObj != nullptr);
155
156     GenTree* op1 = allocObj->gtGetOp1();
157
158     GenTree* helperCall = comp->fgMorphIntoHelperCall(allocObj, allocObj->gtNewHelper, comp->gtNewArgList(op1));
159
160     return helperCall;
161 }
162
163 //------------------------------------------------------------------------
164 // MorphAllocObjNodeIntoStackAlloc: Morph a GT_ALLOCOBJ node into stack
165 //                                  allocation.
166 // Arguments:
167 //    allocObj - GT_ALLOCOBJ that will be replaced by helper call.
168 //    block    - a basic block where allocObj is
169 //    stmt     - a statement where allocObj is
170 //
171 // Return Value:
172 //    Address of tree doing stack allocation (can be the same as allocObj).
173 //
174 // Notes:
175 //    Must update parents flags after this.
176 //    This function can insert additional statements before stmt.
177 GenTree* ObjectAllocator::MorphAllocObjNodeIntoStackAlloc(GenTreeAllocObj* allocObj,
178                                                           BasicBlock*      block,
179                                                           GenTreeStmt*     stmt)
180 {
181     assert(allocObj != nullptr);
182     assert(m_AnalysisDone);
183
184     // TODO-StackAllocation
185     NYI("MorphAllocObjIntoStackAlloc");
186
187     return allocObj;
188 }
189
190 #ifdef DEBUG
191
192 //------------------------------------------------------------------------
193 // AssertWhenAllocObjFoundVisitor: Look for a GT_ALLOCOBJ node and assert
194 //                                 when found one.
195 Compiler::fgWalkResult ObjectAllocator::AssertWhenAllocObjFoundVisitor(GenTree** pTree, Compiler::fgWalkData* data)
196 {
197     GenTree* tree = *pTree;
198
199     assert(tree != nullptr);
200     assert(tree->OperGet() != GT_ALLOCOBJ);
201
202     return Compiler::fgWalkResult::WALK_CONTINUE;
203 }
204
205 #endif // DEBUG
206
207 //===============================================================================