Commit fd004c04 authored by Yutaka Hirano's avatar Yutaka Hirano Committed by Commit Bot

Introduce Readable|WritableTransferringOptimizer

This CL introduces ReadableTransferringOptimizer and
WritableTransferringOptimizer for the Transferable Streams optimization
described in the following design doc.

https://docs.google.com/document/d/19WpamKCysWHYGA6jIrlwZIYxhBrsHCDHYNd98Zl1u5w

This CL doesn't change the behavior.

Bug: 1146396
Change-Id: If19841e27594fa43442f24805e380b23bb0abb67
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2522805Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarAdam Rice <ricea@chromium.org>
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825800}
parent cb858941
......@@ -452,7 +452,7 @@ void SerializedScriptValue::TransferTransformStreams(
}
}
// Creates an entangled pair of channels. Adds one end to |stream_channels_| as
// Creates an entangled pair of channels. Adds one end to |streams_| as
// a MessagePortChannel, and returns the other end as a MessagePort.
MessagePort* SerializedScriptValue::AddStreamChannel(
ExecutionContext* execution_context) {
......@@ -468,7 +468,7 @@ MessagePort* SerializedScriptValue::AddStreamChannel(
// 9. Set dataHolder.[[port]] to ! StructuredSerializeWithTransfer(port2,
// « port2 »).
stream_channels_.push_back(MessagePortChannel(pipe.TakePort1()));
streams_.push_back(Stream(pipe.TakePort1()));
return local_port;
}
......
......@@ -37,11 +37,14 @@
#include "base/optional.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/transferables.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/mojo/mojo_handle.h"
#include "third_party/blink/renderer/core/streams/readable_stream_transferring_optimizer.h"
#include "third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
......@@ -73,11 +76,32 @@ class CORE_EXPORT SerializedScriptValue
USING_FAST_MALLOC(SerializedScriptValue);
public:
class Stream final {
DISALLOW_NEW();
public:
explicit Stream(MessagePortDescriptor descriptor)
: channel(std::move(descriptor)) {}
Stream(MessagePortDescriptor descriptor,
std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer)
: channel(std::move(descriptor)),
readable_optimizer(std::move(optimizer)) {}
Stream(MessagePortDescriptor descriptor,
std::unique_ptr<WritableStreamTransferringOptimizer> optimizer)
: channel(std::move(descriptor)),
writable_optimizer(std::move(optimizer)) {}
MessagePortChannel channel;
std::unique_ptr<ReadableStreamTransferringOptimizer> readable_optimizer;
std::unique_ptr<WritableStreamTransferringOptimizer> writable_optimizer;
};
using ArrayBufferContentsArray = Vector<ArrayBufferContents, 1>;
using SharedArrayBufferContentsArray = Vector<ArrayBufferContents, 1>;
using ImageBitmapContentsArray = Vector<scoped_refptr<StaticBitmapImage>, 1>;
using TransferredWasmModulesArray = WTF::Vector<v8::CompiledWasmModule>;
using MessagePortChannelArray = Vector<MessagePortChannel>;
using StreamArray = Vector<Stream>;
using NativeFileSystemTokensArray =
Vector<mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>>;
......@@ -266,7 +290,7 @@ class CORE_EXPORT SerializedScriptValue
}
void SetImageBitmapContentsArray(ImageBitmapContentsArray contents);
MessagePortChannelArray& GetStreamChannels() { return stream_channels_; }
StreamArray& GetStreams() { return streams_; }
bool IsLockedToAgentCluster() const {
return !wasm_modules_.IsEmpty() ||
......@@ -363,9 +387,9 @@ class CORE_EXPORT SerializedScriptValue
ArrayBufferContentsArray array_buffer_contents_array_;
ImageBitmapContentsArray image_bitmap_contents_array_;
// |stream_channels_| is also single-use but is special-cased because it works
// |streams_| is also single-use but is special-cased because it works
// with ServiceWorkers.
MessagePortChannelArray stream_channels_;
StreamArray streams_;
// These do not have one-use transferred contents, like the above.
TransferredWasmModulesArray wasm_modules_;
......
......@@ -183,9 +183,12 @@ void V8ScriptValueDeserializer::Transfer() {
// TODO(ricea): Make ExtendableMessageEvent store an
// UnpackedSerializedScriptValue like MessageEvent does, and then this
// special case won't be necessary.
Vector<MessagePortChannel> channels;
for (auto& stream : serialized_script_value_->GetStreams()) {
channels.push_back(stream.channel);
}
transferred_stream_ports_ = MessagePort::EntanglePorts(
*ExecutionContext::From(script_state_),
serialized_script_value_->GetStreamChannels());
*ExecutionContext::From(script_state_), channels);
}
// There's nothing else to transfer if the deserializer was not given an
......
......@@ -1934,8 +1934,8 @@ TEST(V8ScriptValueSerializerTest, TransformStreamIntegerOverflow) {
auto corrupted_serialized_script_value =
SerializedScriptValue::Create(serialized_value, sizeof(serialized_value));
corrupted_serialized_script_value->GetStreamChannels() =
serialized_script_value->GetStreamChannels();
corrupted_serialized_script_value->GetStreams() =
std::move(serialized_script_value->GetStreams());
// Entangle the message ports.
MessagePortArray* transferred_message_ports = MessagePort::EntanglePorts(
......
......@@ -57,9 +57,9 @@ BlinkTransferableMessage BlinkTransferableMessage::FromMessageEvent(
}
// Stream channels.
auto& stream_channels = serialized_script_value->GetStreamChannels();
result.message->GetStreamChannels().AppendRange(stream_channels.begin(),
stream_channels.end());
for (auto& stream : serialized_script_value->GetStreams()) {
result.message->GetStreams().push_back(std::move(stream));
}
// Array buffer contents array.
auto& source_array_buffer_contents_array =
serialized_script_value->GetArrayBufferContentsArray();
......@@ -149,8 +149,10 @@ BlinkTransferableMessage BlinkTransferableMessage::FromTransferableMessage(
message.stack_trace_should_pause);
result.locked_agent_cluster_id = message.locked_agent_cluster_id;
result.ports.AppendRange(message.ports.begin(), message.ports.end());
result.message->GetStreamChannels().AppendRange(
message.stream_channels.begin(), message.stream_channels.end());
for (auto& channel : message.stream_channels) {
result.message->GetStreams().push_back(
SerializedScriptValue::Stream(channel.ReleaseHandle()));
}
if (message.user_activation) {
result.user_activation = mojom::blink::UserActivationSnapshot::New(
message.user_activation->has_been_active,
......
......@@ -48,9 +48,10 @@ bool StructTraits<blink::mojom::blink::TransferableMessage::DataView,
out->ports.ReserveInitialCapacity(ports.size());
out->ports.AppendRange(std::make_move_iterator(ports.begin()),
std::make_move_iterator(ports.end()));
out->message->GetStreamChannels().AppendRange(
std::make_move_iterator(stream_channels.begin()),
std::make_move_iterator(stream_channels.end()));
for (auto& channel : stream_channels) {
out->message->GetStreams().push_back(
blink::SerializedScriptValue::Stream(std::move(channel)));
}
out->message->SetArrayBufferContentsArray(
std::move(array_buffer_contents_array));
......
......@@ -38,10 +38,10 @@ struct CORE_EXPORT StructTraits<blink::mojom::TransferableMessageDataView,
static Vector<blink::MessagePortDescriptor> stream_channels(
blink::BlinkTransferableMessage& input) {
Vector<blink::MessagePortDescriptor> result;
auto& stream_channels = input.message->GetStreamChannels();
result.ReserveInitialCapacity(stream_channels.size());
for (const auto& port : stream_channels)
result.push_back(port.ReleaseHandle());
auto& streams = input.message->GetStreams();
result.ReserveInitialCapacity(streams.size());
for (const auto& stream : streams)
result.push_back(stream.channel.ReleaseHandle());
return result;
}
......
......@@ -30,6 +30,7 @@ blink_core_sources_streams = [
"readable_stream_default_reader.h",
"readable_stream_reader.cc",
"readable_stream_reader.h",
"readable_stream_transferring_optimizer.h",
"stream_algorithms.h",
"stream_promise_resolver.cc",
"stream_promise_resolver.h",
......@@ -49,4 +50,5 @@ blink_core_sources_streams = [
"writable_stream_default_controller.h",
"writable_stream_default_writer.cc",
"writable_stream_default_writer.h",
"writable_stream_transferring_optimizer.h",
]
// Copyright 2020 The Chromium AUthors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_TRANSFERRING_OPTIMIZER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_TRANSFERRING_OPTIMIZER_H_
#include "third_party/blink/renderer/core/core_export.h"
namespace blink {
class UnderlyingSourceBase;
class ScriptState;
// ReadableStreamTransferringOptimizer is the base class used to optimize
// transferring a ReadableStream. Please see
// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/.
//
// A ReadableStreamTransferringOptimizer is associated with the source of a
// ReadableStream. When transferring the stream in another realm, the optimizer
// is used to construct the transferred stream in the destination realm. Note
// that two realms can be in different threads (in the same process), in which
// case the optimizer is used across threads.
class CORE_EXPORT ReadableStreamTransferringOptimizer {
USING_FAST_MALLOC(ReadableStreamTransferringOptimizer);
public:
ReadableStreamTransferringOptimizer() = default;
ReadableStreamTransferringOptimizer(
const ReadableStreamTransferringOptimizer&) = delete;
ReadableStreamTransferringOptimizer& operator=(
const ReadableStreamTransferringOptimizer&) = delete;
virtual ~ReadableStreamTransferringOptimizer() = default;
// Returns an UnderlyingSourceBase for the associated source. This method may
// return null, in which case it is no-op.
// This method can be called at most once.
virtual UnderlyingSourceBase* PerformInProcessOptimization(
ScriptState* script_state) {
return nullptr;
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_TRANSFERRING_OPTIMIZER_H_
// Copyright 2020 The Chromium AUthors. All rights reserved.
// Use of this sink code is governed by a BSD-style license that can be found
// in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_TRANSFERRING_OPTIMIZER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_TRANSFERRING_OPTIMIZER_H_
#include "third_party/blink/renderer/core/core_export.h"
namespace blink {
class UnderlyingSinkBase;
class ScriptState;
// WritableStreamTransferringOptimizer is the base class used to optimize
// transferring a WritableStream. Please see
// https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/.
//
// A WritableStreamTransferringOptimizer is associated with the sink of a
// WritableStream. When transferring the stream in another realm, the optimizer
// is used to construct the transferred stream in the destination realm. Note
// that two realms can be in different threads (in the same process), in which
// case the optimizer is used across threads.
class CORE_EXPORT WritableStreamTransferringOptimizer {
USING_FAST_MALLOC(WritableStreamTransferringOptimizer);
public:
WritableStreamTransferringOptimizer() = default;
WritableStreamTransferringOptimizer(
const WritableStreamTransferringOptimizer&) = delete;
WritableStreamTransferringOptimizer& operator=(
const WritableStreamTransferringOptimizer&) = delete;
virtual ~WritableStreamTransferringOptimizer() = default;
// Returns an UnderlyingSinkBase for the associated sink. This method may
// return null, in which case it is no-op.
// This method can be called at most once.
virtual UnderlyingSinkBase* PerformInProcessOptimization(
ScriptState* script_state) {
return nullptr;
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_TRANSFERRING_OPTIMIZER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment