GenTreeCast* gtNewCastNodeL(var_types typ, GenTree* op1, bool fromUnsigned, var_types castType);
- GenTree* gtNewAllocObjNode(unsigned int helper, CORINFO_CLASS_HANDLE clsHnd, var_types type, GenTree* op1);
+ GenTreeAllocObj* gtNewAllocObjNode(unsigned int helper, CORINFO_CLASS_HANDLE clsHnd, var_types type, GenTree* op1);
+
+ GenTreeAllocObj* gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, BOOL useParent);
GenTree* gtNewRuntimeLookup(CORINFO_GENERIC_HANDLE hnd, CorInfoGenericHandleType hndTyp, GenTree* lookupTree);
// Return Value:
// Returns GT_ALLOCOBJ node that will be later morphed into an
// allocation helper call or local variable allocation on the stack.
-inline GenTree* Compiler::gtNewAllocObjNode(unsigned int helper,
- CORINFO_CLASS_HANDLE clsHnd,
- var_types type,
- GenTree* op1)
+
+inline GenTreeAllocObj* Compiler::gtNewAllocObjNode(unsigned int helper,
+ CORINFO_CLASS_HANDLE clsHnd,
+ var_types type,
+ GenTree* op1)
{
- GenTree* node = new (this, GT_ALLOCOBJ) GenTreeAllocObj(type, helper, clsHnd, op1);
+ GenTreeAllocObj* node = new (this, GT_ALLOCOBJ) GenTreeAllocObj(type, helper, clsHnd, op1);
return node;
}
//
// Return Value:
// New GenTreeRuntimeLookup node.
+
inline GenTree* Compiler::gtNewRuntimeLookup(CORINFO_GENERIC_HANDLE hnd, CorInfoGenericHandleType hndTyp, GenTree* tree)
{
assert(tree != nullptr);
return node;
}
+//------------------------------------------------------------------------
+// gtNewAllocObjNode: Helper to create an object allocation node.
+//
+// Arguments:
+// pResolvedToken - Resolved token for the object being allocated
+// useParent - true iff the token represents a child of the object's class
+//
+// Return Value:
+// Returns GT_ALLOCOBJ node that will be later morphed into an
+// allocation helper call or local variable allocation on the stack.
+
+GenTreeAllocObj* Compiler::gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedToken, BOOL useParent)
+{
+ const BOOL mustRestoreHandle = TRUE;
+ BOOL* const pRuntimeLookup = nullptr;
+ bool usingReadyToRunHelper = false;
+ CorInfoHelpFunc helper;
+ GenTree* opHandle = impTokenToHandle(pResolvedToken, pRuntimeLookup, mustRestoreHandle, useParent);
+
+#ifdef FEATURE_READYTORUN_COMPILER
+ CORINFO_CONST_LOOKUP lookup;
+
+ if (opts.IsReadyToRun())
+ {
+ helper = CORINFO_HELP_READYTORUN_NEW;
+ CORINFO_LOOKUP_KIND* const pGenericLookupKind = nullptr;
+ usingReadyToRunHelper =
+ info.compCompHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, helper, &lookup);
+ }
+#endif
+
+ if (!usingReadyToRunHelper)
+ {
+ if (opHandle == nullptr)
+ {
+ // We must be backing out of an inline.
+ assert(compDonotInline());
+ return nullptr;
+ }
+
+ helper = info.compCompHnd->getNewHelper(pResolvedToken, info.compMethodHnd);
+ }
+
+ // TODO: ReadyToRun: When generic dictionary lookups are necessary, replace the lookup call
+ // and the newfast call with a single call to a dynamic R2R cell that will:
+ // 1) Load the context
+ // 2) Perform the generic dictionary lookup and caching, and generate the appropriate stub
+ // 3) Allocate and return the new object for boxing
+ // Reason: performance (today, we'll always use the slow helper for the R2R generics case)
+
+ GenTreeAllocObj* allocObj = gtNewAllocObjNode(helper, pResolvedToken->hClass, TYP_REF, opHandle);
+
+#ifdef FEATURE_READYTORUN_COMPILER
+ if (usingReadyToRunHelper)
+ {
+ allocObj->gtEntryPoint = lookup;
+ }
+#endif
+
+ return allocObj;
+}
+
/*****************************************************************************
*
* Clones the given tree value and returns a copy of the given tree.
{
unsigned int gtNewHelper; // Value returned by ICorJitInfo::getNewHelper
CORINFO_CLASS_HANDLE gtAllocObjClsHnd;
+#ifdef FEATURE_READYTORUN_COMPILER
+ CORINFO_CONST_LOOKUP gtEntryPoint;
+#endif
GenTreeAllocObj(var_types type, unsigned int helper, CORINFO_CLASS_HANDLE clsHnd, GenTree* op)
: GenTreeUnOp(GT_ALLOCOBJ, type, op DEBUGARG(/*largeNode*/ TRUE))
gtNewHelper(helper)
, gtAllocObjClsHnd(clsHnd)
{
+#ifdef FEATURE_READYTORUN_COMPILER
+ gtEntryPoint.addr = nullptr;
+#endif
}
#if DEBUGGABLE_GENTREE
GenTreeAllocObj() : GenTreeUnOp()
// the opcode stack becomes empty
impBoxTempInUse = true;
-#ifdef FEATURE_READYTORUN_COMPILER
- bool usingReadyToRunHelper = false;
-
- if (opts.IsReadyToRun())
- {
- op1 = impReadyToRunHelperToTree(pResolvedToken, CORINFO_HELP_READYTORUN_NEW, TYP_REF);
- usingReadyToRunHelper = (op1 != nullptr);
- }
-
- if (!usingReadyToRunHelper)
-#endif
+ const BOOL useParent = FALSE;
+ op1 = gtNewAllocObjNode(pResolvedToken, useParent);
+ if (op1 == nullptr)
{
- // TODO: ReadyToRun: When generic dictionary lookups are necessary, replace the lookup call
- // and the newfast call with a single call to a dynamic R2R cell that will:
- // 1) Load the context
- // 2) Perform the generic dictionary lookup and caching, and generate the appropriate stub
- // 3) Allocate and return the new object for boxing
- // Reason: performance (today, we'll always use the slow helper for the R2R generics case)
-
- // Ensure that the value class is restored
- op2 = impTokenToHandle(pResolvedToken, nullptr, TRUE /* mustRestoreHandle */);
- if (op2 == nullptr)
- {
- // We must be backing out of an inline.
- assert(compDonotInline());
- return;
- }
-
- op1 = gtNewAllocObjNode(info.compCompHnd->getNewHelper(pResolvedToken, info.compMethodHnd),
- pResolvedToken->hClass, TYP_REF, op2);
+ return;
}
/* Remember that this basic block contains 'new' of an object, and so does this method */
}
else
{
-#ifdef FEATURE_READYTORUN_COMPILER
- if (opts.IsReadyToRun())
- {
- op1 = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_NEW, TYP_REF);
- usingReadyToRunHelper = (op1 != nullptr);
- }
-
- if (!usingReadyToRunHelper)
-#endif
+ const BOOL useParent = TRUE;
+ op1 = gtNewAllocObjNode(&resolvedToken, useParent);
+ if (op1 == nullptr)
{
- op1 = impParentClassTokenToHandle(&resolvedToken, nullptr, TRUE);
- if (op1 == nullptr)
- { // compDonotInline()
- return;
- }
-
- // TODO: ReadyToRun: When generic dictionary lookups are necessary, replace the lookup call
- // and the newfast call with a single call to a dynamic R2R cell that will:
- // 1) Load the context
- // 2) Perform the generic dictionary lookup and caching, and generate the appropriate
- // stub
- // 3) Allocate and return the new object
- // Reason: performance (today, we'll always use the slow helper for the R2R generics case)
-
- op1 = gtNewAllocObjNode(info.compCompHnd->getNewHelper(&resolvedToken, info.compMethodHnd),
- resolvedToken.hClass, TYP_REF, op1);
+ return;
}
// Remember that this basic block contains 'new' of an object
{
assert(allocObj != nullptr);
- GenTree* op1 = allocObj->gtGetOp1();
+ GenTree* op1 = allocObj->gtGetOp1();
+ unsigned int helper = allocObj->gtNewHelper;
- const bool morphArgs = false;
- GenTree* helperCall =
- comp->fgMorphIntoHelperCall(allocObj, allocObj->gtNewHelper, comp->gtNewArgList(op1), morphArgs);
+ GenTreeArgList* args;
+#ifdef FEATURE_READYTORUN_COMPILER
+ CORINFO_CONST_LOOKUP entryPoint = allocObj->gtEntryPoint;
+ if (helper == CORINFO_HELP_READYTORUN_NEW)
+ {
+ args = nullptr;
+ }
+ else
+#endif
+ {
+ args = comp->gtNewArgList(op1);
+ }
+
+ const bool morphArgs = false;
+ GenTree* helperCall = comp->fgMorphIntoHelperCall(allocObj, allocObj->gtNewHelper, args, morphArgs);
+
+#ifdef FEATURE_READYTORUN_COMPILER
+ if (entryPoint.addr != nullptr)
+ {
+ assert(comp->opts.IsReadyToRun());
+ helperCall->gtCall.setEntryPoint(entryPoint);
+ }
+#endif
return helperCall;
}
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
<PropertyGroup>
- <CrossGenTest>false</CrossGenTest>
<CLRTestBatchPreCommands>
<![CDATA[
$(CLRTestBatchPreCommands)