v8 11.3.244 (node 20.3.0)
V8 is Google's open source JavaScript engine
Loading...
Searching...
No Matches
v8-platform.h
Go to the documentation of this file.
1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_V8_PLATFORM_H_
6#define V8_V8_PLATFORM_H_
7
8#include <math.h>
9#include <stddef.h>
10#include <stdint.h>
11#include <stdlib.h> // For abort.
12
13#include <memory>
14#include <string>
15
16#include "v8config.h" // NOLINT(build/include_directory)
17
18namespace v8 {
19
20class Isolate;
21
22// Valid priorities supported by the task scheduling infrastructure.
23enum class TaskPriority : uint8_t {
42};
43
47class Task {
48 public:
49 virtual ~Task() = default;
50
51 virtual void Run() = 0;
52};
53
60class IdleTask {
61 public:
62 virtual ~IdleTask() = default;
63 virtual void Run(double deadline_in_seconds) = 0;
64};
65
73 public:
78 virtual void PostTask(std::unique_ptr<Task> task) = 0;
79
95 virtual void PostNonNestableTask(std::unique_ptr<Task> task) {}
96
102 virtual void PostDelayedTask(std::unique_ptr<Task> task,
103 double delay_in_seconds) = 0;
104
121 virtual void PostNonNestableDelayedTask(std::unique_ptr<Task> task,
122 double delay_in_seconds) {}
123
132 virtual void PostIdleTask(std::unique_ptr<IdleTask> task) = 0;
133
137 virtual bool IdleTasksEnabled() = 0;
138
142 virtual bool NonNestableTasksEnabled() const { return false; }
143
147 virtual bool NonNestableDelayedTasksEnabled() const { return false; }
148
149 TaskRunner() = default;
150 virtual ~TaskRunner() = default;
151
152 TaskRunner(const TaskRunner&) = delete;
153 TaskRunner& operator=(const TaskRunner&) = delete;
154};
155
161 public:
168 virtual bool ShouldYield() = 0;
169
175 virtual void NotifyConcurrencyIncrease() = 0;
176
182 virtual uint8_t GetTaskId() = 0;
183
188 virtual bool IsJoiningThread() const = 0;
189};
190
196 public:
197 virtual ~JobHandle() = default;
198
204 virtual void NotifyConcurrencyIncrease() = 0;
205
213 virtual void Join() = 0;
214
219 virtual void Cancel() = 0;
220
221 /*
222 * Forces all existing workers to yield ASAP but doesn’t wait for them.
223 * Warning, this is dangerous if the Job's callback is bound to or has access
224 * to state which may be deleted after this call.
225 */
226 virtual void CancelAndDetach() = 0;
227
231 virtual bool IsActive() = 0;
232
238 virtual bool IsValid() = 0;
239
243 virtual bool UpdatePriorityEnabled() const { return false; }
244
248 virtual void UpdatePriority(TaskPriority new_priority) {}
249};
250
254class JobTask {
255 public:
256 virtual ~JobTask() = default;
257
258 virtual void Run(JobDelegate* delegate) = 0;
259
267 virtual size_t GetMaxConcurrency(size_t worker_count) const = 0;
268};
269
282enum class BlockingType {
283 // The call might block (e.g. file I/O that might hit in memory cache).
284 kMayBlock,
285 // The call will definitely block (e.g. cache already checked and now pinging
286 // server synchronously).
288};
289
298 public:
299 virtual ~ScopedBlockingCall() = default;
300};
301
306 public:
307 virtual ~ConvertableToTraceFormat() = default;
308
315 virtual void AppendAsTraceFormat(std::string* out) const = 0;
316};
317
326 public:
327 virtual ~TracingController() = default;
328
329 // In Perfetto mode, trace events are written using Perfetto's Track Event
330 // API directly without going through the embedder. However, it is still
331 // possible to observe tracing being enabled and disabled.
332#if !defined(V8_USE_PERFETTO)
340 virtual const uint8_t* GetCategoryGroupEnabled(const char* name) {
341 static uint8_t no = 0;
342 return &no;
343 }
344
353 virtual uint64_t AddTraceEvent(
354 char phase, const uint8_t* category_enabled_flag, const char* name,
355 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
356 const char** arg_names, const uint8_t* arg_types,
357 const uint64_t* arg_values,
358 std::unique_ptr<ConvertableToTraceFormat>* arg_convertables,
359 unsigned int flags) {
360 return 0;
361 }
363 char phase, const uint8_t* category_enabled_flag, const char* name,
364 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
365 const char** arg_names, const uint8_t* arg_types,
366 const uint64_t* arg_values,
367 std::unique_ptr<ConvertableToTraceFormat>* arg_convertables,
368 unsigned int flags, int64_t timestamp) {
369 return 0;
370 }
371
376 virtual void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
377 const char* name, uint64_t handle) {}
378#endif // !defined(V8_USE_PERFETTO)
379
381 public:
382 virtual ~TraceStateObserver() = default;
383 virtual void OnTraceEnabled() = 0;
384 virtual void OnTraceDisabled() = 0;
385 };
386
392
398};
399
406 public:
407 virtual ~PageAllocator() = default;
408
413 virtual size_t AllocatePageSize() = 0;
414
419 virtual size_t CommitPageSize() = 0;
420
425 virtual void SetRandomMmapSeed(int64_t seed) = 0;
426
431 virtual void* GetRandomMmapAddr() = 0;
432
442 // Set this when reserving memory that will later require kReadWriteExecute
443 // permissions. The resulting behavior is platform-specific, currently
444 // this is used to set the MAP_JIT flag on Apple Silicon.
445 // TODO(jkummerow): Remove this when Wasm has a platform-independent
446 // w^x implementation.
447 // TODO(saelo): Remove this once all JIT pages are allocated through the
448 // VirtualAddressSpace API.
450 };
451
455 virtual void* AllocatePages(void* address, size_t length, size_t alignment,
456 Permission permissions) = 0;
457
461 virtual bool FreePages(void* address, size_t length) = 0;
462
466 virtual bool ReleasePages(void* address, size_t length,
467 size_t new_length) = 0;
468
472 virtual bool SetPermissions(void* address, size_t length,
473 Permission permissions) = 0;
474
480 virtual bool RecommitPages(void* address, size_t length,
481 Permission permissions) {
482 // TODO(v8:12797): make it pure once it's implemented on Chromium side.
483 return false;
484 }
485
493 virtual bool DiscardSystemPages(void* address, size_t size) { return true; }
494
503 virtual bool DecommitPages(void* address, size_t size) = 0;
504
510 public:
511 // Implementations are expected to free the shared memory mapping in the
512 // destructor.
513 virtual ~SharedMemoryMapping() = default;
514 virtual void* GetMemory() const = 0;
515 };
516
522 public:
523 // Implementations are expected to free the shared memory in the destructor.
524 virtual ~SharedMemory() = default;
525 virtual std::unique_ptr<SharedMemoryMapping> RemapTo(
526 void* new_address) const = 0;
527 virtual void* GetMemory() const = 0;
528 virtual size_t GetSize() const = 0;
529 };
530
540 virtual bool ReserveForSharedMemoryMapping(void* address, size_t size) {
541 return false;
542 }
543
553 virtual std::unique_ptr<SharedMemory> AllocateSharedPages(
554 size_t length, const void* original_address) {
555 return {};
556 }
557
566 virtual bool CanAllocateSharedPages() { return false; }
567};
568
569// Opaque type representing a handle to a shared memory region.
571static constexpr PlatformSharedMemoryHandle kInvalidSharedMemoryHandle = -1;
572
573// Conversion routines from the platform-dependent shared memory identifiers
574// into the opaque PlatformSharedMemoryHandle type. These use the underlying
575// types (e.g. unsigned int) instead of the typedef'd ones (e.g. mach_port_t)
576// to avoid pulling in large OS header files into this header file. Instead,
577// the users of these routines are expected to include the respecitve OS
578// headers in addition to this one.
579#if V8_OS_DARWIN
580// Convert between a shared memory handle and a mach_port_t referencing a memory
581// entry object.
582inline PlatformSharedMemoryHandle SharedMemoryHandleFromMachMemoryEntry(
583 unsigned int port) {
584 return static_cast<PlatformSharedMemoryHandle>(port);
585}
586inline unsigned int MachMemoryEntryFromSharedMemoryHandle(
588 return static_cast<unsigned int>(handle);
589}
590#elif V8_OS_FUCHSIA
591// Convert between a shared memory handle and a zx_handle_t to a VMO.
592inline PlatformSharedMemoryHandle SharedMemoryHandleFromVMO(uint32_t handle) {
593 return static_cast<PlatformSharedMemoryHandle>(handle);
594}
595inline uint32_t VMOFromSharedMemoryHandle(PlatformSharedMemoryHandle handle) {
596 return static_cast<uint32_t>(handle);
597}
598#elif V8_OS_WIN
599// Convert between a shared memory handle and a Windows HANDLE to a file mapping
600// object.
601inline PlatformSharedMemoryHandle SharedMemoryHandleFromFileMapping(
602 void* handle) {
603 return reinterpret_cast<PlatformSharedMemoryHandle>(handle);
604}
605inline void* FileMappingFromSharedMemoryHandle(
607 return reinterpret_cast<void*>(handle);
608}
609#else
610// Convert between a shared memory handle and a file descriptor.
612 return static_cast<PlatformSharedMemoryHandle>(fd);
613}
616 return static_cast<int>(handle);
617}
618#endif
619
623enum class PagePermissions {
624 kNoAccess,
625 kRead,
629};
630
642 public:
643 using Address = uintptr_t;
644
646 Address base, size_t size,
648 : page_size_(page_size),
649 allocation_granularity_(allocation_granularity),
650 base_(base),
651 size_(size),
652 max_page_permissions_(max_page_permissions) {}
653
654 virtual ~VirtualAddressSpace() = default;
655
663 size_t page_size() const { return page_size_; }
664
673 size_t allocation_granularity() const { return allocation_granularity_; }
674
680 Address base() const { return base_; }
681
687 size_t size() const { return size_; }
688
695 PagePermissions max_page_permissions() const { return max_page_permissions_; }
696
703 virtual void SetRandomSeed(int64_t seed) = 0;
704
712
733 static constexpr Address kNoHint = 0;
735 AllocatePages(Address hint, size_t size, size_t alignment,
736 PagePermissions permissions) = 0;
737
750 virtual void FreePages(Address address, size_t size) = 0;
751
770 Address address, size_t size, PagePermissions permissions) = 0;
771
789 size_t size) = 0;
790
804 virtual void FreeGuardRegion(Address address, size_t size) = 0;
805
827 PlatformSharedMemoryHandle handle, uint64_t offset) = 0;
828
841 virtual void FreeSharedPages(Address address, size_t size) = 0;
842
848 virtual bool CanAllocateSubspaces() = 0;
849
850 /*
851 * Allocate a subspace.
852 *
853 * The address space of a subspace stays reserved in the parent space for the
854 * lifetime of the subspace. As such, it is guaranteed that page allocations
855 * on the parent space cannot end up inside a subspace.
856 *
857 * \param hint Hints where the subspace should be allocated. See
858 * AllocatePages() for more details.
859 *
860 * \param size The size in bytes of the subspace. Must be a multiple of the
861 * allocation_granularity().
862 *
863 * \param alignment The alignment of the subspace in bytes. Must be a multiple
864 * of the allocation_granularity() and should be a power of two.
865 *
866 * \param max_page_permissions The maximum permissions that pages allocated in
867 * the subspace can obtain.
868 *
869 * \returns a new subspace or nullptr on failure.
870 */
871 virtual std::unique_ptr<VirtualAddressSpace> AllocateSubspace(
872 Address hint, size_t size, size_t alignment,
874
875 //
876 // TODO(v8) maybe refactor the methods below before stabilizing the API. For
877 // example by combining them into some form of page operation method that
878 // takes a command enum as parameter.
879 //
880
897 Address address, size_t size, PagePermissions permissions) = 0;
898
910 size_t size) {
911 return true;
912 }
924 size_t size) = 0;
925
926 private:
927 const size_t page_size_;
928 const size_t allocation_granularity_;
929 const Address base_;
930 const size_t size_;
931 const PagePermissions max_page_permissions_;
932};
933
938 public:
939 using MallocFn = void* (*)(size_t);
940 using FreeFn = void (*)(void*);
941
942 virtual MallocFn GetMallocFn() const { return ::malloc; }
943 virtual FreeFn GetFreeFn() const { return ::free; }
944};
945
951 public:
952 virtual void EnterSection() {}
953 virtual void LeaveSection() {}
954};
955
962class Platform {
963 public:
964 virtual ~Platform() = default;
965
971
976 static ZoneBackingAllocator default_allocator;
977 return &default_allocator;
978 }
979
987 virtual void OnCriticalMemoryPressure() {}
988
997 virtual int NumberOfWorkerThreads() = 0;
998
1004 virtual std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner(
1005 Isolate* isolate) = 0;
1006
1010 virtual void CallOnWorkerThread(std::unique_ptr<Task> task) = 0;
1011
1016 virtual void CallBlockingTaskOnWorkerThread(std::unique_ptr<Task> task) {
1017 // Embedders may optionally override this to process these tasks in a high
1018 // priority pool.
1019 CallOnWorkerThread(std::move(task));
1020 }
1021
1025 virtual void CallLowPriorityTaskOnWorkerThread(std::unique_ptr<Task> task) {
1026 // Embedders may optionally override this to process these tasks in a low
1027 // priority pool.
1028 CallOnWorkerThread(std::move(task));
1029 }
1030
1035 virtual void CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
1036 double delay_in_seconds) = 0;
1037
1041 virtual bool IdleTasksEnabled(Isolate* isolate) { return false; }
1042
1087 virtual std::unique_ptr<JobHandle> PostJob(
1088 TaskPriority priority, std::unique_ptr<JobTask> job_task) {
1089 auto handle = CreateJob(priority, std::move(job_task));
1090 handle->NotifyConcurrencyIncrease();
1091 return handle;
1092 }
1093
1107 virtual std::unique_ptr<JobHandle> CreateJob(
1108 TaskPriority priority, std::unique_ptr<JobTask> job_task) = 0;
1109
1113 virtual std::unique_ptr<ScopedBlockingCall> CreateBlockingScope(
1114 BlockingType blocking_type) {
1115 return nullptr;
1116 }
1117
1125 virtual double MonotonicallyIncreasingTime() = 0;
1126
1133 return floor(CurrentClockTimeMillis());
1134 }
1135
1141 virtual double CurrentClockTimeMillis() = 0;
1142
1147 return CurrentClockTimeMillis();
1148 }
1149
1150 typedef void (*StackTracePrinter)();
1151
1156 virtual StackTracePrinter GetStackTracePrinter() { return nullptr; }
1157
1162
1167 virtual void DumpWithoutCrashing() {}
1168
1175 static HighAllocationThroughputObserver default_observer;
1176 return &default_observer;
1177 }
1178
1179 protected:
1186};
1187
1188} // namespace v8
1189
1190#endif // V8_V8_PLATFORM_H_
virtual void AppendAsTraceFormat(std::string *out) const =0
virtual ~ConvertableToTraceFormat()=default
virtual ~IdleTask()=default
virtual void Run(double deadline_in_seconds)=0
virtual bool IsJoiningThread() const =0
virtual uint8_t GetTaskId()=0
virtual bool ShouldYield()=0
virtual void NotifyConcurrencyIncrease()=0
virtual void UpdatePriority(TaskPriority new_priority)
virtual bool UpdatePriorityEnabled() const
virtual void CancelAndDetach()=0
virtual bool IsActive()=0
virtual bool IsValid()=0
virtual void Cancel()=0
virtual void NotifyConcurrencyIncrease()=0
virtual ~JobHandle()=default
virtual void Join()=0
virtual size_t GetMaxConcurrency(size_t worker_count) const =0
virtual void Run(JobDelegate *delegate)=0
virtual ~JobTask()=default
virtual std::unique_ptr< SharedMemoryMapping > RemapTo(void *new_address) const =0
virtual size_t GetSize() const =0
virtual void * GetMemory() const =0
virtual ~SharedMemory()=default
virtual void * GetMemory() const =0
virtual std::unique_ptr< SharedMemory > AllocateSharedPages(size_t length, const void *original_address)
virtual bool SetPermissions(void *address, size_t length, Permission permissions)=0
virtual bool CanAllocateSharedPages()
virtual bool DecommitPages(void *address, size_t size)=0
virtual void * AllocatePages(void *address, size_t length, size_t alignment, Permission permissions)=0
virtual bool RecommitPages(void *address, size_t length, Permission permissions)
virtual void * GetRandomMmapAddr()=0
virtual size_t CommitPageSize()=0
virtual bool DiscardSystemPages(void *address, size_t size)
virtual bool ReserveForSharedMemoryMapping(void *address, size_t size)
virtual bool ReleasePages(void *address, size_t length, size_t new_length)=0
virtual void SetRandomMmapSeed(int64_t seed)=0
virtual ~PageAllocator()=default
virtual size_t AllocatePageSize()=0
virtual bool FreePages(void *address, size_t length)=0
virtual ~Platform()=default
virtual TracingController * GetTracingController()=0
static V8_EXPORT double SystemClockTimeMillis()
virtual double CurrentClockTimeMillisecondsHighResolution()
virtual std::unique_ptr< JobHandle > PostJob(TaskPriority priority, std::unique_ptr< JobTask > job_task)
virtual PageAllocator * GetPageAllocator()=0
virtual void CallLowPriorityTaskOnWorkerThread(std::unique_ptr< Task > task)
virtual ZoneBackingAllocator * GetZoneBackingAllocator()
virtual std::unique_ptr< JobHandle > CreateJob(TaskPriority priority, std::unique_ptr< JobTask > job_task)=0
virtual void DumpWithoutCrashing()
virtual void CallBlockingTaskOnWorkerThread(std::unique_ptr< Task > task)
virtual std::shared_ptr< v8::TaskRunner > GetForegroundTaskRunner(Isolate *isolate)=0
void(* StackTracePrinter)()
virtual StackTracePrinter GetStackTracePrinter()
virtual void CallOnWorkerThread(std::unique_ptr< Task > task)=0
virtual double CurrentClockTimeMillis()=0
virtual void OnCriticalMemoryPressure()
virtual void CallDelayedOnWorkerThread(std::unique_ptr< Task > task, double delay_in_seconds)=0
virtual HighAllocationThroughputObserver * GetHighAllocationThroughputObserver()
virtual bool IdleTasksEnabled(Isolate *isolate)
virtual int64_t CurrentClockTimeMilliseconds()
virtual std::unique_ptr< ScopedBlockingCall > CreateBlockingScope(BlockingType blocking_type)
virtual double MonotonicallyIncreasingTime()=0
virtual int NumberOfWorkerThreads()=0
virtual ~ScopedBlockingCall()=default
virtual void Run()=0
virtual ~Task()=default
virtual bool NonNestableTasksEnabled() const
virtual void PostNonNestableDelayedTask(std::unique_ptr< Task > task, double delay_in_seconds)
virtual void PostDelayedTask(std::unique_ptr< Task > task, double delay_in_seconds)=0
TaskRunner(const TaskRunner &)=delete
TaskRunner()=default
virtual bool NonNestableDelayedTasksEnabled() const
virtual void PostIdleTask(std::unique_ptr< IdleTask > task)=0
virtual bool IdleTasksEnabled()=0
virtual void PostTask(std::unique_ptr< Task > task)=0
virtual ~TaskRunner()=default
TaskRunner & operator=(const TaskRunner &)=delete
virtual void PostNonNestableTask(std::unique_ptr< Task > task)
Definition v8-platform.h:95
virtual const uint8_t * GetCategoryGroupEnabled(const char *name)
virtual void AddTraceStateObserver(TraceStateObserver *)
virtual ~TracingController()=default
virtual uint64_t AddTraceEventWithTimestamp(char phase, const uint8_t *category_enabled_flag, const char *name, const char *scope, uint64_t id, uint64_t bind_id, int32_t num_args, const char **arg_names, const uint8_t *arg_types, const uint64_t *arg_values, std::unique_ptr< ConvertableToTraceFormat > *arg_convertables, unsigned int flags, int64_t timestamp)
virtual void UpdateTraceEventDuration(const uint8_t *category_enabled_flag, const char *name, uint64_t handle)
virtual uint64_t AddTraceEvent(char phase, const uint8_t *category_enabled_flag, const char *name, const char *scope, uint64_t id, uint64_t bind_id, int32_t num_args, const char **arg_names, const uint8_t *arg_types, const uint64_t *arg_values, std::unique_ptr< ConvertableToTraceFormat > *arg_convertables, unsigned int flags)
virtual void RemoveTraceStateObserver(TraceStateObserver *)
size_t page_size() const
virtual V8_WARN_UNUSED_RESULT bool DiscardSystemPages(Address address, size_t size)
static constexpr Address kNoHint
VirtualAddressSpace(size_t page_size, size_t allocation_granularity, Address base, size_t size, PagePermissions max_page_permissions)
virtual void SetRandomSeed(int64_t seed)=0
virtual V8_WARN_UNUSED_RESULT bool SetPagePermissions(Address address, size_t size, PagePermissions permissions)=0
size_t allocation_granularity() const
virtual V8_WARN_UNUSED_RESULT Address AllocateSharedPages(Address hint, size_t size, PagePermissions permissions, PlatformSharedMemoryHandle handle, uint64_t offset)=0
virtual void FreeGuardRegion(Address address, size_t size)=0
virtual V8_WARN_UNUSED_RESULT bool DecommitPages(Address address, size_t size)=0
virtual ~VirtualAddressSpace()=default
virtual std::unique_ptr< VirtualAddressSpace > AllocateSubspace(Address hint, size_t size, size_t alignment, PagePermissions max_page_permissions)=0
virtual V8_WARN_UNUSED_RESULT bool RecommitPages(Address address, size_t size, PagePermissions permissions)=0
virtual void FreeSharedPages(Address address, size_t size)=0
virtual V8_WARN_UNUSED_RESULT Address AllocatePages(Address hint, size_t size, size_t alignment, PagePermissions permissions)=0
virtual void FreePages(Address address, size_t size)=0
virtual bool CanAllocateSubspaces()=0
Address base() const
virtual Address RandomPageAddress()=0
PagePermissions max_page_permissions() const
virtual V8_WARN_UNUSED_RESULT bool AllocateGuardRegion(Address address, size_t size)=0
void(*)(void *) FreeFn
virtual MallocFn GetMallocFn() const
virtual FreeFn GetFreeFn() const
void *(*)(size_t) MallocFn
intptr_t PlatformSharedMemoryHandle
PlatformSharedMemoryHandle SharedMemoryHandleFromFileDescriptor(int fd)
TaskPriority
Definition v8-platform.h:23
int FileDescriptorFromSharedMemoryHandle(PlatformSharedMemoryHandle handle)
PagePermissions
BlockingType
#define V8_EXPORT
Definition v8config.h:719
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:609