summaryrefslogtreecommitdiff
path: root/include/ruby/internal/memory.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ruby/internal/memory.h')
-rw-r--r--include/ruby/internal/memory.h13
1 files changed, 11 insertions, 2 deletions
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h
index 64e850c65e..d231e62982 100644
--- a/include/ruby/internal/memory.h
+++ b/include/ruby/internal/memory.h
@@ -38,9 +38,14 @@
# include <alloca.h>
#endif
-#if defined(_MSC_VER) && defined(_M_AMD64)
+#if defined(_MSC_VER) && defined(_WIN64)
# include <intrin.h>
+# if defined(_M_AMD64)
# pragma intrinsic(_umul128)
+# endif
+# if defined(_M_ARM64)
+# pragma intrinsic(__umulh)
+# endif
#endif
#include "ruby/internal/attr/alloc_size.h"
@@ -581,12 +586,16 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
ret.left = dz > SIZE_MAX;
ret.right = RBIMPL_CAST((size_t)dz);
-#elif defined(_MSC_VER) && defined(_WIN64)
+#elif defined(_MSC_VER) && defined(_M_AMD64)
unsigned __int64 dp = 0;
unsigned __int64 dz = _umul128(x, y, &dp);
ret.left = RBIMPL_CAST((bool)dp);
ret.right = RBIMPL_CAST((size_t)dz);
+#elif defined(_MSC_VER) && defined(_M_ARM64)
+ ret.left = __umulh(x, y) != 0;
+ ret.right = x * y;
+
#else
/* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */
ret.left = (y != 0) && (x > SIZE_MAX / y);