summaryrefslogtreecommitdiff
path: root/deps/v8/src/runtime/runtime-wasm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/runtime/runtime-wasm.cc')
-rw-r--r--deps/v8/src/runtime/runtime-wasm.cc233
1 files changed, 161 insertions, 72 deletions
diff --git a/deps/v8/src/runtime/runtime-wasm.cc b/deps/v8/src/runtime/runtime-wasm.cc
index f852df0d85..84ef744d8b 100644
--- a/deps/v8/src/runtime/runtime-wasm.cc
+++ b/deps/v8/src/runtime/runtime-wasm.cc
@@ -5,9 +5,11 @@
#include "src/arguments-inl.h"
#include "src/compiler/wasm-compiler.h"
#include "src/conversions.h"
+#include "src/counters.h"
#include "src/debug/debug.h"
#include "src/frame-constants.h"
#include "src/heap/factory.h"
+#include "src/message-template.h"
#include "src/objects-inl.h"
#include "src/objects/frame-array-inl.h"
#include "src/runtime/runtime-utils.h"
@@ -24,7 +26,7 @@ namespace internal {
namespace {
-Context* GetNativeContextFromWasmInstanceOnStackTop(Isolate* isolate) {
+WasmInstanceObject GetWasmInstanceOnStackTop(Isolate* isolate) {
StackFrameIterator it(isolate, isolate->thread_local_top());
// On top: C entry stub.
DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
@@ -32,7 +34,11 @@ Context* GetNativeContextFromWasmInstanceOnStackTop(Isolate* isolate) {
// Next: the wasm compiled frame.
DCHECK(it.frame()->is_wasm_compiled());
WasmCompiledFrame* frame = WasmCompiledFrame::cast(it.frame());
- return frame->wasm_instance()->native_context();
+ return frame->wasm_instance();
+}
+
+Context GetNativeContextFromWasmInstanceOnStackTop(Isolate* isolate) {
+ return GetWasmInstanceOnStackTop(isolate)->native_context();
}
class ClearThreadInWasmScope {
@@ -50,11 +56,25 @@ class ClearThreadInWasmScope {
} // namespace
-RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
+RUNTIME_FUNCTION(Runtime_WasmIsValidAnyFuncValue) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Object, function, 0);
+
+ if (function->IsNull(isolate)) {
+ return Smi::FromInt(true);
+ }
+ if (WasmExportedFunction::IsWasmExportedFunction(*function)) {
+ return Smi::FromInt(true);
+ }
+ return Smi::FromInt(false);
+}
+
+RUNTIME_FUNCTION(Runtime_WasmMemoryGrow) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
- // {delta_pages} is checked to be a positive smi in the WasmGrowMemory builtin
+ // {delta_pages} is checked to be a positive smi in the WasmMemoryGrow builtin
// which calls this runtime function.
CONVERT_UINT32_ARG_CHECKED(delta_pages, 1);
@@ -63,7 +83,7 @@ RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
int ret = WasmMemoryObject::Grow(
isolate, handle(instance->memory_object(), isolate), delta_pages);
- // The WasmGrowMemory builtin which calls this runtime function expects us to
+ // The WasmMemoryGrow builtin which calls this runtime function expects us to
// always return a Smi.
return Smi::FromInt(ret);
}
@@ -75,14 +95,14 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
HandleScope scope(isolate);
Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(
- static_cast<MessageTemplate::Template>(message_id));
+ MessageTemplateFromInt(message_id));
return isolate->Throw(*error_obj);
}
RUNTIME_FUNCTION(Runtime_ThrowWasmStackOverflow) {
SealHandleScope shs(isolate);
DCHECK_LE(0, args.length());
- DCHECK_NULL(isolate->context());
+ DCHECK(isolate->context().is_null());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
return isolate->StackOverflow();
}
@@ -98,26 +118,22 @@ RUNTIME_FUNCTION(Runtime_WasmThrowCreate) {
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
- DCHECK_NULL(isolate->context());
+ DCHECK(isolate->context().is_null());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
CONVERT_ARG_CHECKED(HeapObject, tag_raw, 0);
CONVERT_SMI_ARG_CHECKED(size, 1);
// TODO(mstarzinger): Manually box because parameters are not visited yet.
Handle<Object> tag(tag_raw, isolate);
Handle<Object> exception = isolate->factory()->NewWasmRuntimeError(
- static_cast<MessageTemplate::Template>(
- MessageTemplate::kWasmExceptionError));
- CHECK(
- !JSReceiver::SetProperty(isolate, exception,
- isolate->factory()->wasm_exception_tag_symbol(),
- tag, LanguageMode::kStrict)
- .is_null());
- Handle<JSTypedArray> values =
- isolate->factory()->NewJSTypedArray(ElementsKind::UINT16_ELEMENTS, size);
- CHECK(!JSReceiver::SetProperty(
- isolate, exception,
- isolate->factory()->wasm_exception_values_symbol(), values,
- LanguageMode::kStrict)
+ MessageTemplate::kWasmExceptionError);
+ CHECK(!Object::SetProperty(isolate, exception,
+ isolate->factory()->wasm_exception_tag_symbol(),
+ tag, LanguageMode::kStrict)
+ .is_null());
+ Handle<FixedArray> values = isolate->factory()->NewFixedArray(size);
+ CHECK(!Object::SetProperty(isolate, exception,
+ isolate->factory()->wasm_exception_values_symbol(),
+ values, LanguageMode::kStrict)
.is_null());
return *exception;
}
@@ -126,7 +142,7 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetTag) {
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
- DCHECK_NULL(isolate->context());
+ DCHECK(isolate->context().is_null());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
// TODO(mstarzinger): Manually box because parameters are not visited yet.
@@ -143,64 +159,24 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetTag) {
return ReadOnlyRoots(isolate).undefined_value();
}
-RUNTIME_FUNCTION(Runtime_WasmExceptionGetElement) {
+RUNTIME_FUNCTION(Runtime_WasmExceptionGetValues) {
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
HandleScope scope(isolate);
- DCHECK_EQ(2, args.length());
- DCHECK_NULL(isolate->context());
- isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
- CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
- // TODO(mstarzinger): Manually box because parameters are not visited yet.
- Handle<Object> except_obj(except_obj_raw, isolate);
- if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
- Handle<JSReceiver> exception(JSReceiver::cast(*except_obj), isolate);
- Handle<Object> values_obj;
- if (JSReceiver::GetProperty(
- isolate, exception,
- isolate->factory()->wasm_exception_values_symbol())
- .ToHandle(&values_obj)) {
- if (values_obj->IsJSTypedArray()) {
- Handle<JSTypedArray> values = Handle<JSTypedArray>::cast(values_obj);
- CHECK_EQ(values->type(), kExternalUint16Array);
- CONVERT_SMI_ARG_CHECKED(index, 1);
- CHECK(!values->WasNeutered());
- CHECK_LT(index, Smi::ToInt(values->length()));
- auto* vals =
- reinterpret_cast<uint16_t*>(values->GetBuffer()->backing_store());
- return Smi::FromInt(vals[index]);
- }
- }
- }
- return Smi::FromInt(0);
-}
-
-RUNTIME_FUNCTION(Runtime_WasmExceptionSetElement) {
- // TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
- HandleScope scope(isolate);
- DCHECK_EQ(3, args.length());
- DCHECK_NULL(isolate->context());
+ DCHECK_EQ(1, args.length());
+ DCHECK(isolate->context().is_null());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
CONVERT_ARG_CHECKED(Object, except_obj_raw, 0);
// TODO(mstarzinger): Manually box because parameters are not visited yet.
Handle<Object> except_obj(except_obj_raw, isolate);
if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
Handle<JSReceiver> exception(JSReceiver::cast(*except_obj), isolate);
- Handle<Object> values_obj;
+ Handle<Object> values;
if (JSReceiver::GetProperty(
isolate, exception,
isolate->factory()->wasm_exception_values_symbol())
- .ToHandle(&values_obj)) {
- if (values_obj->IsJSTypedArray()) {
- Handle<JSTypedArray> values = Handle<JSTypedArray>::cast(values_obj);
- CHECK_EQ(values->type(), kExternalUint16Array);
- CONVERT_SMI_ARG_CHECKED(index, 1);
- CHECK(!values->WasNeutered());
- CHECK_LT(index, Smi::ToInt(values->length()));
- CONVERT_SMI_ARG_CHECKED(value, 2);
- auto* vals =
- reinterpret_cast<uint16_t*>(values->GetBuffer()->backing_store());
- vals[index] = static_cast<uint16_t>(value);
- }
+ .ToHandle(&values)) {
+ DCHECK(values->IsFixedArray());
+ return *values;
}
}
return ReadOnlyRoots(isolate).undefined_value();
@@ -217,7 +193,7 @@ RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
// cast it back to the raw pointer.
CHECK(!arg_buffer_obj->IsHeapObject());
CHECK(arg_buffer_obj->IsSmi());
- Address arg_buffer = reinterpret_cast<Address>(*arg_buffer_obj);
+ Address arg_buffer = arg_buffer_obj->ptr();
ClearThreadInWasmScope wasm_flag;
@@ -237,7 +213,7 @@ RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) {
}
// Set the current isolate's context.
- DCHECK_NULL(isolate->context());
+ DCHECK(isolate->context().is_null());
isolate->set_context(instance->native_context());
// Run the function in the interpreter. Note that neither the {WasmDebugInfo}
@@ -290,8 +266,121 @@ RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
Address entrypoint = wasm::CompileLazy(
isolate, instance->module_object()->native_module(), func_index);
- return reinterpret_cast<Object*>(entrypoint);
+ return Object(entrypoint);
+}
+
+// Should be called from within a handle scope
+Handle<JSArrayBuffer> getSharedArrayBuffer(Handle<WasmInstanceObject> instance,
+ Isolate* isolate, uint32_t address) {
+ DCHECK(instance->has_memory_object());
+ Handle<JSArrayBuffer> array_buffer(instance->memory_object()->array_buffer(),
+ isolate);
+
+ // Validation should have failed if the memory was not shared.
+ DCHECK(array_buffer->is_shared());
+
+ // Should have trapped if address was OOB
+ DCHECK_LT(address, array_buffer->byte_length());
+ return array_buffer;
+}
+
+RUNTIME_FUNCTION(Runtime_WasmAtomicWake) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(3, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
+ CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
+ CONVERT_NUMBER_CHECKED(uint32_t, count, Uint32, args[2]);
+ Handle<JSArrayBuffer> array_buffer =
+ getSharedArrayBuffer(instance, isolate, address);
+ return FutexEmulation::Wake(array_buffer, address, count);
}
+double WaitTimeoutInMs(double timeout_ns) {
+ return timeout_ns < 0
+ ? V8_INFINITY
+ : timeout_ns / (base::Time::kNanosecondsPerMicrosecond *
+ base::Time::kMicrosecondsPerMillisecond);
+}
+
+RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(4, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
+ CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
+ CONVERT_NUMBER_CHECKED(int32_t, expected_value, Int32, args[2]);
+ CONVERT_DOUBLE_ARG_CHECKED(timeout_ns, 3);
+ double timeout_ms = WaitTimeoutInMs(timeout_ns);
+ Handle<JSArrayBuffer> array_buffer =
+ getSharedArrayBuffer(instance, isolate, address);
+ return FutexEmulation::Wait32(isolate, array_buffer, address, expected_value,
+ timeout_ms);
+}
+
+RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(5, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
+ CONVERT_NUMBER_CHECKED(uint32_t, address, Uint32, args[1]);
+ CONVERT_NUMBER_CHECKED(uint32_t, expected_value_high, Uint32, args[2]);
+ CONVERT_NUMBER_CHECKED(uint32_t, expected_value_low, Uint32, args[3]);
+ CONVERT_DOUBLE_ARG_CHECKED(timeout_ns, 4);
+ int64_t expected_value = (static_cast<uint64_t>(expected_value_high) << 32) |
+ static_cast<uint64_t>(expected_value_low);
+ double timeout_ms = WaitTimeoutInMs(timeout_ns);
+ Handle<JSArrayBuffer> array_buffer =
+ getSharedArrayBuffer(instance, isolate, address);
+ return FutexEmulation::Wait64(isolate, array_buffer, address, expected_value,
+ timeout_ms);
+}
+
+RUNTIME_FUNCTION(Runtime_WasmTableInit) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(5, args.length());
+ auto instance =
+ Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
+ CONVERT_UINT32_ARG_CHECKED(table_index, 0);
+ CONVERT_UINT32_ARG_CHECKED(elem_segment_index, 1);
+ CONVERT_UINT32_ARG_CHECKED(dst, 2);
+ CONVERT_UINT32_ARG_CHECKED(src, 3);
+ CONVERT_UINT32_ARG_CHECKED(size, 4);
+
+ PrintF(
+ "TableInit(table_index=%u, elem_segment_index=%u, dst=%u, src=%u, "
+ "size=%u)\n",
+ table_index, elem_segment_index, dst, src, size);
+
+ USE(instance);
+ USE(table_index);
+ USE(elem_segment_index);
+ USE(dst);
+ USE(src);
+ USE(size);
+
+ UNREACHABLE();
+}
+
+RUNTIME_FUNCTION(Runtime_WasmTableCopy) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(4, args.length());
+ auto instance =
+ Handle<WasmInstanceObject>(GetWasmInstanceOnStackTop(isolate), isolate);
+ CONVERT_UINT32_ARG_CHECKED(table_index, 0);
+ CONVERT_UINT32_ARG_CHECKED(dst, 1);
+ CONVERT_UINT32_ARG_CHECKED(src, 2);
+ CONVERT_UINT32_ARG_CHECKED(count, 3);
+
+ bool oob = !WasmInstanceObject::CopyTableEntries(
+ isolate, instance, table_index, dst, src, count);
+ if (oob) {
+ // Handle out-of-bounds access here in the runtime call, rather
+ // than having the lower-level layers deal with JS exceptions.
+ DCHECK(isolate->context().is_null());
+ isolate->set_context(instance->native_context());
+ Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(
+ MessageTemplate::kWasmTrapTableOutOfBounds);
+ return isolate->Throw(*error_obj);
+ }
+ return ReadOnlyRoots(isolate).undefined_value();
+}
} // namespace internal
} // namespace v8