Skip to content

Commit

Permalink
Upgrade V8 binaries for 10.9.194.9 version
Browse files Browse the repository at this point in the history
  • Loading branch information
jacques-n committed Jan 12, 2023
1 parent 1f00b50 commit fdc11ef
Show file tree
Hide file tree
Showing 86 changed files with 3,927 additions and 1,793 deletions.
7 changes: 5 additions & 2 deletions deps/include/OWNERS
Expand Up @@ -7,9 +7,12 @@ yangguo@chromium.org

per-file *DEPS=file:../COMMON_OWNERS
per-file v8-internal.h=file:../COMMON_OWNERS
per-file v8-inspector.h=file:../src/inspector/OWNERS
per-file v8-inspector-protocol.h=file:../src/inspector/OWNERS

per-file v8-debug.h=file:../src/debug/OWNERS

per-file js_protocol.pdl=file:../src/inspector/OWNERS
per-file v8-inspector*=file:../src/inspector/OWNERS
per-file v8-inspector*=file:../src/inspector/OWNERS

# Needed by the auto_tag builder
per-file v8-version.h=v8-ci-autoroll-builder@chops-service-accounts.iam.gserviceaccount.com
Expand Down
123 changes: 121 additions & 2 deletions deps/include/cppgc/README.md
@@ -1,16 +1,135 @@
# Oilpan: C++ Garbage Collection

Oilpan is an open-source garbage collection library for C++ that can be used stand-alone or in collaboration with V8's JavaScript garbage collector.
Oilpan implements mark-and-sweep garbage collection (GC) with limited compaction (for a subset of objects).

**Key properties**

- Trace-based garbage collection;
- Incremental and concurrent marking;
- Incremental and concurrent sweeping;
- Precise on-heap memory layout;
- Conservative on-stack memory layout;
- Allows for collection with and without considering stack;
- Incremental and concurrent marking;
- Incremental and concurrent sweeping;
- Non-incremental and non-concurrent compaction for selected spaces;

