Commit 9195b000 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by V8 LUCI CQ

[wasm] Disallow using stack-backed handles in runtime-wasm.cc

We currently don't have a way to visit parameter stack slots being
passed from Wasm to the runtime during GC, so while we usually access
them as if they were handles, they're not actually GC-safe in this
case. Until we find a way to fix this differently, force manual creation
of safe handles.

Bug: v8:13036
Change-Id: I9ffec58348d912bd56fb199e9d0bc90bf753b87c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3745372
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Auto-Submit: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81562}
parent ace6a590
...@@ -26,6 +26,25 @@ ...@@ -26,6 +26,25 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// TODO(13036): See if we can find a way to have the stack walker visit
// tagged values being passed from Wasm to runtime functions. In the meantime,
// disallow access to safe-looking-but-actually-unsafe stack-backed handles
// and thereby force manual creation of safe handles (backed by HandleScope).
class RuntimeArgumentsWithoutHandles : public RuntimeArguments {
public:
RuntimeArgumentsWithoutHandles(int length, Address* arguments)
: RuntimeArguments(length, arguments) {}
private:
// Disallowing the superclass method.
template <class S = Object>
V8_INLINE Handle<S> at(int index) const;
};
#define RuntimeArguments RuntimeArgumentsWithoutHandles
// (End of TODO(13036)-related hackery.)
namespace { namespace {
template <typename FrameType> template <typename FrameType>
...@@ -103,15 +122,15 @@ RUNTIME_FUNCTION(Runtime_WasmIsValidRefValue) { ...@@ -103,15 +122,15 @@ RUNTIME_FUNCTION(Runtime_WasmIsValidRefValue) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(3, args.length()); DCHECK_EQ(3, args.length());
// 'raw_instance' can be either a WasmInstanceObject or undefined. // 'raw_instance' can be either a WasmInstanceObject or undefined.
Handle<Object> raw_instance = args.at(0); Object raw_instance = args[0];
Handle<Object> value = args.at(1); Handle<Object> value(args[1], isolate);
// Make sure ValueType fits properly in a Smi. // Make sure ValueType fits properly in a Smi.
static_assert(wasm::ValueType::kLastUsedBit + 1 <= kSmiValueSize); static_assert(wasm::ValueType::kLastUsedBit + 1 <= kSmiValueSize);
int raw_type = args.smi_value_at(2); int raw_type = args.smi_value_at(2);
const wasm::WasmModule* module = const wasm::WasmModule* module =
raw_instance->IsWasmInstanceObject() raw_instance.IsWasmInstanceObject()
? Handle<WasmInstanceObject>::cast(raw_instance)->module() ? WasmInstanceObject::cast(raw_instance).module()
: nullptr; : nullptr;
wasm::ValueType type = wasm::ValueType::FromRawBitField(raw_type); wasm::ValueType type = wasm::ValueType::FromRawBitField(raw_type);
...@@ -126,13 +145,13 @@ RUNTIME_FUNCTION(Runtime_WasmMemoryGrow) { ...@@ -126,13 +145,13 @@ RUNTIME_FUNCTION(Runtime_WasmMemoryGrow) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
// {delta_pages} is checked to be a positive smi in the WasmMemoryGrow builtin // {delta_pages} is checked to be a positive smi in the WasmMemoryGrow builtin
// which calls this runtime function. // which calls this runtime function.
uint32_t delta_pages = args.positive_smi_value_at(1); uint32_t delta_pages = args.positive_smi_value_at(1);
int ret = WasmMemoryObject::Grow( int ret = WasmMemoryObject::Grow(
isolate, handle(instance->memory_object(), isolate), delta_pages); isolate, handle(instance.memory_object(), isolate), delta_pages);
// The WasmMemoryGrow builtin which calls this runtime function expects us to // The WasmMemoryGrow builtin which calls this runtime function expects us to
// always return a Smi. // always return a Smi.
DCHECK(!isolate->has_pending_exception()); DCHECK(!isolate->has_pending_exception());
...@@ -171,12 +190,8 @@ RUNTIME_FUNCTION(Runtime_WasmThrow) { ...@@ -171,12 +190,8 @@ RUNTIME_FUNCTION(Runtime_WasmThrow) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate)); isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
Handle<WasmExceptionTag> tag(WasmExceptionTag::cast(args[0]), isolate);
auto tag_raw = WasmExceptionTag::cast(args[0]); Handle<FixedArray> values(FixedArray::cast(args[1]), isolate);
auto values_raw = FixedArray::cast(args[1]);
// TODO(wasm): Manually box because parameters are not visited yet.
Handle<WasmExceptionTag> tag(tag_raw, isolate);
Handle<FixedArray> values(values_raw, isolate);
Handle<WasmExceptionPackage> exception = Handle<WasmExceptionPackage> exception =
WasmExceptionPackage::New(isolate, tag, values); WasmExceptionPackage::New(isolate, tag, values);
wasm::GetWasmEngine()->SampleThrowEvent(isolate); wasm::GetWasmEngine()->SampleThrowEvent(isolate);
...@@ -212,7 +227,11 @@ RUNTIME_FUNCTION(Runtime_WasmCompileLazy) { ...@@ -212,7 +227,11 @@ RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
ClearThreadInWasmScope wasm_flag(isolate); ClearThreadInWasmScope wasm_flag(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); // TODO(jkummerow): This can be an unhandlified object once
// {wasm::CompileLazy()} no longer allocates even when speculative inlining
// is enabled.
Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
isolate);
int func_index = args.smi_value_at(1); int func_index = args.smi_value_at(1);
#ifdef DEBUG #ifdef DEBUG
...@@ -236,7 +255,7 @@ RUNTIME_FUNCTION(Runtime_WasmCompileLazy) { ...@@ -236,7 +255,7 @@ RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
return ReadOnlyRoots{isolate}.exception(); return ReadOnlyRoots{isolate}.exception();
} }
auto* native_module = instance->module_object().native_module(); wasm::NativeModule* native_module = instance->module_object().native_module();
return Smi::FromInt(native_module->GetJumpTableOffset(func_index)); return Smi::FromInt(native_module->GetJumpTableOffset(func_index));
} }
...@@ -259,9 +278,10 @@ void ReplaceWrapper(Isolate* isolate, Handle<WasmInstanceObject> instance, ...@@ -259,9 +278,10 @@ void ReplaceWrapper(Isolate* isolate, Handle<WasmInstanceObject> instance,
RUNTIME_FUNCTION(Runtime_WasmCompileWrapper) { RUNTIME_FUNCTION(Runtime_WasmCompileWrapper) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
Handle<WasmExportedFunctionData> function_data = isolate);
args.at<WasmExportedFunctionData>(1); Handle<WasmExportedFunctionData> function_data(
WasmExportedFunctionData::cast(args[1]), isolate);
DCHECK(isolate->context().is_null()); DCHECK(isolate->context().is_null());
isolate->set_context(instance->native_context()); isolate->set_context(instance->native_context());
...@@ -335,11 +355,11 @@ RUNTIME_FUNCTION(Runtime_WasmAtomicNotify) { ...@@ -335,11 +355,11 @@ RUNTIME_FUNCTION(Runtime_WasmAtomicNotify) {
ClearThreadInWasmScope clear_wasm_flag(isolate); ClearThreadInWasmScope clear_wasm_flag(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(3, args.length()); DCHECK_EQ(3, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
double offset_double = args.number_value_at(1); double offset_double = args.number_value_at(1);
uintptr_t offset = static_cast<uintptr_t>(offset_double); uintptr_t offset = static_cast<uintptr_t>(offset_double);
uint32_t count = NumberToUint32(args[2]); uint32_t count = NumberToUint32(args[2]);
Handle<JSArrayBuffer> array_buffer{instance->memory_object().array_buffer(), Handle<JSArrayBuffer> array_buffer{instance.memory_object().array_buffer(),
isolate}; isolate};
// Should have trapped if address was OOB. // Should have trapped if address was OOB.
DCHECK_LT(offset, array_buffer->byte_length()); DCHECK_LT(offset, array_buffer->byte_length());
...@@ -351,13 +371,13 @@ RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) { ...@@ -351,13 +371,13 @@ RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) {
ClearThreadInWasmScope clear_wasm_flag(isolate); ClearThreadInWasmScope clear_wasm_flag(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(4, args.length()); DCHECK_EQ(4, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
double offset_double = args.number_value_at(1); double offset_double = args.number_value_at(1);
uintptr_t offset = static_cast<uintptr_t>(offset_double); uintptr_t offset = static_cast<uintptr_t>(offset_double);
int32_t expected_value = NumberToInt32(args[2]); int32_t expected_value = NumberToInt32(args[2]);
Handle<BigInt> timeout_ns = args.at<BigInt>(3); BigInt timeout_ns = BigInt::cast(args[3]);
Handle<JSArrayBuffer> array_buffer{instance->memory_object().array_buffer(), Handle<JSArrayBuffer> array_buffer{instance.memory_object().array_buffer(),
isolate}; isolate};
// Should have trapped if address was OOB. // Should have trapped if address was OOB.
DCHECK_LT(offset, array_buffer->byte_length()); DCHECK_LT(offset, array_buffer->byte_length());
...@@ -367,20 +387,20 @@ RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) { ...@@ -367,20 +387,20 @@ RUNTIME_FUNCTION(Runtime_WasmI32AtomicWait) {
return ThrowWasmError(isolate, MessageTemplate::kAtomicsWaitNotAllowed); return ThrowWasmError(isolate, MessageTemplate::kAtomicsWaitNotAllowed);
} }
return FutexEmulation::WaitWasm32(isolate, array_buffer, offset, return FutexEmulation::WaitWasm32(isolate, array_buffer, offset,
expected_value, timeout_ns->AsInt64()); expected_value, timeout_ns.AsInt64());
} }
RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) { RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) {
ClearThreadInWasmScope clear_wasm_flag(isolate); ClearThreadInWasmScope clear_wasm_flag(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(4, args.length()); DCHECK_EQ(4, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
double offset_double = args.number_value_at(1); double offset_double = args.number_value_at(1);
uintptr_t offset = static_cast<uintptr_t>(offset_double); uintptr_t offset = static_cast<uintptr_t>(offset_double);
Handle<BigInt> expected_value = args.at<BigInt>(2); BigInt expected_value = BigInt::cast(args[2]);
Handle<BigInt> timeout_ns = args.at<BigInt>(3); BigInt timeout_ns = BigInt::cast(args[3]);
Handle<JSArrayBuffer> array_buffer{instance->memory_object().array_buffer(), Handle<JSArrayBuffer> array_buffer{instance.memory_object().array_buffer(),
isolate}; isolate};
// Should have trapped if address was OOB. // Should have trapped if address was OOB.
DCHECK_LT(offset, array_buffer->byte_length()); DCHECK_LT(offset, array_buffer->byte_length());
...@@ -390,8 +410,8 @@ RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) { ...@@ -390,8 +410,8 @@ RUNTIME_FUNCTION(Runtime_WasmI64AtomicWait) {
return ThrowWasmError(isolate, MessageTemplate::kAtomicsWaitNotAllowed); return ThrowWasmError(isolate, MessageTemplate::kAtomicsWaitNotAllowed);
} }
return FutexEmulation::WaitWasm64(isolate, array_buffer, offset, return FutexEmulation::WaitWasm64(isolate, array_buffer, offset,
expected_value->AsInt64(), expected_value.AsInt64(),
timeout_ns->AsInt64()); timeout_ns.AsInt64());
} }
namespace { namespace {
...@@ -410,7 +430,8 @@ RUNTIME_FUNCTION(Runtime_WasmRefFunc) { ...@@ -410,7 +430,8 @@ RUNTIME_FUNCTION(Runtime_WasmRefFunc) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
isolate);
uint32_t function_index = args.positive_smi_value_at(1); uint32_t function_index = args.positive_smi_value_at(1);
return *WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate, instance, return *WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate, instance,
...@@ -421,12 +442,12 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableGet) { ...@@ -421,12 +442,12 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableGet) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(3, args.length()); DCHECK_EQ(3, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
uint32_t table_index = args.positive_smi_value_at(1); uint32_t table_index = args.positive_smi_value_at(1);
uint32_t entry_index = args.positive_smi_value_at(2); uint32_t entry_index = args.positive_smi_value_at(2);
DCHECK_LT(table_index, instance->tables().length()); DCHECK_LT(table_index, instance.tables().length());
auto table = handle( auto table = handle(WasmTableObject::cast(instance.tables().get(table_index)),
WasmTableObject::cast(instance->tables().get(table_index)), isolate); isolate);
// We only use the runtime call for lazily initialized function references. // We only use the runtime call for lazily initialized function references.
DCHECK( DCHECK(
table->instance().IsUndefined() table->instance().IsUndefined()
...@@ -445,15 +466,13 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableSet) { ...@@ -445,15 +466,13 @@ RUNTIME_FUNCTION(Runtime_WasmFunctionTableSet) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(4, args.length()); DCHECK_EQ(4, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
uint32_t table_index = args.positive_smi_value_at(1); uint32_t table_index = args.positive_smi_value_at(1);
uint32_t entry_index = args.positive_smi_value_at(2); uint32_t entry_index = args.positive_smi_value_at(2);
Object element_raw = args[3]; Handle<Object> element(args[3], isolate);
// TODO(wasm): Manually box because parameters are not visited yet. DCHECK_LT(table_index, instance.tables().length());
Handle<Object> element(element_raw, isolate); auto table = handle(WasmTableObject::cast(instance.tables().get(table_index)),
DCHECK_LT(table_index, instance->tables().length()); isolate);
auto table = handle(
WasmTableObject::cast(instance->tables().get(table_index)), isolate);
// We only use the runtime call for lazily initialized function references. // We only use the runtime call for lazily initialized function references.
DCHECK( DCHECK(
table->instance().IsUndefined() table->instance().IsUndefined()
...@@ -472,7 +491,8 @@ RUNTIME_FUNCTION(Runtime_WasmTableInit) { ...@@ -472,7 +491,8 @@ RUNTIME_FUNCTION(Runtime_WasmTableInit) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(6, args.length()); DCHECK_EQ(6, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
isolate);
uint32_t table_index = args.positive_smi_value_at(1); uint32_t table_index = args.positive_smi_value_at(1);
uint32_t elem_segment_index = args.positive_smi_value_at(2); uint32_t elem_segment_index = args.positive_smi_value_at(2);
static_assert( static_assert(
...@@ -497,7 +517,8 @@ RUNTIME_FUNCTION(Runtime_WasmTableCopy) { ...@@ -497,7 +517,8 @@ RUNTIME_FUNCTION(Runtime_WasmTableCopy) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(6, args.length()); DCHECK_EQ(6, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
isolate);
uint32_t table_dst_index = args.positive_smi_value_at(1); uint32_t table_dst_index = args.positive_smi_value_at(1);
uint32_t table_src_index = args.positive_smi_value_at(2); uint32_t table_src_index = args.positive_smi_value_at(2);
static_assert( static_assert(
...@@ -519,15 +540,13 @@ RUNTIME_FUNCTION(Runtime_WasmTableGrow) { ...@@ -519,15 +540,13 @@ RUNTIME_FUNCTION(Runtime_WasmTableGrow) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(4, args.length()); DCHECK_EQ(4, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
uint32_t table_index = args.positive_smi_value_at(1); uint32_t table_index = args.positive_smi_value_at(1);
Object value_raw = args[2]; Handle<Object> value(args[2], isolate);
// TODO(wasm): Manually box because parameters are not visited yet.
Handle<Object> value(value_raw, isolate);
uint32_t delta = args.positive_smi_value_at(3); uint32_t delta = args.positive_smi_value_at(3);
Handle<WasmTableObject> table( Handle<WasmTableObject> table(
WasmTableObject::cast(instance->tables().get(table_index)), isolate); WasmTableObject::cast(instance.tables().get(table_index)), isolate);
int result = WasmTableObject::Grow(isolate, table, delta, value); int result = WasmTableObject::Grow(isolate, table, delta, value);
return Smi::FromInt(result); return Smi::FromInt(result);
...@@ -537,12 +556,11 @@ RUNTIME_FUNCTION(Runtime_WasmTableFill) { ...@@ -537,12 +556,11 @@ RUNTIME_FUNCTION(Runtime_WasmTableFill) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(5, args.length()); DCHECK_EQ(5, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
isolate);
uint32_t table_index = args.positive_smi_value_at(1); uint32_t table_index = args.positive_smi_value_at(1);
uint32_t start = args.positive_smi_value_at(2); uint32_t start = args.positive_smi_value_at(2);
Object value_raw = args[3]; Handle<Object> value(args[3], isolate);
// TODO(wasm): Manually box because parameters are not visited yet.
Handle<Object> value(value_raw, isolate);
uint32_t count = args.positive_smi_value_at(4); uint32_t count = args.positive_smi_value_at(4);
Handle<WasmTableObject> table( Handle<WasmTableObject> table(
...@@ -662,45 +680,37 @@ RUNTIME_FUNCTION(Runtime_WasmDebugBreak) { ...@@ -662,45 +680,37 @@ RUNTIME_FUNCTION(Runtime_WasmDebugBreak) {
return ReadOnlyRoots(isolate).undefined_value(); return ReadOnlyRoots(isolate).undefined_value();
} }
namespace {
inline void* ArrayElementAddress(Handle<WasmArray> array, uint32_t index,
int element_size_bytes) {
return reinterpret_cast<void*>(array->ptr() + WasmArray::kHeaderSize -
kHeapObjectTag + index * element_size_bytes);
}
} // namespace
// Assumes copy ranges are in-bounds and copy length > 0. // Assumes copy ranges are in-bounds and copy length > 0.
RUNTIME_FUNCTION(Runtime_WasmArrayCopy) { RUNTIME_FUNCTION(Runtime_WasmArrayCopy) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DisallowGarbageCollection no_gc;
DCHECK_EQ(5, args.length()); DCHECK_EQ(5, args.length());
Handle<WasmArray> dst_array = args.at<WasmArray>(0); WasmArray dst_array = WasmArray::cast(args[0]);
uint32_t dst_index = args.positive_smi_value_at(1); uint32_t dst_index = args.positive_smi_value_at(1);
Handle<WasmArray> src_array = args.at<WasmArray>(2); WasmArray src_array = WasmArray::cast(args[2]);
uint32_t src_index = args.positive_smi_value_at(3); uint32_t src_index = args.positive_smi_value_at(3);
uint32_t length = args.positive_smi_value_at(4); uint32_t length = args.positive_smi_value_at(4);
DCHECK_GT(length, 0); DCHECK_GT(length, 0);
bool overlapping_ranges = bool overlapping_ranges =
dst_array->ptr() == src_array->ptr() && dst_array.ptr() == src_array.ptr() &&
(dst_index < src_index ? dst_index + length > src_index (dst_index < src_index ? dst_index + length > src_index
: src_index + length > dst_index); : src_index + length > dst_index);
wasm::ValueType element_type = src_array->type()->element_type(); wasm::ValueType element_type = src_array.type()->element_type();
if (element_type.is_reference()) { if (element_type.is_reference()) {
ObjectSlot dst_slot = dst_array->ElementSlot(dst_index); ObjectSlot dst_slot = dst_array.ElementSlot(dst_index);
ObjectSlot src_slot = src_array->ElementSlot(src_index); ObjectSlot src_slot = src_array.ElementSlot(src_index);
if (overlapping_ranges) { if (overlapping_ranges) {
isolate->heap()->MoveRange(*dst_array, dst_slot, src_slot, length, isolate->heap()->MoveRange(dst_array, dst_slot, src_slot, length,
UPDATE_WRITE_BARRIER); UPDATE_WRITE_BARRIER);
} else { } else {
isolate->heap()->CopyRange(*dst_array, dst_slot, src_slot, length, isolate->heap()->CopyRange(dst_array, dst_slot, src_slot, length,
UPDATE_WRITE_BARRIER); UPDATE_WRITE_BARRIER);
} }
} else { } else {
int element_size_bytes = element_type.value_kind_size(); void* dst = reinterpret_cast<void*>(dst_array.ElementAddress(dst_index));
void* dst = ArrayElementAddress(dst_array, dst_index, element_size_bytes); void* src = reinterpret_cast<void*>(src_array.ElementAddress(src_index));
void* src = ArrayElementAddress(src_array, src_index, element_size_bytes); size_t copy_size = length * element_type.value_kind_size();
size_t copy_size = length * element_size_bytes;
if (overlapping_ranges) { if (overlapping_ranges) {
MemMove(dst, src, copy_size); MemMove(dst, src, copy_size);
} else { } else {
...@@ -714,11 +724,12 @@ RUNTIME_FUNCTION(Runtime_WasmArrayNewSegment) { ...@@ -714,11 +724,12 @@ RUNTIME_FUNCTION(Runtime_WasmArrayNewSegment) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(5, args.length()); DCHECK_EQ(5, args.length());
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
isolate);
uint32_t segment_index = args.positive_smi_value_at(1); uint32_t segment_index = args.positive_smi_value_at(1);
uint32_t offset = args.positive_smi_value_at(2); uint32_t offset = args.positive_smi_value_at(2);
uint32_t length = args.positive_smi_value_at(3); uint32_t length = args.positive_smi_value_at(3);
Handle<Map> rtt = args.at<Map>(4); Handle<Map> rtt(Map::cast(args[4]), isolate);
wasm::ArrayType* type = reinterpret_cast<wasm::ArrayType*>( wasm::ArrayType* type = reinterpret_cast<wasm::ArrayType*>(
rtt->wasm_type_info().foreign_address()); rtt->wasm_type_info().foreign_address());
...@@ -791,7 +802,8 @@ void SyncStackLimit(Isolate* isolate) { ...@@ -791,7 +802,8 @@ void SyncStackLimit(Isolate* isolate) {
RUNTIME_FUNCTION(Runtime_WasmAllocateContinuation) { RUNTIME_FUNCTION(Runtime_WasmAllocateContinuation) {
CHECK(FLAG_experimental_wasm_stack_switching); CHECK(FLAG_experimental_wasm_stack_switching);
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<WasmSuspenderObject> suspender = args.at<WasmSuspenderObject>(0); Handle<WasmSuspenderObject> suspender(WasmSuspenderObject::cast(args[0]),
isolate);
if (suspender->state() != WasmSuspenderObject::kInactive) { if (suspender->state() != WasmSuspenderObject::kInactive) {
return ThrowWasmError(isolate, return ThrowWasmError(isolate,
...@@ -833,11 +845,11 @@ RUNTIME_FUNCTION(Runtime_WasmSyncStackLimit) { ...@@ -833,11 +845,11 @@ RUNTIME_FUNCTION(Runtime_WasmSyncStackLimit) {
RUNTIME_FUNCTION(Runtime_WasmCreateResumePromise) { RUNTIME_FUNCTION(Runtime_WasmCreateResumePromise) {
CHECK(FLAG_experimental_wasm_stack_switching); CHECK(FLAG_experimental_wasm_stack_switching);
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<Object> promise = args.at(0); Handle<Object> promise(args[0], isolate);
Handle<WasmSuspenderObject> suspender = args.at<WasmSuspenderObject>(1); WasmSuspenderObject suspender = WasmSuspenderObject::cast(args[1]);
i::Handle<i::Object> argv[] = {handle(suspender->resume(), isolate), i::Handle<i::Object> argv[] = {handle(suspender.resume(), isolate),
handle(suspender->reject(), isolate)}; handle(suspender.reject(), isolate)};
i::Handle<i::Object> result; i::Handle<i::Object> result;
bool has_pending_exception = bool has_pending_exception =
!i::Execution::CallBuiltin(isolate, isolate->promise_then(), promise, !i::Execution::CallBuiltin(isolate, isolate->promise_then(), promise,
...@@ -868,7 +880,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf8) { ...@@ -868,7 +880,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf8) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(5, args.length()); DCHECK_EQ(5, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
uint32_t memory = args.positive_smi_value_at(1); uint32_t memory = args.positive_smi_value_at(1);
uint32_t policy_value = args.positive_smi_value_at(2); uint32_t policy_value = args.positive_smi_value_at(2);
uint32_t offset = NumberToUint32(args[3]); uint32_t offset = NumberToUint32(args[3]);
...@@ -881,12 +893,12 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf8) { ...@@ -881,12 +893,12 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf8) {
auto policy = static_cast<wasm::StringRefWtf8Policy>(policy_value); auto policy = static_cast<wasm::StringRefWtf8Policy>(policy_value);
auto utf8_variant = Utf8VariantFromWtf8Policy(policy); auto utf8_variant = Utf8VariantFromWtf8Policy(policy);
uint64_t mem_size = instance->memory_size(); uint64_t mem_size = instance.memory_size();
if (!base::IsInBounds<uint64_t>(offset, size, mem_size)) { if (!base::IsInBounds<uint64_t>(offset, size, mem_size)) {
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds); return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds);
} }
const base::Vector<const uint8_t> bytes{instance->memory_start() + offset, const base::Vector<const uint8_t> bytes{instance.memory_start() + offset,
size}; size};
RETURN_RESULT_OR_FAILURE( RETURN_RESULT_OR_FAILURE(
isolate, isolate->factory()->NewStringFromUtf8(bytes, utf8_variant)); isolate, isolate->factory()->NewStringFromUtf8(bytes, utf8_variant));
...@@ -897,7 +909,6 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf8Array) { ...@@ -897,7 +909,6 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf8Array) {
DCHECK_EQ(4, args.length()); DCHECK_EQ(4, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
uint32_t policy_value = args.positive_smi_value_at(0); uint32_t policy_value = args.positive_smi_value_at(0);
// TODO(wasm): Manually box because parameters are not visited yet.
Handle<WasmArray> array(WasmArray::cast(args[1]), isolate); Handle<WasmArray> array(WasmArray::cast(args[1]), isolate);
uint32_t start = NumberToUint32(args[2]); uint32_t start = NumberToUint32(args[2]);
uint32_t end = NumberToUint32(args[3]); uint32_t end = NumberToUint32(args[3]);
...@@ -914,7 +925,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16) { ...@@ -914,7 +925,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(4, args.length()); DCHECK_EQ(4, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
uint32_t memory = args.positive_smi_value_at(1); uint32_t memory = args.positive_smi_value_at(1);
uint32_t offset = NumberToUint32(args[2]); uint32_t offset = NumberToUint32(args[2]);
uint32_t size_in_codeunits = NumberToUint32(args[3]); uint32_t size_in_codeunits = NumberToUint32(args[3]);
...@@ -922,7 +933,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16) { ...@@ -922,7 +933,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16) {
DCHECK_EQ(memory, 0); DCHECK_EQ(memory, 0);
USE(memory); USE(memory);
uint64_t mem_size = instance->memory_size(); uint64_t mem_size = instance.memory_size();
if (size_in_codeunits > kMaxUInt32 / 2 || if (size_in_codeunits > kMaxUInt32 / 2 ||
!base::IsInBounds<uint64_t>(offset, size_in_codeunits * 2, mem_size)) { !base::IsInBounds<uint64_t>(offset, size_in_codeunits * 2, mem_size)) {
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds); return ThrowWasmError(isolate, MessageTemplate::kWasmTrapMemOutOfBounds);
...@@ -931,7 +942,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16) { ...@@ -931,7 +942,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16) {
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapUnalignedAccess); return ThrowWasmError(isolate, MessageTemplate::kWasmTrapUnalignedAccess);
} }
const byte* bytes = instance->memory_start() + offset; const byte* bytes = instance.memory_start() + offset;
const base::uc16* codeunits = reinterpret_cast<const base::uc16*>(bytes); const base::uc16* codeunits = reinterpret_cast<const base::uc16*>(bytes);
// TODO(12868): Override any exception with an uncatchable-by-wasm trap. // TODO(12868): Override any exception with an uncatchable-by-wasm trap.
RETURN_RESULT_OR_FAILURE(isolate, RETURN_RESULT_OR_FAILURE(isolate,
...@@ -943,7 +954,6 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16Array) { ...@@ -943,7 +954,6 @@ RUNTIME_FUNCTION(Runtime_WasmStringNewWtf16Array) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(3, args.length()); DCHECK_EQ(3, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
// TODO(wasm): Manually box because parameters are not visited yet.
Handle<WasmArray> array(WasmArray::cast(args[0]), isolate); Handle<WasmArray> array(WasmArray::cast(args[0]), isolate);
uint32_t start = NumberToUint32(args[1]); uint32_t start = NumberToUint32(args[1]);
uint32_t end = NumberToUint32(args[2]); uint32_t end = NumberToUint32(args[2]);
...@@ -958,17 +968,17 @@ RUNTIME_FUNCTION(Runtime_WasmStringConst) { ...@@ -958,17 +968,17 @@ RUNTIME_FUNCTION(Runtime_WasmStringConst) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
static_assert( static_assert(
base::IsInRange(wasm::kV8MaxWasmStringLiterals, 0, Smi::kMaxValue)); base::IsInRange(wasm::kV8MaxWasmStringLiterals, 0, Smi::kMaxValue));
uint32_t index = args.positive_smi_value_at(1); uint32_t index = args.positive_smi_value_at(1);
DCHECK_LT(index, instance->module()->stringref_literals.size()); DCHECK_LT(index, instance.module()->stringref_literals.size());
const wasm::WasmStringRefLiteral& literal = const wasm::WasmStringRefLiteral& literal =
instance->module()->stringref_literals[index]; instance.module()->stringref_literals[index];
const base::Vector<const uint8_t> module_bytes = const base::Vector<const uint8_t> module_bytes =
instance->module_object().native_module()->wire_bytes(); instance.module_object().native_module()->wire_bytes();
const base::Vector<const uint8_t> string_bytes = const base::Vector<const uint8_t> string_bytes =
module_bytes.SubVector(literal.source.offset(), module_bytes.SubVector(literal.source.offset(),
literal.source.offset() + literal.source.length()); literal.source.offset() + literal.source.length());
...@@ -1050,7 +1060,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringMeasureUtf8) { ...@@ -1050,7 +1060,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringMeasureUtf8) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<String> string = args.at<String>(0); Handle<String> string(String::cast(args[0]), isolate);
string = String::Flatten(isolate, string); string = String::Flatten(isolate, string);
int length; int length;
...@@ -1077,7 +1087,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringMeasureWtf8) { ...@@ -1077,7 +1087,7 @@ RUNTIME_FUNCTION(Runtime_WasmStringMeasureWtf8) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<String> string = args.at<String>(0); Handle<String> string(String::cast(args[0]), isolate);
string = String::Flatten(isolate, string); string = String::Flatten(isolate, string);
int length; int length;
...@@ -1098,18 +1108,18 @@ RUNTIME_FUNCTION(Runtime_WasmStringEncodeWtf8) { ...@@ -1098,18 +1108,18 @@ RUNTIME_FUNCTION(Runtime_WasmStringEncodeWtf8) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(5, args.length()); DCHECK_EQ(5, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
uint32_t memory = args.positive_smi_value_at(1); uint32_t memory = args.positive_smi_value_at(1);
uint32_t policy_value = args.positive_smi_value_at(2); uint32_t policy_value = args.positive_smi_value_at(2);
Handle<String> string = args.at<String>(3); Handle<String> string(String::cast(args[3]), isolate);
uint32_t offset = NumberToUint32(args[4]); uint32_t offset = NumberToUint32(args[4]);
DCHECK_EQ(memory, 0); DCHECK_EQ(memory, 0);
USE(memory); USE(memory);
DCHECK(policy_value <= wasm::kLastWtf8Policy); DCHECK(policy_value <= wasm::kLastWtf8Policy);
char* memory_start = reinterpret_cast<char*>(instance->memory_start()); char* memory_start = reinterpret_cast<char*>(instance.memory_start());
size_t mem_size = instance->memory_size(); size_t mem_size = instance.memory_size();
auto policy = static_cast<wasm::StringRefWtf8Policy>(policy_value); auto policy = static_cast<wasm::StringRefWtf8Policy>(policy_value);
string = String::Flatten(isolate, string); string = String::Flatten(isolate, string);
...@@ -1132,18 +1142,18 @@ RUNTIME_FUNCTION(Runtime_WasmStringEncodeWtf16) { ...@@ -1132,18 +1142,18 @@ RUNTIME_FUNCTION(Runtime_WasmStringEncodeWtf16) {
ClearThreadInWasmScope flag_scope(isolate); ClearThreadInWasmScope flag_scope(isolate);
DCHECK_EQ(6, args.length()); DCHECK_EQ(6, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
Handle<WasmInstanceObject> instance = args.at<WasmInstanceObject>(0); WasmInstanceObject instance = WasmInstanceObject::cast(args[0]);
uint32_t memory = args.positive_smi_value_at(1); uint32_t memory = args.positive_smi_value_at(1);
Handle<String> string = args.at<String>(2); String string = String::cast(args[2]);
uint32_t offset = NumberToUint32(args[3]); uint32_t offset = NumberToUint32(args[3]);
uint32_t start = args.positive_smi_value_at(4); uint32_t start = args.positive_smi_value_at(4);
uint32_t length = args.positive_smi_value_at(5); uint32_t length = args.positive_smi_value_at(5);
DCHECK_EQ(memory, 0); DCHECK_EQ(memory, 0);
USE(memory); USE(memory);
DCHECK(base::IsInBounds<uint32_t>(start, length, string->length())); DCHECK(base::IsInBounds<uint32_t>(start, length, string.length()));
size_t mem_size = instance->memory_size(); size_t mem_size = instance.memory_size();
static_assert(String::kMaxLength <= static_assert(String::kMaxLength <=
(std::numeric_limits<size_t>::max() / sizeof(base::uc16))); (std::numeric_limits<size_t>::max() / sizeof(base::uc16)));
if (!base::IsInBounds<size_t>(offset, length * sizeof(base::uc16), if (!base::IsInBounds<size_t>(offset, length * sizeof(base::uc16),
...@@ -1155,9 +1165,8 @@ RUNTIME_FUNCTION(Runtime_WasmStringEncodeWtf16) { ...@@ -1155,9 +1165,8 @@ RUNTIME_FUNCTION(Runtime_WasmStringEncodeWtf16) {
} }
#if defined(V8_TARGET_LITTLE_ENDIAN) #if defined(V8_TARGET_LITTLE_ENDIAN)
uint16_t* dst = uint16_t* dst = reinterpret_cast<uint16_t*>(instance.memory_start() + offset);
reinterpret_cast<uint16_t*>(instance->memory_start() + offset); String::WriteToFlat(string, dst, start, length);
String::WriteToFlat(*string, dst, start, length);
#elif defined(V8_TARGET_BIG_ENDIAN) #elif defined(V8_TARGET_BIG_ENDIAN)
// TODO(12868): The host is big-endian but we need to write the string // TODO(12868): The host is big-endian but we need to write the string
// contents as little-endian. // contents as little-endian.
......
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