[serializer] change internal field callbacks to take data pointer.
R=jochen@chromium.org, peria@chromium.org BUG=chromium:617892 Review-Url: https://codereview.chromium.org/2628093003 Cr-Commit-Position: refs/heads/master@{#42268}
This commit is contained in:
parent
9884fb91e1
commit
9cd0de73dc
36
include/v8.h
36
include/v8.h
@ -6281,17 +6281,33 @@ class V8_EXPORT EmbedderHeapTracer {
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to the embedder used in SnapshotCreator to handle internal fields.
|
||||
* Callback and supporting data used in SnapshotCreator to implement embedder
|
||||
* logic to serialize internal fields.
|
||||
*/
|
||||
typedef StartupData (*SerializeInternalFieldsCallback)(Local<Object> holder,
|
||||
int index);
|
||||
struct SerializeInternalFieldsCallback {
|
||||
typedef StartupData (*CallbackFunction)(Local<Object> holder, int index,
|
||||
void* data);
|
||||
SerializeInternalFieldsCallback(CallbackFunction function = nullptr,
|
||||
void* data_arg = nullptr)
|
||||
: callback(function), data(data_arg) {}
|
||||
CallbackFunction callback;
|
||||
void* data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to the embedder used to deserialize internal fields.
|
||||
* Callback and supporting data used to implement embedder logic to deserialize
|
||||
* internal fields.
|
||||
*/
|
||||
typedef void (*DeserializeInternalFieldsCallback)(Local<Object> holder,
|
||||
int index,
|
||||
StartupData payload);
|
||||
struct DeserializeInternalFieldsCallback {
|
||||
typedef void (*CallbackFunction)(Local<Object> holder, int index,
|
||||
StartupData payload, void* data);
|
||||
DeserializeInternalFieldsCallback(CallbackFunction function = nullptr,
|
||||
void* data_arg = nullptr)
|
||||
: callback(function), data(data_arg) {}
|
||||
void (*callback)(Local<Object> holder, int index, StartupData payload,
|
||||
void* data);
|
||||
void* data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Isolate represents an isolated instance of the V8 engine. V8 isolates have
|
||||
@ -7689,7 +7705,8 @@ class V8_EXPORT SnapshotCreator {
|
||||
* \returns the index of the context in the snapshot blob.
|
||||
*/
|
||||
size_t AddContext(Local<Context> context,
|
||||
SerializeInternalFieldsCallback callback = nullptr);
|
||||
SerializeInternalFieldsCallback callback =
|
||||
SerializeInternalFieldsCallback());
|
||||
|
||||
/**
|
||||
* Add a template to be included in the snapshot blob.
|
||||
@ -8029,7 +8046,8 @@ class V8_EXPORT Context {
|
||||
|
||||
static MaybeLocal<Context> FromSnapshot(
|
||||
Isolate* isolate, size_t context_snapshot_index,
|
||||
DeserializeInternalFieldsCallback internal_fields_deserializer = nullptr,
|
||||
DeserializeInternalFieldsCallback internal_fields_deserializer =
|
||||
DeserializeInternalFieldsCallback(),
|
||||
ExtensionConfiguration* extensions = nullptr,
|
||||
MaybeLocal<Value> global_object = MaybeLocal<Value>());
|
||||
|
||||
|
@ -615,8 +615,8 @@ StartupData SnapshotCreator::CreateBlob(
|
||||
|
||||
{
|
||||
// The default snapshot does not support internal fields.
|
||||
i::PartialSerializer partial_serializer(isolate, &startup_serializer,
|
||||
nullptr);
|
||||
i::PartialSerializer partial_serializer(
|
||||
isolate, &startup_serializer, v8::SerializeInternalFieldsCallback());
|
||||
partial_serializer.Serialize(&default_context, false);
|
||||
context_snapshots.Add(new i::SnapshotData(&partial_serializer));
|
||||
}
|
||||
@ -6297,7 +6297,7 @@ Local<Context> v8::Context::New(v8::Isolate* external_isolate,
|
||||
v8::MaybeLocal<ObjectTemplate> global_template,
|
||||
v8::MaybeLocal<Value> global_object) {
|
||||
return NewContext(external_isolate, extensions, global_template,
|
||||
global_object, 0, nullptr);
|
||||
global_object, 0, DeserializeInternalFieldsCallback());
|
||||
}
|
||||
|
||||
MaybeLocal<Context> v8::Context::FromSnapshot(
|
||||
@ -6334,7 +6334,8 @@ MaybeLocal<Object> v8::Context::NewRemoteContext(
|
||||
"Global template needs to have access check handlers.");
|
||||
i::Handle<i::JSGlobalProxy> global_proxy =
|
||||
CreateEnvironment<i::JSGlobalProxy>(isolate, nullptr, global_template,
|
||||
global_object, 0, nullptr);
|
||||
global_object, 0,
|
||||
DeserializeInternalFieldsCallback());
|
||||
if (global_proxy.is_null()) {
|
||||
if (isolate->has_pending_exception()) {
|
||||
isolate->OptionalRescheduleException(true);
|
||||
|
@ -466,7 +466,8 @@ bool Debug::Load() {
|
||||
static const int kFirstContextSnapshotIndex = 0;
|
||||
Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
|
||||
MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
|
||||
kFirstContextSnapshotIndex, nullptr, DEBUG_CONTEXT);
|
||||
kFirstContextSnapshotIndex, v8::DeserializeInternalFieldsCallback(),
|
||||
DEBUG_CONTEXT);
|
||||
|
||||
// Fail if no context could be created.
|
||||
if (context.is_null()) return false;
|
||||
|
@ -221,7 +221,7 @@ void Deserializer::DeserializeInternalFields(
|
||||
DisallowHeapAllocation no_gc;
|
||||
DisallowJavascriptExecution no_js(isolate_);
|
||||
DisallowCompilation no_compile(isolate_);
|
||||
DCHECK_NOT_NULL(internal_fields_deserializer);
|
||||
DCHECK_NOT_NULL(internal_fields_deserializer.callback);
|
||||
for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) {
|
||||
HandleScope scope(isolate_);
|
||||
int space = code & kSpaceMask;
|
||||
@ -233,8 +233,9 @@ void Deserializer::DeserializeInternalFields(
|
||||
int size = source_.GetInt();
|
||||
byte* data = new byte[size];
|
||||
source_.CopyRaw(data, size);
|
||||
internal_fields_deserializer(v8::Utils::ToLocal(obj), index,
|
||||
{reinterpret_cast<char*>(data), size});
|
||||
internal_fields_deserializer.callback(v8::Utils::ToLocal(obj), index,
|
||||
{reinterpret_cast<char*>(data), size},
|
||||
internal_fields_deserializer.data);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
||||
if (obj->IsJSObject()) {
|
||||
JSObject* jsobj = JSObject::cast(obj);
|
||||
if (jsobj->GetInternalFieldCount() > 0) {
|
||||
DCHECK_NOT_NULL(serialize_internal_fields_);
|
||||
DCHECK_NOT_NULL(serialize_internal_fields_.callback);
|
||||
internal_field_holders_.Add(jsobj);
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,7 @@ void PartialSerializer::SerializeInternalFields() {
|
||||
DisallowHeapAllocation no_gc;
|
||||
DisallowJavascriptExecution no_js(isolate());
|
||||
DisallowCompilation no_compile(isolate());
|
||||
DCHECK_NOT_NULL(serialize_internal_fields_);
|
||||
DCHECK_NOT_NULL(serialize_internal_fields_.callback);
|
||||
sink_.Put(kInternalFieldsData, "internal fields data");
|
||||
while (internal_field_holders_.length() > 0) {
|
||||
HandleScope scope(isolate());
|
||||
@ -142,7 +142,8 @@ void PartialSerializer::SerializeInternalFields() {
|
||||
int internal_fields_count = obj->GetInternalFieldCount();
|
||||
for (int i = 0; i < internal_fields_count; i++) {
|
||||
if (obj->GetInternalField(i)->IsHeapObject()) continue;
|
||||
StartupData data = serialize_internal_fields_(v8::Utils::ToLocal(obj), i);
|
||||
StartupData data = serialize_internal_fields_.callback(
|
||||
v8::Utils::ToLocal(obj), i, serialize_internal_fields_.data);
|
||||
sink_.Put(kNewObject + reference.space(), "internal field holder");
|
||||
PutBackReference(*obj, reference);
|
||||
sink_.PutInt(i, "internal field index");
|
||||
|
@ -285,7 +285,8 @@ static void PartiallySerializeObject(Vector<const byte>* startup_blob_out,
|
||||
isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
|
||||
startup_serializer.SerializeStrongReferences();
|
||||
|
||||
PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr);
|
||||
PartialSerializer partial_serializer(isolate, &startup_serializer,
|
||||
v8::SerializeInternalFieldsCallback());
|
||||
partial_serializer.Serialize(&raw_foo, false);
|
||||
|
||||
startup_serializer.SerializeWeakReferencesAndDeferred();
|
||||
@ -321,7 +322,9 @@ UNINITIALIZED_TEST(PartialSerializerObject) {
|
||||
{
|
||||
SnapshotData snapshot_data(partial_blob);
|
||||
Deserializer deserializer(&snapshot_data);
|
||||
root = deserializer.DeserializePartial(isolate, global_proxy, nullptr)
|
||||
root = deserializer
|
||||
.DeserializePartial(isolate, global_proxy,
|
||||
v8::DeserializeInternalFieldsCallback())
|
||||
.ToHandleChecked();
|
||||
CHECK(root->IsString());
|
||||
}
|
||||
@ -330,7 +333,9 @@ UNINITIALIZED_TEST(PartialSerializerObject) {
|
||||
{
|
||||
SnapshotData snapshot_data(partial_blob);
|
||||
Deserializer deserializer(&snapshot_data);
|
||||
root2 = deserializer.DeserializePartial(isolate, global_proxy, nullptr)
|
||||
root2 = deserializer
|
||||
.DeserializePartial(isolate, global_proxy,
|
||||
v8::DeserializeInternalFieldsCallback())
|
||||
.ToHandleChecked();
|
||||
CHECK(root2->IsString());
|
||||
CHECK(root.is_identical_to(root2));
|
||||
@ -385,7 +390,8 @@ static void PartiallySerializeContext(Vector<const byte>* startup_blob_out,
|
||||
startup_serializer.SerializeStrongReferences();
|
||||
|
||||
SnapshotByteSink partial_sink;
|
||||
PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr);
|
||||
PartialSerializer partial_serializer(isolate, &startup_serializer,
|
||||
v8::SerializeInternalFieldsCallback());
|
||||
partial_serializer.Serialize(&raw_context, false);
|
||||
startup_serializer.SerializeWeakReferencesAndDeferred();
|
||||
|
||||
@ -419,7 +425,9 @@ UNINITIALIZED_TEST(PartialSerializerContext) {
|
||||
{
|
||||
SnapshotData snapshot_data(partial_blob);
|
||||
Deserializer deserializer(&snapshot_data);
|
||||
root = deserializer.DeserializePartial(isolate, global_proxy, nullptr)
|
||||
root = deserializer
|
||||
.DeserializePartial(isolate, global_proxy,
|
||||
v8::DeserializeInternalFieldsCallback())
|
||||
.ToHandleChecked();
|
||||
CHECK(root->IsContext());
|
||||
CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
|
||||
@ -429,7 +437,9 @@ UNINITIALIZED_TEST(PartialSerializerContext) {
|
||||
{
|
||||
SnapshotData snapshot_data(partial_blob);
|
||||
Deserializer deserializer(&snapshot_data);
|
||||
root2 = deserializer.DeserializePartial(isolate, global_proxy, nullptr)
|
||||
root2 = deserializer
|
||||
.DeserializePartial(isolate, global_proxy,
|
||||
v8::DeserializeInternalFieldsCallback())
|
||||
.ToHandleChecked();
|
||||
CHECK(root2->IsContext());
|
||||
CHECK(!root.is_identical_to(root2));
|
||||
@ -505,7 +515,8 @@ static void PartiallySerializeCustomContext(
|
||||
startup_serializer.SerializeStrongReferences();
|
||||
|
||||
SnapshotByteSink partial_sink;
|
||||
PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr);
|
||||
PartialSerializer partial_serializer(isolate, &startup_serializer,
|
||||
v8::SerializeInternalFieldsCallback());
|
||||
partial_serializer.Serialize(&raw_context, false);
|
||||
startup_serializer.SerializeWeakReferencesAndDeferred();
|
||||
|
||||
@ -539,7 +550,9 @@ UNINITIALIZED_TEST(PartialSerializerCustomContext) {
|
||||
{
|
||||
SnapshotData snapshot_data(partial_blob);
|
||||
Deserializer deserializer(&snapshot_data);
|
||||
root = deserializer.DeserializePartial(isolate, global_proxy, nullptr)
|
||||
root = deserializer
|
||||
.DeserializePartial(isolate, global_proxy,
|
||||
v8::DeserializeInternalFieldsCallback())
|
||||
.ToHandleChecked();
|
||||
CHECK(root->IsContext());
|
||||
Handle<Context> context = Handle<Context>::cast(root);
|
||||
@ -2161,25 +2174,27 @@ struct InternalFieldData {
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder,
|
||||
int index) {
|
||||
InternalFieldData* data = static_cast<InternalFieldData*>(
|
||||
v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
void* data) {
|
||||
CHECK_EQ(reinterpret_cast<void*>(2016), data);
|
||||
InternalFieldData* internal_field = static_cast<InternalFieldData*>(
|
||||
holder->GetAlignedPointerFromInternalField(index));
|
||||
int size = sizeof(*data);
|
||||
int size = sizeof(*internal_field);
|
||||
char* payload = new char[size];
|
||||
// We simply use memcpy to serialize the content.
|
||||
memcpy(payload, data, size);
|
||||
memcpy(payload, internal_field, size);
|
||||
return {payload, size};
|
||||
}
|
||||
|
||||
std::vector<InternalFieldData*> deserialized_data;
|
||||
|
||||
void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
|
||||
v8::StartupData payload) {
|
||||
InternalFieldData* data = new InternalFieldData{0};
|
||||
memcpy(data, payload.data, payload.raw_size);
|
||||
holder->SetAlignedPointerInInternalField(index, data);
|
||||
deserialized_data.push_back(data);
|
||||
v8::StartupData payload, void* data) {
|
||||
CHECK_EQ(reinterpret_cast<void*>(2017), data);
|
||||
InternalFieldData* internal_field = new InternalFieldData{0};
|
||||
memcpy(internal_field, payload.data, payload.raw_size);
|
||||
holder->SetAlignedPointerInInternalField(index, internal_field);
|
||||
deserialized_data.push_back(internal_field);
|
||||
}
|
||||
|
||||
TEST(SnapshotCreatorTemplates) {
|
||||
@ -2231,7 +2246,10 @@ TEST(SnapshotCreatorTemplates) {
|
||||
c->SetInternalField(2, field_external);
|
||||
CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust());
|
||||
|
||||
CHECK_EQ(0u, creator.AddContext(context, SerializeInternalFields));
|
||||
CHECK_EQ(0u,
|
||||
creator.AddContext(context, v8::SerializeInternalFieldsCallback(
|
||||
SerializeInternalFields,
|
||||
reinterpret_cast<void*>(2016))));
|
||||
CHECK_EQ(0u, creator.AddTemplate(callback));
|
||||
CHECK_EQ(1u, creator.AddTemplate(global_template));
|
||||
}
|
||||
@ -2255,7 +2273,10 @@ TEST(SnapshotCreatorTemplates) {
|
||||
// Create a new context without a new object template.
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context =
|
||||
v8::Context::FromSnapshot(isolate, 0, DeserializeInternalFields)
|
||||
v8::Context::FromSnapshot(
|
||||
isolate, 0,
|
||||
v8::DeserializeInternalFieldsCallback(
|
||||
DeserializeInternalFields, reinterpret_cast<void*>(2017)))
|
||||
.ToLocalChecked();
|
||||
v8::Context::Scope context_scope(context);
|
||||
ExpectInt32("f()", 42);
|
||||
@ -2408,7 +2429,10 @@ TEST(SnapshotCreatorIncludeGlobalProxy) {
|
||||
.ToLocalChecked())
|
||||
.FromJust());
|
||||
|
||||
CHECK_EQ(0u, creator.AddContext(context, SerializeInternalFields));
|
||||
CHECK_EQ(0u,
|
||||
creator.AddContext(context, v8::SerializeInternalFieldsCallback(
|
||||
SerializeInternalFields,
|
||||
reinterpret_cast<void*>(2016))));
|
||||
}
|
||||
blob =
|
||||
creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
|
||||
@ -2452,8 +2476,12 @@ TEST(SnapshotCreatorIncludeGlobalProxy) {
|
||||
// will use the global object from the snapshot, including interceptor.
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context =
|
||||
v8::Context::FromSnapshot(isolate, 0, DeserializeInternalFields)
|
||||
v8::Context::FromSnapshot(
|
||||
isolate, 0,
|
||||
v8::DeserializeInternalFieldsCallback(
|
||||
DeserializeInternalFields, reinterpret_cast<void*>(2017)))
|
||||
.ToLocalChecked();
|
||||
|
||||
{
|
||||
v8::Context::Scope context_scope(context);
|
||||
ExpectInt32("f()", 42);
|
||||
@ -2480,8 +2508,11 @@ TEST(SnapshotCreatorIncludeGlobalProxy) {
|
||||
// New context, but reuse global proxy.
|
||||
v8::ExtensionConfiguration* no_extensions = nullptr;
|
||||
v8::Local<v8::Context> context2 =
|
||||
v8::Context::FromSnapshot(isolate, 0, DeserializeInternalFields,
|
||||
no_extensions, global)
|
||||
v8::Context::FromSnapshot(
|
||||
isolate, 0,
|
||||
v8::DeserializeInternalFieldsCallback(
|
||||
DeserializeInternalFields, reinterpret_cast<void*>(2017)),
|
||||
no_extensions, global)
|
||||
.ToLocalChecked();
|
||||
{
|
||||
v8::Context::Scope context_scope(context2);
|
||||
|
Loading…
Reference in New Issue
Block a user