diff --git a/BUILD.gn b/BUILD.gn index f756b4d..e92c3db 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -95,6 +95,7 @@ executable("vm") { "vm/port.h", "vm/primitives.cc", "vm/primitives.h", + "vm/random.cc", "vm/random.h", "vm/snapshot.cc", "vm/snapshot.h", diff --git a/SConstruct b/SConstruct index 21f0c44..23b31aa 100644 --- a/SConstruct +++ b/SConstruct @@ -220,6 +220,7 @@ def BuildVM(cxx, arch, target_os, debug, sanitize): 'os_win', 'port', 'primitives', + 'random', 'snapshot', 'thread_emscripten', 'thread_pool', diff --git a/vm/isolate.cc b/vm/isolate.cc index e8bb6fd..f9c3fdc 100644 --- a/vm/isolate.cc +++ b/vm/isolate.cc @@ -83,14 +83,14 @@ void Isolate::PrintStack() { interpreter_->PrintStack(); } -Isolate::Isolate(const void* snapshot, size_t snapshot_length, uint64_t seed) +Isolate::Isolate(const void* snapshot, size_t snapshot_length) : heap_(nullptr), interpreter_(nullptr), loop_(nullptr), snapshot_(snapshot), snapshot_length_(snapshot_length), - salt_(static_cast(seed)), - random_(seed), + random_(), + salt_(static_cast(random_.NextUInt64())), next_(nullptr) { heap_ = new Heap(); interpreter_ = new Interpreter(heap_, this); @@ -204,8 +204,7 @@ class SpawnIsolateTask : public ThreadPool::Task { initial_message_(initial_message) {} virtual void Run() { - uint64_t seed = OS::CurrentMonotonicNanos(); - Isolate* child_isolate = new Isolate(snapshot_, snapshot_length_, seed); + Isolate* child_isolate = new Isolate(snapshot_, snapshot_length_); child_isolate->loop()->PostMessage(initial_message_); initial_message_ = nullptr; intptr_t exit_code = child_isolate->loop()->Run(); diff --git a/vm/isolate.h b/vm/isolate.h index f5532eb..20a5d67 100644 --- a/vm/isolate.h +++ b/vm/isolate.h @@ -21,7 +21,7 @@ class ThreadPool; class Isolate { public: - Isolate(const void* snapshot, size_t snapshot_length, uint64_t seed); + Isolate(const void* snapshot, size_t snapshot_length); ~Isolate(); Heap* heap() const { return heap_; } @@ -54,10 +54,10 @@ class Isolate { Heap* heap_; Interpreter* interpreter_; MessageLoop* loop_; - const void* snapshot_; - size_t snapshot_length_; - uintptr_t salt_; + const void* const snapshot_; + const size_t snapshot_length_; Random random_; + const uintptr_t salt_; Isolate* next_; void AddIsolateToList(Isolate* isolate); diff --git a/vm/main.cc b/vm/main.cc index 99dfc5b..afee073 100644 --- a/vm/main.cc +++ b/vm/main.cc @@ -31,9 +31,8 @@ int main(int argc, const char** argv) { psoup::Isolate::Startup(); void (*defaultSIGINT)(int) = signal(SIGINT, SIGINT_handler); - uint64_t seed = psoup::OS::CurrentMonotonicNanos(); psoup::Isolate* isolate = new psoup::Isolate(snapshot.address(), - snapshot.size(), seed); + snapshot.size()); isolate->loop()->PostMessage(new psoup::IsolateMessage(ILLEGAL_PORT, argc - 2, &argv[2])); intptr_t exit_code = isolate->loop()->Run(); diff --git a/vm/main_emscripten.cc b/vm/main_emscripten.cc index 71db3f0..b614f92 100644 --- a/vm/main_emscripten.cc +++ b/vm/main_emscripten.cc @@ -31,8 +31,7 @@ extern "C" void load_snapshot(const void* snapshot, size_t snapshot_length) { psoup::Isolate::Startup(); _JS_initializeAliens(); - uint64_t seed = psoup::OS::CurrentMonotonicNanos(); - isolate = new psoup::Isolate(snapshot, snapshot_length, seed); + isolate = new psoup::Isolate(snapshot, snapshot_length); int argc = 0; const char** argv = nullptr; isolate->loop()->PostMessage(new psoup::IsolateMessage(ILLEGAL_PORT, diff --git a/vm/port.cc b/vm/port.cc index b8e9407..5aec1d9 100644 --- a/vm/port.cc +++ b/vm/port.cc @@ -4,7 +4,6 @@ #include "vm/port.h" -#include "vm/flags.h" #include "vm/lockers.h" #include "vm/message_loop.h" #include "vm/os.h" @@ -16,7 +15,7 @@ namespace psoup { Mutex* PortMap::mutex_ = nullptr; PortMap::Entry* PortMap::map_ = nullptr; -MessageLoop* PortMap::deleted_entry_ = reinterpret_cast(1); +MessageLoop* const PortMap::deleted_entry_ = reinterpret_cast(1); intptr_t PortMap::capacity_ = 0; intptr_t PortMap::used_ = 0; intptr_t PortMap::deleted_ = 0; @@ -31,7 +30,7 @@ intptr_t PortMap::FindPort(Port port) { return -1; } ASSERT(port != ILLEGAL_PORT); - intptr_t index = port % capacity_; + intptr_t index = static_cast(port) % capacity_; intptr_t start_index = index; Entry entry = map_[index]; while (entry.loop != nullptr) { @@ -103,7 +102,7 @@ Port PortMap::CreatePort(MessageLoop* loop) { // Search for the first unused slot. Make use of the knowledge that here is // currently no port with this id in the port map. ASSERT(FindPort(entry.port) < 0); - intptr_t index = entry.port % capacity_; + intptr_t index = static_cast(entry.port) % capacity_; Entry cur = map_[index]; // Stop the search at the first found unused (free or deleted) slot. while (cur.port != 0) { @@ -182,7 +181,7 @@ void PortMap::CloseAllPorts(MessageLoop* loop) { void PortMap::Startup() { mutex_ = new Mutex(); - prng_ = new Random(OS::CurrentMonotonicNanos()); + prng_ = new Random(); static const intptr_t kInitialCapacity = 8; // TODO(iposva): Verify whether we want to keep exponentially growing. diff --git a/vm/port.h b/vm/port.h index 17c75a9..511b330 100644 --- a/vm/port.h +++ b/vm/port.h @@ -45,7 +45,7 @@ class PortMap : public AllStatic { static Mutex* mutex_; static Entry* map_; - static MessageLoop* deleted_entry_; + static MessageLoop* const deleted_entry_; static intptr_t capacity_; static intptr_t used_; static intptr_t deleted_; diff --git a/vm/random.cc b/vm/random.cc new file mode 100644 index 0000000..a5b5654 --- /dev/null +++ b/vm/random.cc @@ -0,0 +1,22 @@ +// Copyright (c) 2024, the Newspeak project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "vm/random.h" + +#include "vm/assert.h" +#include "vm/os.h" + +namespace psoup { + +Random::Random() { + int result = OS::GetEntropy(&state_, sizeof(state_)); + if (result != 0) { + const size_t kBufferSize = 256; \ + char error_message[kBufferSize]; \ + FATAL("GetEntropy error: %d (%s)", result, \ + OS::StrError(result, error_message, kBufferSize)); \ + } +} + +} // namespace psoup diff --git a/vm/random.h b/vm/random.h index 68d4775..9e790dc 100644 --- a/vm/random.h +++ b/vm/random.h @@ -5,30 +5,28 @@ #ifndef VM_RANDOM_H_ #define VM_RANDOM_H_ +#include "vm/globals.h" + namespace psoup { // xorshift128+ // Sebastiano Vigna. "Further scramblings of Marsaglia’s xorshift generators." class Random { public: - explicit Random(uint64_t seed) { - state0_ = seed; - state1_ = 0; - } + Random(); uint64_t NextUInt64() { - uint64_t s1 = state0_; - const uint64_t s0 = state1_; + uint64_t s1 = state_[0]; + const uint64_t s0 = state_[1]; const uint64_t result = s0 + s1; - state0_ = s0; + state_[0] = s0; s1 ^= s1 << 23; - state1_ = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); + state_[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); return result; } private: - uint64_t state0_; - uint64_t state1_; + uint64_t state_[2]; }; } // namespace psoup