diff options
| Commit | 75faff8b35b8f9bfa0a00b973e9323c1dc4c614e (patch) | |
|---|---|---|
| Author | 2018-11-19 23:47:44 +0200 | |
| Committer | 2018-11-19 23:47:44 +0200 | |
| Files | 276580c81b951058b77a4955ba34f71bd6c4809f /JSImpl/test/empty.cpp | |
| IPL-75faff8b35b8f9bfa0a00b973e9323c1dc4c614e.tar IPL-75faff8b35b8f9bfa0a00b973e9323c1dc4c614e.tar.gz IPL-75faff8b35b8f9bfa0a00b973e9323c1dc4c614e.zip | ||
| Parent | add56ccba064ed1012a00319834efeee222516a7 (diff) | |
Proof of concept for NaN boxing (#54)
* Proof of concept implementation of NaN boxing
* Added note about how to contribute
* Added homeworks post
* Fixed windows build
* Fixed windows build
1 files changed, 116 insertions, 0 deletions
| -rw-r--r-- | JSImpl/test/empty.cpp | 116 |
diff --git a/JSImpl/test/empty.cpp b/JSImpl/test/empty.cpp index 2787b00..2725467 100644 --- a/JSImpl/test/empty.cpp +++ b/JSImpl/test/empty.cpp @@ -1,4 +1,6 @@ #include <gtest/gtest.h> +#include <memory> +#include <cmath> TEST(Empty, Empty) { @@ -58,5 +60,119 @@ TEST(Pointer, int64) ASSERT_EQ(data + 9, PC); } +/* + * Value will be either a double, undefined, null, string, array, object, + * function, boolean. + * + * Pointer values (like string, array, object, function) can be shared pointers + * via intrusive pointer implementation. This way we can get a reference + * counting garbage collection. + * + */ +struct Value +{ + Value(double v) + { + m_value.as_double = v; + } + + Value(int tag, void* pointer) + { + assert(tag && "Zero tag is plain double"); + assert(!((size_t)pointer >> 48) && "Use only pointers to the heap."); + m_value.as_pointer.pointer = (size_t)pointer; + m_value.as_pointer.tag = tag; + m_value.as_pointer.nan = 0x1fff; + } + struct NanPointer + { + size_t pointer:48; + size_t tag:3; + size_t nan:13; + }; + + struct CheckType + { + size_t payload: 48; + size_t check:16; + }; + union { + double as_double; + NanPointer as_pointer; + CheckType to_check; + + } m_value; + + static_assert(sizeof(size_t) == 8, "unsupported arch"); + static_assert(sizeof(double) == 8, "unsupported arch"); + + bool is_double() const + { + return m_value.to_check.check <= 0xFFF8; + } + + double get_double() const + { + assert(is_double()); + return m_value.as_double; + } + + int get_tag() { + assert(!is_double()); + return m_value.as_pointer.tag; + } + + void* get_pointer() const { + return (void*)(size_t) m_value.as_pointer.pointer; + } +}; + + +TEST(NaNBox, PlainDoubles) +{ + double a = floor(rand() / RAND_MAX); + double values[] = { + 0.0, 2.89, 3.14, 0.0 / 1.0, 1.0 / a + }; + for (auto value: values) + { + Value box(value); + ASSERT_TRUE(box.is_double()); + ASSERT_EQ(value, box.get_double()); + + Value box2(-value); + ASSERT_TRUE(box2.is_double()); + ASSERT_EQ(-value, box2.get_double()); + } +} +TEST(NaNBox, Border) +{ + Value v(2, nullptr); + ASSERT_TRUE(std::isnan(v.m_value.as_double)); + ASSERT_FALSE(std::isinf(v.m_value.as_double)); +} +TEST(NaNBox, IsNaN) +{ + Value v2(std::sqrt(-1.0)); + ASSERT_TRUE(v2.is_double()); +} + +TEST(NaNBox, Pointers) +{ + std::vector<std::unique_ptr<int>> pointers; + int n = 1024; + pointers.reserve(n); + for (int i = 0; i < n; ++i) + { + pointers.emplace_back(std::make_unique<int>(i)); + } + + for (auto& value: pointers) + { + Value box(1, value.get()); + ASSERT_FALSE(box.is_double()); + ASSERT_EQ(value.get(), box.get_pointer()); + } +} |
