Commit 0b98dbcc authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] Consolidate CompileAndRunWasmModule

Remove second wasm module compilation and instantiation path that
we had in CompileAndRunWasmModule and reuse the same path used
by user code.

BUG=

Review-Url: https://codereview.chromium.org/2091533002
Cr-Commit-Position: refs/heads/master@{#37203}
parent 2601900d
......@@ -966,106 +966,6 @@ compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone,
return GetWasmCallDescriptor(zone, function->sig);
}
int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
const byte* module_end, bool asm_js) {
HandleScope scope(isolate);
Zone zone(isolate->allocator());
// Decode the module, but don't verify function bodies, since we'll
// be compiling them anyway.
ModuleResult result =
DecodeWasmModule(isolate, &zone, module_start, module_end, false,
asm_js ? kAsmJsOrigin : kWasmOrigin);
if (result.failed()) {
if (result.val) {
delete result.val;
}
// Module verification failed. throw.
std::ostringstream str;
str << "WASM.compileRun() failed: " << result;
isolate->Throw(
*isolate->factory()->NewStringFromAsciiChecked(str.str().c_str()));
return -1;
}
int32_t retval = CompileAndRunWasmModule(isolate, result.val);
delete result.val;
return retval;
}
int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module) {
ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
WasmModuleInstance instance(module);
Handle<FixedArray> code_table = module->CompileFunctions(isolate);
if (code_table.is_null()) return -1;
for (uint32_t i = 0; i < module->functions.size(); ++i) {
Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i)));
instance.function_code[i] = code;
}
// Allocate and initialize the linear memory.
if (!AllocateMemory(&thrower, isolate, &instance)) {
return -1;
}
LoadDataSegments(module, instance.mem_start, instance.mem_size);
// Allocate the globals area if necessary.
if (!AllocateGlobals(&thrower, isolate, &instance)) {
return -1;
}
ModuleEnv module_env;
module_env.module = module;
module_env.instance = &instance;
module_env.origin = module->origin;
InitializePlaceholders(isolate->factory(), &module_env.placeholders,
module->functions.size());
if (module->export_table.size() == 0) {
thrower.Error("WASM.compileRun() failed: no exported functions");
return -2;
}
// Compile all functions.
for (const WasmFunction& func : module->functions) {
// Compile the function and install it in the linker.
Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction(
&thrower, isolate, &module_env, &func);
if (!code.is_null()) instance.function_code[func.func_index] = code;
if (thrower.error()) return -1;
}
LinkModuleFunctions(isolate, instance.function_code);
// Wrap the main code so it can be called as a JS function.
uint32_t main_index = module->export_table.back().func_index;
Handle<Code> main_code = instance.function_code[main_index];
Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper(
isolate, &module_env, name, main_code, module_object, main_index);
// Call the JS function.
Handle<Object> undefined = isolate->factory()->undefined_value();
MaybeHandle<Object> retval =
Execution::Call(isolate, jsfunc, undefined, 0, nullptr);
// The result should be a number.
if (retval.is_null()) {
thrower.Error("WASM.compileRun() failed: Invocation was null");
return -1;
}
Handle<Object> result = retval.ToHandleChecked();
if (result->IsSmi()) {
return Smi::cast(*result)->value();
}
if (result->IsHeapNumber()) {
return static_cast<int32_t>(HeapNumber::cast(*result)->value());
}
thrower.Error("WASM.compileRun() failed: Return value should be number");
return -1;
}
Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm,
uint32_t func_index) {
if (!wasm->IsUndefined(isolate)) {
......@@ -1126,6 +1026,74 @@ WasmDebugInfo* GetDebugInfo(JSObject* wasm) {
return *new_info;
}
namespace testing {
int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
const byte* module_end, bool asm_js) {
HandleScope scope(isolate);
Zone zone(isolate->allocator());
ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
// Decode the module, but don't verify function bodies, since we'll
// be compiling them anyway.
ModuleResult decoding_result =
DecodeWasmModule(isolate, &zone, module_start, module_end, false,
asm_js ? kAsmJsOrigin : kWasmOrigin);
if (decoding_result.failed()) {
// Module verification failed. throw.
thrower.Error("WASM.compileRun() failed: %s",
decoding_result.error_msg.get());
}
std::unique_ptr<const WasmModule> module(decoding_result.val);
if (module->import_table.size() > 0) {
thrower.Error("Not supported: module has imports.");
}
if (module->export_table.size() == 0) {
thrower.Error("Not supported: module has no exports.");
}
if (thrower.error()) return -1;
Handle<JSObject> instance =
module
->Instantiate(isolate, Handle<JSReceiver>::null(),
Handle<JSArrayBuffer>::null())
.ToHandleChecked();
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");
PropertyDescriptor desc;
Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
isolate, exports_object, main_name, &desc);
if (!property_found.FromMaybe(false)) return -1;
Handle<JSFunction> main_export = Handle<JSFunction>::cast(desc.value());
// Call the JS function.
Handle<Object> undefined = isolate->factory()->undefined_value();
MaybeHandle<Object> retval =
Execution::Call(isolate, main_export, undefined, 0, nullptr);
// The result should be a number.
if (retval.is_null()) {
thrower.Error("WASM.compileRun() failed: Invocation was null");
return -1;
}
Handle<Object> result = retval.ToHandleChecked();
if (result->IsSmi()) {
return Smi::cast(*result)->value();
}
if (result->IsHeapNumber()) {
return static_cast<int32_t>(HeapNumber::cast(*result)->value());
}
thrower.Error("WASM.compileRun() failed: Return value should be number");
return -1;
}
} // namespace testing
} // namespace wasm
} // namespace internal
} // namespace v8
......@@ -335,15 +335,6 @@ typedef Result<WasmFunction*> FunctionResult;
typedef std::vector<std::pair<int, int>> FunctionOffsets;
typedef Result<FunctionOffsets> FunctionOffsetsResult;
// For testing. Decode, verify, and run the last exported function in the
// given encoded module.
int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
const byte* module_end, bool asm_js = false);
// For testing. Decode, verify, and run the last exported function in the
// given decoded module.
int32_t CompileAndRunWasmModule(Isolate* isolate, const WasmModule* module);
// Extract a function name from the given wasm object.
// Returns "<WASM UNNAMED>" if the function is unnamed or the name is not a
// valid UTF-8 string.
......@@ -370,6 +361,15 @@ WasmDebugInfo* GetDebugInfo(JSObject* wasm);
// else.
bool IsWasmObject(Object* object);
namespace testing {
// Decode, verify, and run the function labeled "main" in the
// given encoded module. The module should have no imports.
int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
const byte* module_end, bool asm_js = false);
} // namespace testing
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -29,9 +29,15 @@ void TestModule(Zone* zone, WasmModuleBuilder* builder,
HandleScope scope(isolate);
WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
int32_t result =
CompileAndRunWasmModule(isolate, buffer.begin(), buffer.end());
testing::CompileAndRunWasmModule(isolate, buffer.begin(), buffer.end());
CHECK_EQ(expected_result, result);
}
void ExportAsMain(WasmFunctionBuilder* f) {
static const char kMainName[] = "main";
f->SetExported();
f->SetName(kMainName, arraysize(kMainName) - 1);
}
} // namespace
TEST(Run_WasmModule_Return114) {
......@@ -44,7 +50,7 @@ TEST(Run_WasmModule_Return114) {
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->SetSignature(sigs.i_v());
f->SetExported();
ExportAsMain(f);
byte code[] = {WASM_I8(kReturnValue)};
f->EmitCode(code, sizeof(code));
TestModule(&zone, builder, kReturnValue);
......@@ -69,7 +75,7 @@ TEST(Run_WasmModule_CallAdd) {
f = builder->FunctionAt(f2_index);
f->SetSignature(sigs.i_v());
f->SetExported();
ExportAsMain(f);
byte code2[] = {WASM_CALL_FUNCTION2(f1_index, WASM_I8(77), WASM_I8(22))};
f->EmitCode(code2, sizeof(code2));
TestModule(&zone, builder, 99);
......@@ -86,7 +92,7 @@ TEST(Run_WasmModule_ReadLoadedDataSegment) {
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->SetSignature(sigs.i_v());
f->SetExported();
ExportAsMain(f);
byte code[] = {
WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kDataSegmentDest0))};
f->EmitCode(code, sizeof(code));
......@@ -108,7 +114,7 @@ TEST(Run_WasmModule_CheckMemoryIsZero) {
f->SetSignature(sigs.i_v());
uint16_t localIndex = f->AddLocal(kAstI32);
f->SetExported();
ExportAsMain(f);
byte code[] = {WASM_BLOCK(
2,
WASM_WHILE(
......@@ -132,7 +138,7 @@ TEST(Run_WasmModule_CallMain_recursive) {
f->SetSignature(sigs.i_v());
uint16_t localIndex = f->AddLocal(kAstI32);
f->SetExported();
ExportAsMain(f);
byte code[] = {WASM_BLOCK(
2, WASM_SET_LOCAL(localIndex,
WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)),
......@@ -162,7 +168,7 @@ TEST(Run_WasmModule_Global) {
uint16_t f2_index = builder->AddFunction();
f = builder->FunctionAt(f2_index);
f->SetSignature(sigs.i_v());
f->SetExported();
ExportAsMain(f);
byte code2[] = {WASM_STORE_GLOBAL(global1, WASM_I32V_1(56)),
WASM_STORE_GLOBAL(global2, WASM_I32V_1(41)),
WASM_RETURN1(WASM_CALL_FUNCTION0(f1_index))};
......
......@@ -33,7 +33,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
v8::TryCatch try_catch(isolate);
v8::internal::WasmJs::InstallWasmFunctionMap(i_isolate,
i_isolate->native_context());
v8::internal::wasm::CompileAndRunWasmModule(i_isolate, data, data + size,
true);
v8::internal::wasm::testing::CompileAndRunWasmModule(i_isolate, data,
data + size, true);
return 0;
}
......@@ -33,7 +33,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
v8::TryCatch try_catch(isolate);
v8::internal::WasmJs::InstallWasmFunctionMap(i_isolate,
i_isolate->native_context());
v8::internal::wasm::CompileAndRunWasmModule(i_isolate, data, data + size,
false);
v8::internal::wasm::testing::CompileAndRunWasmModule(i_isolate, data,
data + size, false);
return 0;
}
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