See the [Hello World](https://chromium.googlesource.com/v8/v8/+/main/samples/cppgc/hello-world.cc) example on how to get started using Oilpan to manage C++ code.

Oilpan follows V8's project organization, see e.g. on how we accept [contributions](https://v8.dev/docs/contribute) and [provide a stable API](https://v8.dev/docs/api).

## Threading model

Oilpan features thread-local garbage collection and assumes heaps are not shared among threads.
In other words, objects are accessed and ultimately reclaimed by the garbage collector on the same thread that allocates them.
This allows Oilpan to run garbage collection in parallel with mutators running in other threads.

References to objects belonging to another thread's heap are modeled using cross-thread roots.
This is even true for on-heap to on-heap references.

Oilpan heaps may generally not be accessed from different threads unless otherwise noted.

## Heap partitioning

Oilpan's heaps are partitioned into spaces.
The space for an object is chosen depending on a number of criteria, e.g.:

- Objects over 64KiB are allocated in a large object space
- Objects can be assigned to a dedicated custom space.
Custom spaces can also be marked as compactable.
- Other objects are allocated in one of the normal page spaces bucketed depending on their size.

## Precise and conservative garbage collection

Oilpan supports two kinds of GCs:

1. **Conservative GC.**
A GC is called conservative when it is executed while the regular native stack is not empty.
In this case, the native stack might contain references to objects in Oilpan's heap, which should be kept alive.
The GC scans the native stack and treats the pointers discovered via the native stack as part of the root set.
This kind of GC is considered imprecise because values on stack other than references may accidentally appear as references to on-heap object, which means these objects will be kept alive despite being in practice unreachable from the application as an actual reference.

2. **Precise GC.**
A precise GC is triggered at the end of an event loop, which is controlled by an embedder via a platform.
At this point, it is guaranteed that there are no on-stack references pointing to Oilpan's heap.
This means there is no risk of confusing other value types with references.
Oilpan has precise knowledge of on-heap object layouts, and so it knows exactly where pointers lie in memory.
Oilpan can just start marking from the regular root set and collect all garbage precisely.

## Atomic, incremental and concurrent garbage collection

Oilpan has three modes of operation:

1. **Atomic GC.**
The entire GC cycle, including all its phases (e.g. see [Marking](#Marking-phase) and [Sweeping](#Sweeping-phase)), are executed back to back in a single pause.
This mode of operation is also known as Stop-The-World (STW) garbage collection.
It results in the most jank (due to a single long pause), but is overall the most efficient (e.g. no need for write barriers).

2. **Incremental GC.**
Garbage collection work is split up into multiple steps which are interleaved with the mutator, i.e. user code chunked into tasks.
Each step is a small chunk of work that is executed either as dedicated tasks between mutator tasks or, as needed, during mutator tasks.
Using incremental GC introduces the need for write barriers that record changes to the object graph so that a consistent state is observed and no objects are accidentally considered dead and reclaimed.
The incremental steps are followed by a smaller atomic pause to finalize garbage collection.
The smaller pause times, due to smaller chunks of work, helps with reducing jank.

3. **Concurrent GC.**
This is the most common type of GC.
It builds on top of incremental GC and offloads much of the garbage collection work away from the mutator thread and on to background threads.
Using concurrent GC allows the mutator thread to spend less time on GC and more on the actual mutator.

## Marking phase

The marking phase consists of the following steps:

1. Mark all objects in the root set.

2. Mark all objects transitively reachable from the root set by calling `Trace()` methods defined on each object.

3. Clear out all weak handles to unreachable objects and run weak callbacks.

The marking phase can be executed atomically in a stop-the-world manner, in which all 3 steps are executed one after the other.

Alternatively, it can also be executed incrementally/concurrently.
With incremental/concurrent marking, step 1 is executed in a short pause after which the mutator regains control.
Step 2 is repeatedly executed in an interleaved manner with the mutator.
When the GC is ready to finalize, i.e. step 2 is (almost) finished, another short pause is triggered in which step 2 is finished and step 3 is performed.

To prevent a user-after-free (UAF) issues it is required for Oilpan to know about all edges in the object graph.
This means that all pointers except on-stack pointers must be wrapped with Oilpan's handles (i.e., Persistent<>, Member<>, WeakMember<>).
Raw pointers to on-heap objects create an edge that Oilpan cannot observe and cause UAF issues
Thus, raw pointers shall not be used to reference on-heap objects (except for raw pointers on native stacks).

## Sweeping phase

The sweeping phase consists of the following steps:

1. Invoke pre-finalizers.
At this point, no destructors have been invoked and no memory has been reclaimed.
Pre-finalizers are allowed to access any other on-heap objects, even those that may get destructed.

2. Sweeping invokes destructors of the dead (unreachable) objects and reclaims memory to be reused by future allocations.

Assumptions should not be made about the order and the timing of their execution.
There is no guarantee on the order in which the destructors are invoked.
That's why destructors must not access any other on-heap objects (which might have already been destructed).
If some destructor unavoidably needs to access other on-heap objects, it will have to be converted to a pre-finalizer.
The pre-finalizer is allowed to access other on-heap objects.

The mutator is resumed before all destructors have ran.
For example, imagine a case where X is a client of Y, and Y holds a list of clients.
If the code relies on X's destructor removing X from the list, there is a risk that Y iterates the list and calls some method of X which may touch other on-heap objects.
This causes a use-after-free.
Care must be taken to make sure that X is explicitly removed from the list before the mutator resumes its execution in a way that doesn't rely on X's destructor (e.g. a pre-finalizer).

Similar to marking, sweeping can be executed in either an atomic stop-the-world manner or incrementally/concurrently.
With incremental/concurrent sweeping, step 2 is interleaved with mutator.
Incremental/concurrent sweeping can be atomically finalized in case it is needed to trigger another GC cycle.
Even with concurrent sweeping, destructors are guaranteed to run on the thread the object has been allocated on to preserve C++ semantics.

Notes:

* Weak processing runs only when the holder object of the WeakMember outlives the pointed object.
If the holder object and the pointed object die at the same time, weak processing doesn't run.
It is wrong to write code assuming that the weak processing always runs.

* Pre-finalizers are heavy because the thread needs to scan all pre-finalizers at each sweeping phase to determine which pre-finalizers should be invoked (the thread needs to invoke pre-finalizers of dead objects).
Adding pre-finalizers to frequently created objects should be avoided.
1 change: 0 additions & 1 deletion deps/include/cppgc/common.h
Expand Up @@ -5,7 +5,6 @@
#ifndef INCLUDE_CPPGC_COMMON_H_
#define INCLUDE_CPPGC_COMMON_H_

// TODO(chromium:1056170): Remove dependency on v8.
#include "v8config.h" // NOLINT(build/include_directory)

namespace cppgc {
Expand Down
15 changes: 7 additions & 8 deletions deps/include/cppgc/cross-thread-persistent.h
Expand Up @@ -120,7 +120,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
if (!IsValid(raw)) return;
PersistentRegionLock guard;
CrossThreadPersistentRegion& region = this->GetPersistentRegion(raw);
SetNode(region.AllocateNode(this, &Trace));
SetNode(region.AllocateNode(this, &TraceAsRoot));
this->CheckPointer(raw);
}

Expand All @@ -138,7 +138,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
: CrossThreadPersistentBase(raw), LocationPolicy(loc) {
if (!IsValid(raw)) return;
CrossThreadPersistentRegion& region = this->GetPersistentRegion(raw);
SetNode(region.AllocateNode(this, &Trace));
SetNode(region.AllocateNode(this, &TraceAsRoot));
this->CheckPointer(raw);
}

Expand Down Expand Up @@ -349,9 +349,8 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
return ptr && ptr != kSentinelPointer;
}

static void Trace(Visitor* v, const void* ptr) {
const auto* handle = static_cast<const BasicCrossThreadPersistent*>(ptr);
v->TraceRoot(*handle, handle->Location());
static void TraceAsRoot(RootVisitor& root_visitor, const void* ptr) {
root_visitor.Trace(*static_cast<const BasicCrossThreadPersistent*>(ptr));
}

void AssignUnsafe(T* ptr) {
Expand All @@ -378,7 +377,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
SetValue(ptr);
if (!IsValid(ptr)) return;
PersistentRegionLock guard;
SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &Trace));
SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &TraceAsRoot));
this->CheckPointer(ptr);
}

