forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: support WeakReference in snapshot
Move util::WeakReference to a separate header and implement {de}serialization for it to be snapshotable. PR-URL: nodejs#44193 Refs: nodejs#44014 Refs: nodejs#37476 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
- Loading branch information
1 parent
5144634
commit 4670f7c
Showing
9 changed files
with
246 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
|
||
#ifndef SRC_NODE_UTIL_H_ | ||
#define SRC_NODE_UTIL_H_ | ||
|
||
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | ||
#include "base_object.h" | ||
#include "node_snapshotable.h" | ||
#include "v8.h" | ||
|
||
namespace node { | ||
namespace util { | ||
|
||
class WeakReference : public SnapshotableObject { | ||
public: | ||
SERIALIZABLE_OBJECT_METHODS(); | ||
|
||
static constexpr FastStringKey type_name{"node::util::WeakReference"}; | ||
static constexpr EmbedderObjectType type_int = | ||
EmbedderObjectType::k_util_weak_reference; | ||
|
||
WeakReference(Environment* env, | ||
v8::Local<v8::Object> object, | ||
v8::Local<v8::Object> target); | ||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
static void Get(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
static void IncRef(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
static void DecRef(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
|
||
SET_MEMORY_INFO_NAME(WeakReference) | ||
SET_SELF_SIZE(WeakReference) | ||
SET_NO_MEMORY_INFO() | ||
|
||
struct InternalFieldInfo : public node::InternalFieldInfoBase { | ||
SnapshotIndex target; | ||
uint64_t reference_count; | ||
}; | ||
|
||
private: | ||
WeakReference(Environment* env, | ||
v8::Local<v8::Object> object, | ||
v8::Local<v8::Object> target, | ||
uint64_t reference_count); | ||
v8::Global<v8::Object> target_; | ||
uint64_t reference_count_ = 0; | ||
|
||
SnapshotIndex target_index_ = 0; // 0 means target_ is not snapshotted | ||
}; | ||
|
||
} // namespace util | ||
} // namespace node | ||
|
||
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | ||
|
||
#endif // SRC_NODE_UTIL_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
'use strict'; | ||
|
||
const { internalBinding } = require('internal/test/binding'); | ||
const { WeakReference } = internalBinding('util'); | ||
const { | ||
setDeserializeMainFunction | ||
} = require('v8').startupSnapshot | ||
const assert = require('assert'); | ||
|
||
let obj = { hello: 'world' }; | ||
const ref = new WeakReference(obj); | ||
|
||
setDeserializeMainFunction(() => { | ||
obj = null; | ||
globalThis.gc(); | ||
|
||
setImmediate(() => { | ||
assert.strictEqual(ref.get(), undefined); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use strict'; | ||
|
||
const { internalBinding } = require('internal/test/binding'); | ||
const { WeakReference } = internalBinding('util'); | ||
const { | ||
setDeserializeMainFunction | ||
} = require('v8').startupSnapshot | ||
const assert = require('assert'); | ||
|
||
let obj = { hello: 'world' }; | ||
const ref = new WeakReference(obj); | ||
|
||
setDeserializeMainFunction(() => { | ||
assert.strictEqual(ref.get(), obj); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
'use strict'; | ||
|
||
// This tests that weak references work across serialization. | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
const { spawnSync } = require('child_process'); | ||
const tmpdir = require('../common/tmpdir'); | ||
const fixtures = require('../common/fixtures'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
|
||
tmpdir.refresh(); | ||
const blobPath = path.join(tmpdir.path, 'snapshot.blob'); | ||
|
||
function runTest(entry) { | ||
console.log('running test with', entry); | ||
{ | ||
const child = spawnSync(process.execPath, [ | ||
'--expose-internals', | ||
'--expose-gc', | ||
'--snapshot-blob', | ||
blobPath, | ||
'--build-snapshot', | ||
entry, | ||
], { | ||
cwd: tmpdir.path | ||
}); | ||
if (child.status !== 0) { | ||
console.log(child.stderr.toString()); | ||
console.log(child.stdout.toString()); | ||
assert.strictEqual(child.status, 0); | ||
} | ||
const stats = fs.statSync(path.join(tmpdir.path, 'snapshot.blob')); | ||
assert(stats.isFile()); | ||
} | ||
|
||
{ | ||
const child = spawnSync(process.execPath, [ | ||
'--expose-internals', | ||
'--expose-gc', | ||
'--snapshot-blob', | ||
blobPath, | ||
], { | ||
cwd: tmpdir.path, | ||
env: { | ||
...process.env, | ||
} | ||
}); | ||
|
||
const stdout = child.stdout.toString().trim(); | ||
const stderr = child.stderr.toString().trim(); | ||
console.log(`[stdout]:\n${stdout}\n`); | ||
console.log(`[stderr]:\n${stderr}\n`); | ||
assert.strictEqual(child.status, 0); | ||
} | ||
} | ||
|
||
runTest(fixtures.path('snapshot', 'weak-reference.js')); | ||
runTest(fixtures.path('snapshot', 'weak-reference-gc.js')); |