[PATCH 2/2] msvcp140_1: Implement the DLL.
Piotr Caban
piotr at codeweavers.com
Fri Apr 2 11:18:28 CDT 2021
Hi Arek,
I still need to look more into first patch so you can wait with resend.
Here are some initial comments:
On 4/1/21 3:38 PM, Arkadiusz Hiler wrote:
> +#ifdef __i386__
> +#define MAX_UNALIGNED_ALIGNMENT 8
> +#else
> +#define MAX_UNALIGNED_ALIGNMENT 16
> +#endif
It probably corresponds to operator new alignment. If so it would make
more sense to define it as:
#define NEW_ALIGNMENT (2*sizeof(void*))
so it matches with new alignment on arm.
> +DEFINE_RTTI_DATA0(base_memory_resource, 0, ".?AVmemory_resource at pmr@std@@")
> +DEFINE_RTTI_DATA1(aligned_resource, 0, &base_memory_resource_rtti_base_descriptor, ".?AV_Aligned_new_delete_resource at pmr@std@@")
> +DEFINE_RTTI_DATA1(unaligned_resource, 0, &base_memory_resource_rtti_base_descriptor, ".?AV_Unligned_new_delete_resource at pmr@std@@")
> +DEFINE_RTTI_DATA1(null_resource, 0, &base_memory_resource_rtti_base_descriptor, ".?AV_null_resource at pmr@std@@")
This doesn't match with native RTTI data. If you need help with that
part please let me know
> +DEFINE_THISCALL_WRAPPER(aligned_do_allocate, 12)
> +void* __thiscall aligned_do_allocate(memory_resource *this, size_t bytes, size_t alignment)
> +{
> + return MSVCRT_operator_new_aligned(bytes, alignment);
> +}
This doesn't match the tests that are calling free (instead of
_aligned_free) in some cases.
> +DEFINE_THISCALL_WRAPPER(aligned_do_deallocate, 16)
> +void __thiscall aligned_do_deallocate(memory_resource *this, void *p, size_t bytes, size_t alignment)
> +{
> + MSVCRT_operator_delete_aligned(p, alignment);
> +}
Same here.
> +static memory_resource impl_aligned_resource = { &MSVCP_aligned_resource_vtable };
> +static memory_resource impl_unaligned_resource = { &MSVCP_unaligned_resource_vtable };
> +static memory_resource impl_null_resource = { &MSVCP_null_resource_vtable };
> +
> +memory_resource *default_unaligned_resource = &impl_unaligned_resource;
> +memory_resource *default_aligned_resource = &impl_aligned_resource;
Quick test shows that _Aligned_get_default_resource and
_Unaligned_get_default_resource returns the same data after
_Aligned_set_default_resource(0xdeadbeef) call. Probably there's only
one default_resource variable that is shared in both of the functions.
It should probably return default object when set to NULL and stored
object otherwise. I'm thinking about something like:
memory_resource* __cdecl _Aligned_new_delete_resource(void)
{
static memory_resource impl_aligned_resource = {
&MSVCP_aligned_resource_vtable };
return &impl_aligned_resource;
}
memory_resource* __cdecl _Aligned_get_default_resource(void)
{
if (default_resource) return default_resource;
return _Aligned_new_delete_resource();
}
memory_resource* __cdecl _Aligned_set_default_resource(memory_resource *res)
{
memory_resource *ret =
InterlockedExchangePointer((void**)&default_resource, res);
if (!ret) ret = _Aligned_new_delete_resource();
return ret;
}
> +static void init_cxx_funcs(void)
> +{
> + msvcp140 = LoadLibraryA("msvcp140.dll");
> + if (!msvcp140) FIXME("Failed to load msvcp140.dll\n");
> + throw_bad_alloc = (void*)GetProcAddress(msvcp140, "?_Xbad_alloc at std@@YAXXZ");
> + if (!throw_bad_alloc) FIXME("Failed to get address of ?_Xbad_alloc at std@@YAXXZ\n");
> +}
Please return error (so dll fails to load) if msvcp140 can't be loaded.
> +static void test__Aligned_new_delete_resource(void)
> +{
> + void *ptr;
> + memory_resource *resource = p__Aligned_new_delete_resource();
> + ok(resource != NULL, "Failed to get aligned new delete memory resource.\n");
> +
> + /* calling dtor should be harmless nop */
> + call_func1(resource->vtbl->dtor, resource);
Please avoid adding such tests (or add them as last test in the file).
Sometimes it changes object behavior in unexpected ways. I guess that in
this case it should work but it's better to play safe.
> + p_free(ptr); /* aligned delete, crashes with non-aligned */
Looks like the comment was copied from _aligned_free case.
> +static void test_get_set_defult_resource(memory_resource *(__cdecl *new_delete_resource)(void),
> + memory_resource *(__cdecl *get_default_resource)(void),
> + memory_resource *(__cdecl *set_default_resource)(memory_resource *resource))
> +{
> + memory_resource *new_resource = new_delete_resource();
> + memory_resource *default_resource = get_default_resource();
> + ok(default_resource == new_resource, "Expected the default memory resource to be equal new/delete one.\n");
> +
> + default_resource = set_default_resource((void*)0xdeadbeef);
> + ok(default_resource == new_resource, "Expected that setting default resource would return the old one.\n");
> +
> + default_resource = get_default_resource();
> + ok(default_resource == (void*)0xdeadbeef, "Expected that setting reasource would take effect.\n");
> +
> + default_resource = set_default_resource(NULL);
> + ok(default_resource == (void*)0xdeadbeef, "Expected that setting default resource would return the old one.\n");
> +
> + default_resource = get_default_resource();
> + ok(default_resource == new_resource, "Expected that setting default resource to NULL would reset the value.\n");
> +}
Please add a test that calls p__Unaligned_get_default_resource after
p__Aligned_set_default_resource(0xdeadbeef) call.
Thanks,
Piotr
More information about the wine-devel
mailing list