diff options
Diffstat (limited to 'deps/v8/src/wasm/wasm-js.cc')
-rw-r--r-- | deps/v8/src/wasm/wasm-js.cc | 173 |
1 files changed, 85 insertions, 88 deletions
diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index 6cbfdbc837..ba12cf19c9 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -485,6 +485,20 @@ bool EnforceUint32(T argument_name, Local<v8::Value> v, Local<Context> context, *res = static_cast<uint32_t>(double_number); return true; } + +// The enum values need to match "WasmCompilationMethod" in +// tools/metrics/histograms/enums.xml. +enum CompilationMethod { + kSyncCompilation = 0, + kAsyncCompilation = 1, + kStreamingCompilation = 2, + kAsyncInstantiation = 3, + kStreamingInstantiation = 4, +}; + +void RecordCompilationMethod(i::Isolate* isolate, CompilationMethod method) { + isolate->counters()->wasm_compilation_method()->AddSample(method); +} } // namespace // WebAssembly.compile(bytes) -> Promise @@ -492,6 +506,7 @@ void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { constexpr const char* kAPIMethodName = "WebAssembly.compile()"; v8::Isolate* isolate = args.GetIsolate(); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + RecordCompilationMethod(i_isolate, kAsyncCompilation); HandleScope scope(isolate); ScheduledErrorThrower thrower(i_isolate, kAPIMethodName); @@ -561,6 +576,7 @@ void WebAssemblyCompileStreaming( const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = args.GetIsolate(); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + RecordCompilationMethod(i_isolate, kStreamingCompilation); HandleScope scope(isolate); const char* const kAPIMethodName = "WebAssembly.compileStreaming()"; ScheduledErrorThrower thrower(i_isolate, kAPIMethodName); @@ -680,6 +696,7 @@ void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = args.GetIsolate(); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); if (i_isolate->wasm_module_callback()(args)) return; + RecordCompilationMethod(i_isolate, kSyncCompilation); HandleScope scope(isolate); ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Module()"); @@ -795,6 +812,7 @@ void WebAssemblyModuleCustomSections( void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { Isolate* isolate = args.GetIsolate(); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + RecordCompilationMethod(i_isolate, kAsyncInstantiation); i_isolate->CountUsage( v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation); @@ -856,6 +874,7 @@ void WebAssemblyInstantiateStreaming( const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = args.GetIsolate(); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + RecordCompilationMethod(i_isolate, kStreamingInstantiation); i_isolate->CountUsage( v8::Isolate::UseCounterFeature::kWebAssemblyInstantiation); @@ -1116,15 +1135,13 @@ bool GetInitialOrMinimumProperty(v8::Isolate* isolate, ErrorThrower* thrower, namespace { i::Handle<i::Object> DefaultReferenceValue(i::Isolate* isolate, i::wasm::ValueType type) { - if (type.is_reference()) { - // Use undefined for JS type (externref) but null for wasm types as wasm - // does not know undefined. - if (type.heap_representation() == i::wasm::HeapType::kExtern) { - return isolate->factory()->undefined_value(); - } - return isolate->factory()->null_value(); + DCHECK(type.is_object_reference()); + // Use undefined for JS type (externref) but null for wasm types as wasm does + // not know undefined. + if (type.heap_representation() == i::wasm::HeapType::kExtern) { + return isolate->factory()->undefined_value(); } - UNREACHABLE(); + return isolate->factory()->wasm_null(); } } // namespace @@ -1179,8 +1196,10 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { } else if (enabled_features.has_gc() && string->StringEquals(v8_str(isolate, "arrayref"))) { type = i::wasm::kWasmArrayRef; + } else if (enabled_features.has_gc() && + string->StringEquals(v8_str(isolate, "i31ref"))) { + type = i::wasm::kWasmI31Ref; } else { - // TODO(7748): Add "i31ref". thrower.TypeError( "Descriptor property 'element' must be a WebAssembly reference type"); return; @@ -1336,7 +1355,7 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { i::Handle<i::WasmMemoryObject>::cast(memory_obj)->array_buffer(), i_isolate); Maybe<bool> result = - buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow); + buffer->SetIntegrityLevel(i_isolate, buffer, i::FROZEN, i::kDontThrow); if (!result.FromJust()) { thrower.TypeError( "Status of setting SetIntegrityLevel of buffer is false."); @@ -1390,9 +1409,11 @@ bool GetValueType(Isolate* isolate, MaybeLocal<Value> maybe, } else if (enabled_features.has_gc() && string->StringEquals(v8_str(isolate, "arrayref"))) { *type = i::wasm::kWasmArrayRef; + } else if (enabled_features.has_gc() && + string->StringEquals(v8_str(isolate, "i31ref"))) { + *type = i::wasm::kWasmI31Ref; } else { // Unrecognized type. - // TODO(7748): Add "i31ref". *type = i::wasm::kWasmVoid; } return true; @@ -1550,7 +1571,10 @@ void WebAssemblyGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) { (args.Length() < 2) ? i_isolate->factory()->null_value() : Utils::OpenHandle(*value); const char* error_message; - if (!i::wasm::JSToWasmObject(i_isolate, nullptr, value_handle, type, + // The JS API does not allow for indexed types. + // TODO(7748): Fix this if that changes. + DCHECK(!type.has_index()); + if (!i::wasm::JSToWasmObject(i_isolate, value_handle, type, &error_message) .ToHandle(&value_handle)) { thrower.TypeError("%s", error_message); @@ -1645,8 +1669,12 @@ void WebAssemblyTag(const v8::FunctionCallbackInfo<v8::Value>& args) { // Set the tag index to 0. It is only used for debugging purposes, and has no // meaningful value when declared outside of a wasm module. auto tag = i::WasmExceptionTag::New(i_isolate, 0); + + uint32_t canonical_type_index = + i::wasm::GetWasmEngine()->type_canonicalizer()->AddRecursiveGroup(&sig); + i::Handle<i::JSObject> tag_object = - i::WasmTagObject::New(i_isolate, &sig, tag); + i::WasmTagObject::New(i_isolate, &sig, canonical_type_index, tag); args.GetReturnValue().Set(Utils::ToLocal(tag_object)); } @@ -1685,8 +1713,7 @@ uint32_t GetEncodedSize(i::Handle<i::WasmTagObject> tag_object) { i::wasm::WasmTagSig sig{0, static_cast<size_t>(serialized_sig.length()), reinterpret_cast<i::wasm::ValueType*>( serialized_sig.GetDataStartAddress())}; - i::wasm::WasmTag tag(&sig); - return i::WasmExceptionPackage::GetEncodedSize(&tag); + return i::WasmExceptionPackage::GetEncodedSize(&sig); } void EncodeExceptionValues(v8::Isolate* isolate, @@ -2028,7 +2055,10 @@ void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { bool is_wasm_js_function = i::WasmJSFunction::IsWasmJSFunction(*callable); if (is_wasm_exported_function && !suspend && !promise) { - if (*i::Handle<i::WasmExportedFunction>::cast(callable)->sig() == *sig) { + uint32_t canonical_sig_index = + i::wasm::GetWasmEngine()->type_canonicalizer()->AddRecursiveGroup(sig); + if (i::Handle<i::WasmExportedFunction>::cast(callable)->MatchesSignature( + canonical_sig_index)) { args.GetReturnValue().Set(Utils::ToLocal(callable)); return; } @@ -2040,7 +2070,10 @@ void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { } if (is_wasm_js_function && !suspend && !promise) { - if (i::Handle<i::WasmJSFunction>::cast(callable)->MatchesSignature(sig)) { + uint32_t canonical_sig_index = + i::wasm::GetWasmEngine()->type_canonicalizer()->AddRecursiveGroup(sig); + if (i::Handle<i::WasmJSFunction>::cast(callable)->MatchesSignature( + canonical_sig_index)) { args.GetReturnValue().Set(Utils::ToLocal(callable)); return; } @@ -2067,7 +2100,7 @@ void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { i::Handle<i::WasmInstanceObject> instance( i::WasmInstanceObject::cast(data.internal().ref()), i_isolate); int func_index = data.function_index(); - i::Handle<i::CodeT> wrapper = + i::Handle<i::Code> wrapper = BUILTIN_CODE(i_isolate, WasmReturnPromiseOnSuspend); i::Handle<i::JSFunction> result = i::WasmExportedFunction::New( i_isolate, instance, func_index, @@ -2226,56 +2259,15 @@ void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { namespace { void WasmObjectToJSReturnValue(v8::ReturnValue<v8::Value>& return_value, i::Handle<i::Object> value, - i::wasm::HeapType::Representation repr, - const i::wasm::WasmModule* module, - i::Isolate* isolate, + i::wasm::HeapType type, i::Isolate* isolate, ScheduledErrorThrower* thrower) { - switch (repr) { - case i::wasm::HeapType::kExtern: - case i::wasm::HeapType::kString: - // TODO(7748): Make sure i31ref is compatible with Smi, or transform here. - case i::wasm::HeapType::kI31: - return_value.Set(Utils::ToLocal(value)); - return; - case i::wasm::HeapType::kFunc: { - if (!value->IsNull()) { - DCHECK(value->IsWasmInternalFunction()); - value = - handle(i::Handle<i::WasmInternalFunction>::cast(value)->external(), - isolate); - } - return_value.Set(Utils::ToLocal(value)); - return; - } - case i::wasm::HeapType::kStringViewWtf8: - thrower->TypeError("stringview_wtf8 has no JS representation"); - return; - case i::wasm::HeapType::kStringViewWtf16: - thrower->TypeError("stringview_wtf16 has no JS representation"); - return; - case i::wasm::HeapType::kStringViewIter: - thrower->TypeError("stringview_iter has no JS representation"); - return; - case i::wasm::HeapType::kBottom: - UNREACHABLE(); - case i::wasm::HeapType::kStruct: - case i::wasm::HeapType::kArray: - case i::wasm::HeapType::kEq: - case i::wasm::HeapType::kAny: { - return_value.Set(Utils::ToLocal(value)); - return; - } - default: - if (module->has_signature(repr)) { - if (!value->IsNull()) { - DCHECK(value->IsWasmInternalFunction()); - value = handle( - i::Handle<i::WasmInternalFunction>::cast(value)->external(), - isolate); - } - } - return_value.Set(Utils::ToLocal(value)); - return; + const char* error_message = nullptr; + i::MaybeHandle<i::Object> maybe_result = + i::wasm::WasmToJSObject(isolate, value, type, &error_message); + if (maybe_result.is_null()) { + thrower->TypeError("%s", error_message); + } else { + return_value.Set(Utils::ToLocal(maybe_result.ToHandleChecked())); } } } // namespace @@ -2315,12 +2307,7 @@ void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { i::WasmTableObject::Get(i_isolate, receiver, index); v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); - const i::wasm::WasmModule* module = - receiver->instance().IsWasmInstanceObject() - ? i::WasmInstanceObject::cast(receiver->instance()).module() - : nullptr; - WasmObjectToJSReturnValue(return_value, result, - receiver->type().heap_representation(), module, + WasmObjectToJSReturnValue(return_value, result, receiver->type().heap_type(), i_isolate, &thrower); } @@ -2346,6 +2333,13 @@ void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { i::Handle<i::Object> element; if (args.Length() >= 2) { element = Utils::OpenHandle(*args[1]); + const char* error_message; + if (!i::WasmTableObject::JSToWasmElement(i_isolate, table_object, element, + &error_message) + .ToHandle(&element)) { + thrower.TypeError("Argument 1 is invalid for table: %s", error_message); + return; + } } else if (table_object->type().is_defaultable()) { element = DefaultReferenceValue(i_isolate, table_object->type()); } else { @@ -2354,14 +2348,6 @@ void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { return; } - const char* error_message; - if (!i::WasmTableObject::JSToWasmElement(i_isolate, table_object, element, - &error_message) - .ToHandle(&element)) { - thrower.TypeError("Argument 1 is invalid for table: %s", error_message); - return; - } - i::WasmTableObject::Set(i_isolate, table_object, index, element); } @@ -2435,7 +2421,7 @@ void WebAssemblyMemoryGetBuffer( // buffer are out of sync, handle that here when bounds checks, and Grow // are handled correctly. Maybe<bool> result = - buffer->SetIntegrityLevel(buffer, i::FROZEN, i::kDontThrow); + buffer->SetIntegrityLevel(i_isolate, buffer, i::FROZEN, i::kDontThrow); if (!result.FromJust()) { thrower.TypeError( "Status of setting SetIntegrityLevel of buffer is false."); @@ -2688,13 +2674,9 @@ void WebAssemblyGlobalGetValueCommon( break; case i::wasm::kRef: case i::wasm::kRefNull: { - const i::wasm::WasmModule* module = - receiver->instance().IsWasmInstanceObject() - ? i::WasmInstanceObject::cast(receiver->instance()).module() - : nullptr; WasmObjectToJSReturnValue(return_value, receiver->GetRef(), - receiver->type().heap_representation(), module, - i_isolate, &thrower); + receiver->type().heap_type(), i_isolate, + &thrower); break; } case i::wasm::kRtt: @@ -2967,6 +2949,8 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) { // TODO(7748): These built-ins should not be shipped with wasm GC. // Either a new flag will be needed or the built-ins have to be deleted prior // to shipping. + // TODO(13810): We should install these later, when we can query the + // isolate's wasm_gc_enabled_callback, to take the Origin Trial into account. if (v8_flags.experimental_wasm_gc) { SimpleInstallFunction( isolate, webassembly, "experimentalConvertArrayToString", @@ -3151,6 +3135,19 @@ void WasmJs::InstallConditionalFeatures(Isolate* isolate, Handle<Context> context) { // This space left blank for future origin trials. } + +namespace wasm { +// static +std::unique_ptr<WasmStreaming> StartStreamingForTesting( + Isolate* isolate, + std::shared_ptr<wasm::CompilationResultResolver> resolver) { + return std::make_unique<WasmStreaming>( + std::make_unique<WasmStreaming::WasmStreamingImpl>( + reinterpret_cast<v8::Isolate*>(isolate), "StartStreamingForTesting", + resolver)); +} +} // namespace wasm + #undef ASSIGN #undef EXTRACT_THIS |