Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
dotNET Platform
runtime
提交
3aec142e
R
runtime
项目概览
dotNET Platform
/
runtime
大约 1 年 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
runtime
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
3aec142e
编写于
8月 11, 2023
作者:
E
Egor Bogatov
提交者:
GitHub
8月 11, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make getStaticFieldContent less conservative for struct with gc fields (#90162)
Co-authored-by:
N
Jan Kotas
<
jkotas@microsoft.com
>
上级
bbe40f8c
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
81 addition
and
62 deletion
+81
-62
src/coreclr/vm/jitinterface.cpp
src/coreclr/vm/jitinterface.cpp
+79
-62
src/coreclr/vm/jitinterface.h
src/coreclr/vm/jitinterface.h
+2
-0
未找到文件。
src/coreclr/vm/jitinterface.cpp
浏览文件 @
3aec142e
...
@@ -2483,6 +2483,8 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs)
...
@@ -2483,6 +2483,8 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs)
unsigned
CEEInfo
::
getClassGClayoutStatic
(
TypeHandle
VMClsHnd
,
BYTE
*
gcPtrs
)
unsigned
CEEInfo
::
getClassGClayoutStatic
(
TypeHandle
VMClsHnd
,
BYTE
*
gcPtrs
)
{
{
STANDARD_VM_CONTRACT
;
unsigned
result
=
0
;
unsigned
result
=
0
;
MethodTable
*
pMT
=
VMClsHnd
.
GetMethodTable
();
MethodTable
*
pMT
=
VMClsHnd
.
GetMethodTable
();
...
@@ -11587,6 +11589,30 @@ InfoAccessType CEEJitInfo::emptyStringLiteral(void ** ppValue)
...
@@ -11587,6 +11589,30 @@ InfoAccessType CEEJitInfo::emptyStringLiteral(void ** ppValue)
return
result
;
return
result
;
}
}
bool
CEEInfo
::
getStaticObjRefContent
(
OBJECTREF
obj
,
uint8_t
*
buffer
,
bool
ignoreMovableObjects
)
{
CONTRACTL
{
THROWS
;
GC_TRIGGERS
;
MODE_COOPERATIVE
;
}
CONTRACTL_END
;
if
(
obj
==
NULL
)
{
// GC handle is null
memset
(
buffer
,
0
,
sizeof
(
CORINFO_OBJECT_HANDLE
));
return
true
;
}
else
if
(
!
ignoreMovableObjects
||
GCHeapUtilities
::
GetGCHeap
()
->
IsInFrozenSegment
(
OBJECTREFToObject
(
obj
)))
{
CORINFO_OBJECT_HANDLE
handle
=
getJitHandleForObject
(
obj
);
memcpy
(
buffer
,
&
handle
,
sizeof
(
CORINFO_OBJECT_HANDLE
));
return
true
;
}
return
false
;
}
bool
CEEInfo
::
getStaticFieldContent
(
CORINFO_FIELD_HANDLE
fieldHnd
,
uint8_t
*
buffer
,
int
bufferSize
,
int
valueOffset
,
bool
ignoreMovableObjects
)
bool
CEEInfo
::
getStaticFieldContent
(
CORINFO_FIELD_HANDLE
fieldHnd
,
uint8_t
*
buffer
,
int
bufferSize
,
int
valueOffset
,
bool
ignoreMovableObjects
)
{
{
CONTRACTL
{
CONTRACTL
{
...
@@ -11618,103 +11644,94 @@ bool CEEInfo::getStaticFieldContent(CORINFO_FIELD_HANDLE fieldHnd, uint8_t* buff
...
@@ -11618,103 +11644,94 @@ bool CEEInfo::getStaticFieldContent(CORINFO_FIELD_HANDLE fieldHnd, uint8_t* buff
if
(
!
field
->
IsThreadStatic
()
&&
pEnclosingMT
->
IsClassInited
()
&&
IsFdInitOnly
(
field
->
GetAttributes
()))
if
(
!
field
->
IsThreadStatic
()
&&
pEnclosingMT
->
IsClassInited
()
&&
IsFdInitOnly
(
field
->
GetAttributes
()))
{
{
GCX_COOP
();
if
(
field
->
IsObjRef
())
if
(
field
->
IsObjRef
())
{
{
GCX_COOP
();
_ASSERT
(
!
field
->
IsRVA
());
_ASSERT
(
!
field
->
IsRVA
());
_ASSERT
(
valueOffset
==
0
);
// there is no point in returning a chunk of a gc handle
_ASSERT
(
valueOffset
==
0
);
// there is no point in returning a chunk of a gc handle
_ASSERT
((
UINT
)
bufferSize
==
field
->
GetSize
());
_ASSERT
((
UINT
)
bufferSize
==
field
->
GetSize
());
OBJECTREF
fieldObj
=
field
->
GetStaticOBJECTREF
();
result
=
getStaticObjRefContent
(
field
->
GetStaticOBJECTREF
(),
buffer
,
ignoreMovableObjects
);
if
(
fieldObj
!=
NULL
)
{
Object
*
obj
=
OBJECTREFToObject
(
fieldObj
);
CORINFO_OBJECT_HANDLE
handle
;
if
(
ignoreMovableObjects
)
{
if
(
GCHeapUtilities
::
GetGCHeap
()
->
IsInFrozenSegment
(
obj
))
{
handle
=
getJitHandleForObject
(
fieldObj
,
true
);
memcpy
(
buffer
,
&
handle
,
sizeof
(
CORINFO_OBJECT_HANDLE
));
result
=
true
;
}
}
else
{
handle
=
getJitHandleForObject
(
fieldObj
);
memcpy
(
buffer
,
&
handle
,
sizeof
(
CORINFO_OBJECT_HANDLE
));
result
=
true
;
}
}
else
{
memset
(
buffer
,
0
,
sizeof
(
intptr_t
));
result
=
true
;
}
}
}
else
else
{
{
// Either RVA, primitive or struct (or even part of that struct)
size_t
baseAddr
=
(
size_t
)
field
->
GetCurrentStaticAddress
();
UINT
size
=
field
->
GetSize
();
UINT
size
=
field
->
GetSize
();
_ASSERTE
(
baseAddr
>
0
);
_ASSERTE
(
size
>
0
);
_ASSERTE
(
size
>
0
);
if
(
size
>=
(
UINT
)
bufferSize
&&
valueOffset
>=
0
&&
(
UINT
)
valueOffset
<=
size
-
(
UINT
)
bufferSize
)
if
(
size
>=
(
UINT
)
bufferSize
&&
valueOffset
>=
0
&&
(
UINT
)
valueOffset
<=
size
-
(
UINT
)
bufferSize
)
{
{
bool
useMemcpy
=
false
;
// For structs containing GC pointers we want to make sure those GC pointers belong to FOH
// For structs containing GC pointers we want to make sure those GC pointers belong to FOH
// so we expect valueOffset to be a real field offset (same for bufferSize)
// so we expect valueOffset to be a real field offset (same for bufferSize)
if
(
!
field
->
IsRVA
()
&&
field
->
GetFieldType
()
==
ELEMENT_TYPE_VALUETYPE
)
if
(
!
field
->
IsRVA
()
&&
field
->
GetFieldType
()
==
ELEMENT_TYPE_VALUETYPE
)
{
{
PTR_MethodTable
structType
=
field
->
GetFieldTypeHandleThrowing
().
AsMethodTable
();
TypeHandle
structType
=
field
->
GetFieldTypeHandleThrowing
();
if
(
structType
->
ContainsPointers
()
&&
(
UINT
)
bufferSize
==
sizeof
(
CORINFO_OBJECT_HANDLE
))
PTR_MethodTable
structTypeMT
=
structType
.
AsMethodTable
();
if
(
!
structTypeMT
->
ContainsPointers
())
{
{
ApproxFieldDescIterator
fieldIterator
(
structType
,
ApproxFieldDescIterator
::
INSTANCE_FIELDS
);
// Fast-path: no GC pointers in the struct, we can use memcpy
for
(
FieldDesc
*
subField
=
fieldIterator
.
Next
();
subField
!=
NULL
;
subField
=
fieldIterator
.
Next
())
useMemcpy
=
true
;
}
else
{
// The struct contains GC pointer(s), but we still can use memcpy if we don't intersect with them.
unsigned
numSlots
=
(
structType
.
GetSize
()
+
TARGET_POINTER_SIZE
-
1
)
/
TARGET_POINTER_SIZE
;
CQuickBytes
gcPtrs
;
BYTE
*
ptr
=
static_cast
<
BYTE
*>
(
gcPtrs
.
AllocThrows
(
numSlots
));
CEEInfo
::
getClassGClayoutStatic
(
structType
,
ptr
);
_ASSERT
(
numSlots
>
0
);
useMemcpy
=
true
;
for
(
unsigned
i
=
0
;
i
<
numSlots
;
i
++
)
{
{
// TODO: If subField is also a struct we might want to inspect its fields too
if
(
ptr
[
i
]
==
TYPE_GC_NONE
)
if
(
subField
->
GetOffset
()
==
(
DWORD
)
valueOffset
&&
subField
->
IsObjRef
())
{
{
GCX_COOP
();
// Not a GC slot
continue
;
}
// Read field's value
const
unsigned
gcSlotBegin
=
i
*
TARGET_POINTER_SIZE
;
Object
*
subFieldValue
=
nullptr
;
const
unsigned
gcSlotEnd
=
gcSlotBegin
+
TARGET_POINTER_SIZE
;
memcpy
(
&
subFieldValue
,
(
uint8_t
*
)
baseAddr
+
valueOffset
,
bufferSize
);
if
(
subFieldValue
==
nullptr
)
if
(
gcSlotBegin
>=
(
unsigned
)
valueOffset
&&
gcSlotEnd
<=
(
unsigned
)(
valueOffset
+
bufferSize
)
)
{
{
// Report null
// GC slot intersects with our valueOffset + bufferSize - we can't use memcpy...
memset
(
buffer
,
0
,
bufferSize
)
;
useMemcpy
=
false
;
result
=
true
;
}
// ...unless we're interested in that GC slot's value itself
else
if
(
GCHeapUtilities
::
GetGCHeap
()
->
IsInFrozenSegment
(
subFieldValue
)
)
if
(
gcSlotBegin
==
(
unsigned
)
valueOffset
&&
gcSlotEnd
==
(
unsigned
)(
valueOffset
+
bufferSize
)
&&
ptr
[
i
]
==
TYPE_GC_REF
)
{
{
CORINFO_OBJECT_HANDLE
handle
=
getJitHandleForObject
(
GCX_COOP
();
ObjectToOBJECTREF
(
subFieldValue
),
/*knownFrozen*/
true
);
size_t
baseAddr
=
(
size_t
)
field
->
GetCurrentStaticAddress
();
// GC handle is either from FOH or null
_ASSERT
((
UINT
)
bufferSize
==
sizeof
(
CORINFO_OBJECT_HANDLE
));
memcpy
(
buffer
,
&
handle
,
bufferSize
);
result
=
getStaticObjRefContent
(
ObjectToOBJECTREF
(
*
(
Object
**
)((
uint8_t
*
)
baseAddr
+
gcSlotBegin
)),
buffer
,
ignoreMovableObjects
);
result
=
true
;
}
}
// We
're done with this struct
// We
had an intersection with a gc slot - no point in looking futher.
break
;
break
;
}
}
}
}
}
}
else
if
(
!
structType
->
ContainsPointers
())
{
// No gc pointers in the struct
memcpy
(
buffer
,
(
uint8_t
*
)
baseAddr
+
valueOffset
,
bufferSize
);
result
=
true
;
}
}
}
else
else
{
{
// Primitive or RVA
// RVA data, no gc pointers
memcpy
(
buffer
,
(
uint8_t
*
)
baseAddr
+
valueOffset
,
bufferSize
);
useMemcpy
=
true
;
}
if
(
useMemcpy
)
{
_ASSERT
(
!
result
);
result
=
true
;
result
=
true
;
GCX_COOP
();
size_t
baseAddr
=
(
size_t
)
field
->
GetCurrentStaticAddress
();
_ASSERT
(
baseAddr
!=
0
);
memcpy
(
buffer
,
(
uint8_t
*
)
baseAddr
+
valueOffset
,
bufferSize
);
}
}
}
}
}
}
...
...
src/coreclr/vm/jitinterface.h
浏览文件 @
3aec142e
...
@@ -465,6 +465,8 @@ public:
...
@@ -465,6 +465,8 @@ public:
CORINFO_GET_TAILCALL_HELPERS_FLAGS
flags
,
CORINFO_GET_TAILCALL_HELPERS_FLAGS
flags
,
CORINFO_TAILCALL_HELPERS
*
pResult
);
CORINFO_TAILCALL_HELPERS
*
pResult
);
bool
getStaticObjRefContent
(
OBJECTREF
obj
,
uint8_t
*
buffer
,
bool
ignoreMovableObjects
);
// This normalizes EE type information into the form expected by the JIT.
// This normalizes EE type information into the form expected by the JIT.
//
//
// If typeHnd contains exact type information, then *clsRet will contain
// If typeHnd contains exact type information, then *clsRet will contain
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录