Commit 0686c414 authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] Serialization test using external APIs and contexts

A test exercising the public APIs for wasm serialization and
simulates the serialization scenario - serialize in one isolate, deserialize
in another.

BUG=v8:5072

Review-Url: https://codereview.chromium.org/2249973002
Cr-Commit-Position: refs/heads/master@{#38644}
parent 860a3ce2
......@@ -3469,7 +3469,7 @@ class V8_EXPORT WasmCompiledModule : public Object {
SerializedModule Serialize();
static MaybeLocal<WasmCompiledModule> Deserialize(
Isolate* isolate, const SerializedModule serialized_data);
Isolate* isolate, const SerializedModule& serialized_data);
V8_INLINE static WasmCompiledModule* Cast(Value* obj);
private:
......
......@@ -6833,14 +6833,14 @@ WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
std::unique_ptr<i::ScriptData> script_data =
i::WasmCompiledModuleSerializer::SerializeWasmModule(obj->GetIsolate(),
compiled_part);
script_data->ReleaseDataOwnership();
size_t size = static_cast<size_t>(script_data->length());
script_data.release();
return {std::unique_ptr<const uint8_t[]>(script_data->data()), size};
}
MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
Isolate* isolate,
const WasmCompiledModule::SerializedModule serialized_data) {
const WasmCompiledModule::SerializedModule& serialized_data) {
int size = static_cast<int>(serialized_data.second);
i::ScriptData sc(serialized_data.first.get(), size);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
......
......@@ -1628,10 +1628,16 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
Handle<JSArrayBuffer>::null())
.ToHandleChecked();
return CallFunction(isolate, instance, &thrower, "main", 0, nullptr);
}
int32_t CallFunction(Isolate* isolate, Handle<JSObject> instance,
ErrorThrower* thrower, const char* name, int argc,
Handle<Object> argv[]) {
Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
Handle<JSObject> exports_object = Handle<JSObject>::cast(
JSObject::GetProperty(instance, exports).ToHandleChecked());
Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main");
Handle<Name> main_name = isolate->factory()->NewStringFromAsciiChecked(name);
PropertyDescriptor desc;
Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
isolate, exports_object, main_name, &desc);
......@@ -1642,11 +1648,11 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
// Call the JS function.
Handle<Object> undefined = isolate->factory()->undefined_value();
MaybeHandle<Object> retval =
Execution::Call(isolate, main_export, undefined, 0, nullptr);
Execution::Call(isolate, main_export, undefined, argc, argv);
// The result should be a number.
if (retval.is_null()) {
thrower.Error("WASM.compileRun() failed: Invocation was null");
thrower->Error("WASM.compileRun() failed: Invocation was null");
return -1;
}
Handle<Object> result = retval.ToHandleChecked();
......@@ -1656,7 +1662,7 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
if (result->IsHeapNumber()) {
return static_cast<int32_t>(HeapNumber::cast(*result)->value());
}
thrower.Error("WASM.compileRun() failed: Return value should be number");
thrower->Error("WASM.compileRun() failed: Return value should be number");
return -1;
}
......
......@@ -408,6 +408,9 @@ namespace testing {
int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
const byte* module_end, bool asm_js = false);
int32_t CallFunction(Isolate* isolate, Handle<JSObject> instance,
ErrorThrower* thrower, const char* name, int argc,
Handle<Object> argv[]);
} // namespace testing
} // namespace wasm
} // namespace internal
......
......@@ -6,6 +6,7 @@
#include <string.h>
#include "src/wasm/encoder.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h"
......@@ -33,11 +34,16 @@ void TestModule(Zone* zone, WasmModuleBuilder* builder,
CHECK_EQ(expected_result, result);
}
void ExportAs(WasmFunctionBuilder* f, const char* name) {
f->SetExported();
f->SetName(name, static_cast<int>(strlen(name)));
}
void ExportAsMain(WasmFunctionBuilder* f) {
static const char kMainName[] = "main";
f->SetExported();
f->SetName(kMainName, arraysize(kMainName) - 1);
ExportAs(f, kMainName);
}
} // namespace
TEST(Run_WasmModule_Return114) {
......@@ -174,3 +180,79 @@ TEST(Run_WasmModule_Global) {
f->EmitCode(code2, sizeof(code2));
TestModule(&zone, builder, 97);
}
TEST(Run_WasmModule_Serialization) {
FLAG_expose_wasm = true;
static const char* kFunctionName = "increment";
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
TestSignatures sigs;
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->SetSignature(sigs.i_i());
byte code[] = {WASM_GET_LOCAL(0), kExprI32Const, 1, kExprI32Add};
f->EmitCode(code, sizeof(code));
ExportAs(f, kFunctionName);
ZoneBuffer buffer(&zone);
builder->WriteTo(buffer);
Isolate* isolate = CcTest::InitIsolateOnce();
ErrorThrower thrower(isolate, "");
v8::WasmCompiledModule::SerializedModule data;
{
HandleScope scope(isolate);
ModuleResult decoding_result = DecodeWasmModule(
isolate, &zone, buffer.begin(), buffer.end(), false, kWasmOrigin);
std::unique_ptr<const WasmModule> module(decoding_result.val);
CHECK(!decoding_result.failed());
MaybeHandle<FixedArray> compiled_module =
module->CompileFunctions(isolate, &thrower);
CHECK(!compiled_module.is_null());
Handle<JSObject> module_obj =
CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked());
v8::Local<v8::Object> v8_module_obj = v8::Utils::ToLocal(module_obj);
CHECK(v8_module_obj->IsWebAssemblyCompiledModule());
v8::Local<v8::WasmCompiledModule> v8_compiled_module =
v8_module_obj.As<v8::WasmCompiledModule>();
data = v8_compiled_module->Serialize();
}
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = isolate->array_buffer_allocator();
v8::Isolate* v8_isolate = v8::Isolate::New(create_params);
isolate = reinterpret_cast<Isolate*>(v8_isolate);
{
v8::Isolate::Scope isolate_scope(v8_isolate);
v8::HandleScope new_scope(v8_isolate);
v8::Local<v8::Context> new_ctx = v8::Context::New(v8_isolate);
new_ctx->Enter();
v8::MaybeLocal<v8::WasmCompiledModule> deserialized =
v8::WasmCompiledModule::Deserialize(v8_isolate, data);
v8::Local<v8::WasmCompiledModule> compiled_module;
CHECK(deserialized.ToLocal(&compiled_module));
Handle<JSObject> module_object =
Handle<JSObject>::cast(v8::Utils::OpenHandle(*compiled_module));
Handle<FixedArray> compiled_part =
handle(FixedArray::cast(module_object->GetInternalField(0)));
Handle<JSObject> instance =
WasmModule::Instantiate(isolate, compiled_part,
Handle<JSReceiver>::null(),
Handle<JSArrayBuffer>::null())
.ToHandleChecked();
Handle<Object> params[1] = {Handle<Object>(Smi::FromInt(41), isolate)};
int32_t result = testing::CallFunction(isolate, instance, &thrower,
kFunctionName, 1, params);
CHECK(result == 42);
new_ctx->Exit();
}
}
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