Commit 8092acbe authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Store signature with {WebAssembly.Function} objects.

This adds simple serialization and deserialization of the signature
provided when a {WebAssembly.Function} object is constructed. For now
this signature is only used by the {WebAssembly.Function.type} method,
but will soon be used when importing such functions as well.

R=jkummerow@chromium.org
TEST=mjsunit/wasm/type-reflection
BUG=v8:7742

Change-Id: If4a687ea537d8c12f4f01a7d3ac5a795ceb999c6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1632211Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61898}
parent 2054dab3
......@@ -878,7 +878,12 @@ extern class WasmExportedFunctionData extends Struct {
function_index: Smi;
}
extern class WasmJSFunctionData extends Struct { wrapper_code: Code; }
extern class WasmJSFunctionData extends Struct {
wrapper_code: Code;
serialized_return_count: Smi;
serialized_parameter_count: Smi;
serialized_signature: ByteArray; // PodArray<wasm::ValueType>
}
extern class WasmCapiFunctionData extends Struct {
call_target: RawPtr;
......
......@@ -552,9 +552,9 @@ class PodArray : public ByteArray {
static Handle<PodArray<T>> New(
Isolate* isolate, int length,
AllocationType allocation = AllocationType::kYoung);
void copy_out(int index, T* result) {
void copy_out(int index, T* result, int length) {
ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
sizeof(T));
length * sizeof(T));
}
void copy_in(int index, const T* buffer, int length) {
......@@ -564,7 +564,7 @@ class PodArray : public ByteArray {
T get(int index) {
T result;
copy_out(index, &result);
copy_out(index, &result, 1);
return result;
}
......
......@@ -1437,7 +1437,7 @@ void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
// Decode the function type and construct a signature.
i::Zone zone(i_isolate->allocator(), ZONE_NAME);
i::wasm::FunctionSig::Builder builder(&zone, parameters_len, results_len);
i::wasm::FunctionSig::Builder builder(&zone, results_len, parameters_len);
for (uint32_t i = 0; i < parameters_len; ++i) {
i::wasm::ValueType type;
MaybeLocal<Value> maybe = parameters->Get(context, i);
......@@ -1513,13 +1513,12 @@ void WebAssemblyFunctionType(const v8::FunctionCallbackInfo<v8::Value>& args) {
ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Function.type()");
i::wasm::FunctionSig* sig;
i::Zone zone(i_isolate->allocator(), ZONE_NAME);
i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]);
if (i::WasmExportedFunction::IsWasmExportedFunction(*arg0)) {
sig = i::Handle<i::WasmExportedFunction>::cast(arg0)->sig();
} else if (i::WasmJSFunction::IsWasmJSFunction(*arg0)) {
// TODO(7742): Implement deserialization of signature.
sig = nullptr;
UNIMPLEMENTED();
sig = i::Handle<i::WasmJSFunction>::cast(arg0)->GetSignature(&zone);
} else {
thrower.TypeError("Argument 0 must be a WebAssembly.Function");
return;
......
......@@ -317,6 +317,12 @@ CAST_ACCESSOR(WasmJSFunction)
// WasmJSFunctionData
OBJECT_CONSTRUCTORS_IMPL(WasmJSFunctionData, Struct)
CAST_ACCESSOR(WasmJSFunctionData)
SMI_ACCESSORS(WasmJSFunctionData, serialized_return_count,
kSerializedReturnCountOffset)
SMI_ACCESSORS(WasmJSFunctionData, serialized_parameter_count,
kSerializedParameterCountOffset)
ACCESSORS(WasmJSFunctionData, serialized_signature, PodArray<wasm::ValueType>,
kSerializedSignatureOffset)
ACCESSORS(WasmJSFunctionData, wrapper_code, Code, kWrapperCodeOffset)
// WasmCapiFunction
......
......@@ -2143,9 +2143,19 @@ bool WasmJSFunction::IsWasmJSFunction(Object object) {
Handle<WasmJSFunction> WasmJSFunction::New(Isolate* isolate,
wasm::FunctionSig* sig,
Handle<JSReceiver> callable) {
DCHECK_LE(sig->all().size(), kMaxInt);
int sig_size = static_cast<int>(sig->all().size());
int return_count = static_cast<int>(sig->return_count());
int parameter_count = static_cast<int>(sig->parameter_count());
Handle<PodArray<wasm::ValueType>> serialized_sig =
PodArray<wasm::ValueType>::New(isolate, sig_size, AllocationType::kOld);
serialized_sig->copy_in(0, sig->all().begin(), sig_size);
Handle<WasmJSFunctionData> function_data =
Handle<WasmJSFunctionData>::cast(isolate->factory()->NewStruct(
WASM_JS_FUNCTION_DATA_TYPE, AllocationType::kOld));
function_data->set_serialized_return_count(return_count);
function_data->set_serialized_parameter_count(parameter_count);
function_data->set_serialized_signature(*serialized_sig);
// TODO(7742): Make this callable by using a proper wrapper code.
function_data->set_wrapper_code(
isolate->builtins()->builtin(Builtins::kIllegal));
......@@ -2160,6 +2170,16 @@ Handle<WasmJSFunction> WasmJSFunction::New(Isolate* isolate,
return Handle<WasmJSFunction>::cast(js_function);
}
wasm::FunctionSig* WasmJSFunction::GetSignature(Zone* zone) {
WasmJSFunctionData function_data = shared().wasm_js_function_data();
int sig_size = function_data.serialized_signature().length();
wasm::ValueType* types = zone->NewArray<wasm::ValueType>(sig_size);
function_data.serialized_signature().copy_out(0, types, sig_size);
int return_count = function_data.serialized_return_count();
int parameter_count = function_data.serialized_parameter_count();
return new (zone) wasm::FunctionSig(return_count, parameter_count, types);
}
Address WasmCapiFunction::GetHostCallTarget() const {
return shared().wasm_capi_function_data().call_target();
}
......
......@@ -681,6 +681,10 @@ class WasmJSFunction : public JSFunction {
static Handle<WasmJSFunction> New(Isolate* isolate, wasm::FunctionSig* sig,
Handle<JSReceiver> callable);
// Deserializes the signature of this function using the provided zone. Note
// that lifetime of the signature is hence directly coupled to the zone.
wasm::FunctionSig* GetSignature(Zone* zone);
DECL_CAST(WasmJSFunction)
OBJECT_CONSTRUCTORS(WasmJSFunction, JSFunction);
};
......@@ -754,6 +758,9 @@ class WasmExportedFunctionData : public Struct {
// {SharedFunctionInfo::HasWasmJSFunctionData} predicate.
class WasmJSFunctionData : public Struct {
public:
DECL_INT_ACCESSORS(serialized_return_count)
DECL_INT_ACCESSORS(serialized_parameter_count)
DECL_ACCESSORS(serialized_signature, PodArray<wasm::ValueType>)
DECL_ACCESSORS(wrapper_code, Code)
DECL_CAST(WasmJSFunctionData)
......
......@@ -239,6 +239,21 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
assertDoesNotThrow(() => fun());
})();
(function TestFunctionTypeOfConstructedFunction() {
let testcases = [
{parameters:[], results:[]},
{parameters:["i32"], results:[]},
{parameters:["i64"], results:["i32"]},
{parameters:["f64", "f64", "i32"], results:[]},
{parameters:["f32"], results:["f32"]},
];
testcases.forEach(function(expected) {
let fun = new WebAssembly.Function(expected, _ => 0);
let type = WebAssembly.Function.type(fun);
assertEquals(expected, type)
});
})();
(function TestFunctionTypeOfExportedFunction() {
let testcases = [
[kSig_v_v, {parameters:[], results:[]}],
......
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