Commit 78905107 authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] Skeleton WasmModuleObjectBuilder for streamed compilation

APIs and trivial implementation, to unblock Chrome side dev.

BUG=chromium:697028

Review-Url: https://codereview.chromium.org/2763413003
Cr-Commit-Position: refs/heads/master@{#44053}
parent 06a551ae
......@@ -3914,6 +3914,8 @@ class V8_EXPORT Proxy : public Object {
static void CheckCast(Value* obj);
};
// TODO(mtrofin): rename WasmCompiledModule to WasmModuleObject, for
// consistency with internal APIs.
class V8_EXPORT WasmCompiledModule : public Object {
public:
typedef std::pair<std::unique_ptr<const uint8_t[]>, size_t> SerializedModule;
......@@ -3965,6 +3967,10 @@ class V8_EXPORT WasmCompiledModule : public Object {
V8_INLINE static WasmCompiledModule* Cast(Value* obj);
private:
// TODO(ahaas): please remove the friend once streamed compilation is
// implemented
friend class WasmModuleObjectBuilder;
static MaybeLocal<WasmCompiledModule> Deserialize(
Isolate* isolate, const CallerOwnedBuffer& serialized_module,
const CallerOwnedBuffer& wire_bytes);
......@@ -3980,6 +3986,29 @@ class V8_EXPORT WasmCompiledModule : public Object {
static void CheckCast(Value* obj);
};
class V8_EXPORT WasmModuleObjectBuilder final {
public:
WasmModuleObjectBuilder(Isolate* isolate) : isolate_(isolate) {}
void OnBytesReceived(std::unique_ptr<const uint8_t[]>&& bytes, size_t size);
MaybeLocal<WasmCompiledModule> Finish();
private:
Isolate* isolate_ = nullptr;
// TODO(ahaas): We probably need none of this below here once streamed
// compilation is implemented.
typedef std::pair<std::unique_ptr<const uint8_t[]>, size_t> Buffer;
// Disable copy semantics *in this implementation*. We can choose to
// relax this, albeit it's not clear why.
WasmModuleObjectBuilder(const WasmModuleObjectBuilder&) = delete;
WasmModuleObjectBuilder(WasmModuleObjectBuilder&&) = default;
WasmModuleObjectBuilder& operator=(const WasmModuleObjectBuilder&) = delete;
WasmModuleObjectBuilder& operator=(WasmModuleObjectBuilder&&) = default;
std::vector<Buffer> received_buffers_;
size_t total_size_ = 0;
};
#ifndef V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT
// The number of required internal fields can be defined by embedder.
#define V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT 2
......
......@@ -7615,6 +7615,24 @@ MaybeLocal<WasmCompiledModule> WasmCompiledModule::Compile(Isolate* isolate,
Utils::ToLocal(maybe_compiled.ToHandleChecked()));
}
void WasmModuleObjectBuilder::OnBytesReceived(
std::unique_ptr<const uint8_t[]>&& bytes, size_t size) {
received_buffers_.push_back(Buffer(std::move(bytes), size));
total_size_ += size;
}
MaybeLocal<WasmCompiledModule> WasmModuleObjectBuilder::Finish() {
std::unique_ptr<uint8_t[]> wire_bytes(new uint8_t[total_size_]);
uint8_t* insert_at = wire_bytes.get();
for (size_t i = 0; i < received_buffers_.size(); ++i) {
const Buffer& buff = received_buffers_[i];
memcpy(insert_at, buff.first.get(), buff.second);
insert_at += buff.second;
}
return WasmCompiledModule::Compile(isolate_, wire_bytes.get(), total_size_);
}
// static
v8::ArrayBuffer::Allocator* v8::ArrayBuffer::Allocator::NewDefaultAllocator() {
return new ArrayBufferAllocator();
......
......@@ -437,6 +437,67 @@ TEST(DeserializeWireBytesAndSerializedDataInvalid) {
Cleanup();
}
std::unique_ptr<const uint8_t[]> CreatePayload(const uint8_t* start,
size_t size) {
uint8_t* ret = new uint8_t[size];
memcpy(ret, start, size);
return std::unique_ptr<const uint8_t[]>(const_cast<const uint8_t*>(ret));
}
TEST(ModuleBuilder) {
v8::internal::AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneBuffer buffer(&zone);
WasmSerializationTest::BuildWireBytes(&zone, &buffer);
CHECK_GT(buffer.size(), 0);
size_t third = buffer.size() / 3;
size_t first_mark = third - 2;
size_t second_mark = buffer.size() - 2 - third;
CHECK(0 < first_mark);
CHECK(first_mark < second_mark);
CHECK(second_mark < buffer.size());
Isolate* i_isolate = CcTest::InitIsolateOnce();
v8::WasmModuleObjectBuilder builder(CcTest::isolate());
std::unique_ptr<const uint8_t[]> first_part =
CreatePayload(buffer.begin(), first_mark);
std::unique_ptr<const uint8_t[]> second_part =
CreatePayload(buffer.begin() + first_mark, second_mark - first_mark);
std::unique_ptr<const uint8_t[]> third_part =
CreatePayload(buffer.begin() + second_mark, buffer.size() - second_mark);
builder.OnBytesReceived(std::move(first_part), first_mark);
builder.OnBytesReceived(std::move(second_part), second_mark - first_mark);
builder.OnBytesReceived(std::move(third_part), buffer.size() - second_mark);
{
HandleScope scope(i_isolate);
v8::MaybeLocal<v8::WasmCompiledModule> maybe_module = builder.Finish();
CHECK(!maybe_module.IsEmpty());
}
}
TEST(FailingModuleBuilder) {
v8::internal::AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneBuffer buffer(&zone);
WasmSerializationTest::BuildWireBytes(&zone, &buffer);
CHECK_GT(buffer.size(), 0);
size_t third = buffer.size() / 3;
size_t first_mark = third - 2;
size_t second_mark = buffer.size() - 2 - third;
CHECK(0 < first_mark);
CHECK(first_mark < second_mark);
CHECK(second_mark < buffer.size());
Isolate* i_isolate = CcTest::InitIsolateOnce();
v8::WasmModuleObjectBuilder builder(CcTest::isolate());
std::unique_ptr<const uint8_t[]> first_part =
CreatePayload(buffer.begin(), first_mark);
builder.OnBytesReceived(std::move(first_part), first_mark);
{
HandleScope scope(i_isolate);
v8::MaybeLocal<v8::WasmCompiledModule> maybe_module = builder.Finish();
CHECK(maybe_module.IsEmpty());
}
}
bool False(v8::Local<v8::Context> context) { return false; }
TEST(BlockWasmCodeGen) {
......
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