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 { ...@@ -3469,7 +3469,7 @@ class V8_EXPORT WasmCompiledModule : public Object {
SerializedModule Serialize(); SerializedModule Serialize();
static MaybeLocal<WasmCompiledModule> Deserialize( static MaybeLocal<WasmCompiledModule> Deserialize(
Isolate* isolate, const SerializedModule serialized_data); Isolate* isolate, const SerializedModule& serialized_data);
V8_INLINE static WasmCompiledModule* Cast(Value* obj); V8_INLINE static WasmCompiledModule* Cast(Value* obj);
private: private:
......
...@@ -6833,14 +6833,14 @@ WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() { ...@@ -6833,14 +6833,14 @@ WasmCompiledModule::SerializedModule WasmCompiledModule::Serialize() {
std::unique_ptr<i::ScriptData> script_data = std::unique_ptr<i::ScriptData> script_data =
i::WasmCompiledModuleSerializer::SerializeWasmModule(obj->GetIsolate(), i::WasmCompiledModuleSerializer::SerializeWasmModule(obj->GetIsolate(),
compiled_part); compiled_part);
script_data->ReleaseDataOwnership();
size_t size = static_cast<size_t>(script_data->length()); size_t size = static_cast<size_t>(script_data->length());
script_data.release();
return {std::unique_ptr<const uint8_t[]>(script_data->data()), size}; return {std::unique_ptr<const uint8_t[]>(script_data->data()), size};
} }
MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize( MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
Isolate* isolate, Isolate* isolate,
const WasmCompiledModule::SerializedModule serialized_data) { const WasmCompiledModule::SerializedModule& serialized_data) {
int size = static_cast<int>(serialized_data.second); int size = static_cast<int>(serialized_data.second);
i::ScriptData sc(serialized_data.first.get(), size); i::ScriptData sc(serialized_data.first.get(), size);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
......
...@@ -1628,10 +1628,16 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, ...@@ -1628,10 +1628,16 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
Handle<JSArrayBuffer>::null()) Handle<JSArrayBuffer>::null())
.ToHandleChecked(); .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<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
Handle<JSObject> exports_object = Handle<JSObject>::cast( Handle<JSObject> exports_object = Handle<JSObject>::cast(
JSObject::GetProperty(instance, exports).ToHandleChecked()); JSObject::GetProperty(instance, exports).ToHandleChecked());
Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main"); Handle<Name> main_name = isolate->factory()->NewStringFromAsciiChecked(name);
PropertyDescriptor desc; PropertyDescriptor desc;
Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor( Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
isolate, exports_object, main_name, &desc); isolate, exports_object, main_name, &desc);
...@@ -1642,11 +1648,11 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, ...@@ -1642,11 +1648,11 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
// Call the JS function. // Call the JS function.
Handle<Object> undefined = isolate->factory()->undefined_value(); Handle<Object> undefined = isolate->factory()->undefined_value();
MaybeHandle<Object> retval = 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. // The result should be a number.
if (retval.is_null()) { if (retval.is_null()) {
thrower.Error("WASM.compileRun() failed: Invocation was null"); thrower->Error("WASM.compileRun() failed: Invocation was null");
return -1; return -1;
} }
Handle<Object> result = retval.ToHandleChecked(); Handle<Object> result = retval.ToHandleChecked();
...@@ -1656,7 +1662,7 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, ...@@ -1656,7 +1662,7 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
if (result->IsHeapNumber()) { if (result->IsHeapNumber()) {
return static_cast<int32_t>(HeapNumber::cast(*result)->value()); 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; return -1;
} }
......
...@@ -408,6 +408,9 @@ namespace testing { ...@@ -408,6 +408,9 @@ namespace testing {
int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
const byte* module_end, bool asm_js = false); 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 testing
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <string.h> #include <string.h>
#include "src/wasm/encoder.h" #include "src/wasm/encoder.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-js.h" #include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-macro-gen.h" #include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h" #include "src/wasm/wasm-module.h"
...@@ -33,11 +34,16 @@ void TestModule(Zone* zone, WasmModuleBuilder* builder, ...@@ -33,11 +34,16 @@ void TestModule(Zone* zone, WasmModuleBuilder* builder,
CHECK_EQ(expected_result, result); 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) { void ExportAsMain(WasmFunctionBuilder* f) {
static const char kMainName[] = "main"; static const char kMainName[] = "main";
f->SetExported(); ExportAs(f, kMainName);
f->SetName(kMainName, arraysize(kMainName) - 1);
} }
} // namespace } // namespace
TEST(Run_WasmModule_Return114) { TEST(Run_WasmModule_Return114) {
...@@ -174,3 +180,79 @@ TEST(Run_WasmModule_Global) { ...@@ -174,3 +180,79 @@ TEST(Run_WasmModule_Global) {
f->EmitCode(code2, sizeof(code2)); f->EmitCode(code2, sizeof(code2));
TestModule(&zone, builder, 97); 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