Expand All @@ -398,7 +397,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
}
SetValue(ptr);
if (!IsValid(ptr)) return;
SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &Trace));
SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &TraceAsRoot));
this->CheckPointer(ptr);
}

Expand All @@ -416,7 +415,7 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase,
return static_cast<T*>(const_cast<void*>(GetValueFromGC()));
}

friend class cppgc::Visitor;
friend class internal::RootVisitor;
};

template <typename T, typename LocationPolicy, typename CheckingPolicy>
Expand Down
12 changes: 2 additions & 10 deletions deps/include/cppgc/default-platform.h
Expand Up @@ -6,7 +6,6 @@
#define INCLUDE_CPPGC_DEFAULT_PLATFORM_H_

#include <memory>
#include <vector>

#include "cppgc/platform.h"
#include "libplatform/libplatform.h"
Expand All @@ -20,15 +19,6 @@ namespace cppgc {
*/
class V8_EXPORT DefaultPlatform : public Platform {
public:
/**
* Use this method instead of 'cppgc::InitializeProcess' when using
* 'cppgc::DefaultPlatform'. 'cppgc::DefaultPlatform::InitializeProcess'
* will initialize cppgc and v8 if needed (for non-standalone builds).
*
* \param platform DefaultPlatform instance used to initialize cppgc/v8.
*/
static void InitializeProcess(DefaultPlatform* platform);

using IdleTaskSupport = v8::platform::IdleTaskSupport;
explicit DefaultPlatform(
int thread_pool_size = 0,
Expand Down Expand Up @@ -64,6 +54,8 @@ class V8_EXPORT DefaultPlatform : public Platform {
return v8_platform_->GetTracingController();
}

v8::Platform* GetV8Platform() const { return v8_platform_.get(); }

protected:
static constexpr v8::Isolate* kNoIsolate = nullptr;

Expand Down
26 changes: 22 additions & 4 deletions deps/include/cppgc/explicit-management.h
Expand Up @@ -15,11 +15,27 @@ namespace cppgc {

class HeapHandle;

namespace subtle {

template <typename T>
void FreeUnreferencedObject(HeapHandle& heap_handle, T& object);
template <typename T>
bool Resize(T& object, AdditionalBytes additional_bytes);

} // namespace subtle

namespace internal {

V8_EXPORT void FreeUnreferencedObject(HeapHandle&, void*);
V8_EXPORT bool Resize(void*, size_t);
class ExplicitManagementImpl final {
private:
V8_EXPORT static void FreeUnreferencedObject(HeapHandle&, void*);
V8_EXPORT static bool Resize(void*, size_t);

template <typename T>
friend void subtle::FreeUnreferencedObject(HeapHandle&, T&);
template <typename T>
friend bool subtle::Resize(T&, AdditionalBytes);
};
} // namespace internal

namespace subtle {
Expand All @@ -45,7 +61,8 @@ template <typename T>
void FreeUnreferencedObject(HeapHandle& heap_handle, T& object) {
static_assert(IsGarbageCollectedTypeV<T>,
"Object must be of type GarbageCollected.");
internal::FreeUnreferencedObject(heap_handle, &object);
internal::ExplicitManagementImpl::FreeUnreferencedObject(heap_handle,
&object);
}

/**
Expand Down Expand Up @@ -73,7 +90,8 @@ template <typename T>
bool Resize(T& object, AdditionalBytes additional_bytes) {
static_assert(IsGarbageCollectedTypeV<T>,
"Object must be of type GarbageCollected.");
return internal::Resize(&object, sizeof(T) + additional_bytes.value);
return internal::ExplicitManagementImpl::Resize(
&object, sizeof(T) + additional_bytes.value);
}

} // namespace subtle
Expand Down
41 changes: 15 additions & 26 deletions deps/include/cppgc/garbage-collected.h
Expand Up @@ -5,8 +5,6 @@
#ifndef INCLUDE_CPPGC_GARBAGE_COLLECTED_H_
#define INCLUDE_CPPGC_GARBAGE_COLLECTED_H_

#include <type_traits>

#include "cppgc/internal/api-constants.h"
#include "cppgc/platform.h"
#include "cppgc/trace-trait.h"
Expand All @@ -16,28 +14,6 @@ namespace cppgc {

class Visitor;

namespace internal {

class GarbageCollectedBase {
public:
// Must use MakeGarbageCollected.
void* operator new(size_t) = delete;
void* operator new[](size_t) = delete;
// The garbage collector is taking care of reclaiming the object. Also,
// virtual destructor requires an unambiguous, accessible 'operator delete'.
void operator delete(void*) {
#ifdef V8_ENABLE_CHECKS
internal::Abort();
#endif // V8_ENABLE_CHECKS
}
void operator delete[](void*) = delete;

protected:
GarbageCollectedBase() = default;
};

} // namespace internal

/**
* Base class for managed objects. Only descendent types of `GarbageCollected`
* can be constructed using `MakeGarbageCollected()`. Must be inherited from as
Expand Down Expand Up @@ -74,11 +50,24 @@ class GarbageCollectedBase {
* \endcode
*/
template <typename T>
class GarbageCollected : public internal::GarbageCollectedBase {
class GarbageCollected {
public:
using IsGarbageCollectedTypeMarker = void;
using ParentMostGarbageCollectedType = T;

// Must use MakeGarbageCollected.
void* operator new(size_t) = delete;
void* operator new[](size_t) = delete;
// The garbage collector is taking care of reclaiming the object. Also,
// virtual destructor requires an unambiguous, accessible 'operator delete'.
void operator delete(void*) {
#ifdef V8_ENABLE_CHECKS
internal::Fatal(
"Manually deleting a garbage collected object is not allowed");
#endif // V8_ENABLE_CHECKS
}
void operator delete[](void*) = delete;

protected:
GarbageCollected() = default;
};
Expand All @@ -101,7 +90,7 @@ class GarbageCollected : public internal::GarbageCollectedBase {
* };
* \endcode
*/
class GarbageCollectedMixin : public internal::GarbageCollectedBase {
class GarbageCollectedMixin {
public:
using IsGarbageCollectedMixinTypeMarker = void;

Expand Down

0 comments on commit fdc11ef

Please sign in to comment.