Commit 3f17f96f authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm-gc] Preliminary changes for array.init_from_data

Changes:
- Rename kWasmTrapDataSegmentDropped to the more accurate ~OutOfBounds.
- Drop unused argument from {WasmCompiler::ArrayInit}.
- Rename {Factory::NewWasmArray} -> NewWasmArrayFromElements.
- Add error handling to {InitExprInterface}.
- Allow the data count section to appear anywhere in the module under
  --experimental-wasm-gc. Add the same capability in
  wasm-module-builder.js.
- Add {WasmArray::MaxLength(uint32_t element_size_log2)}.
- Add kTrapArrayTooLarge in wasm-module-builder.js.
- Small test improvements in gc-nominal.js.

Bug: v8:7748
Change-Id: I68ca0e8b08f906503f0d82e5866395018d216382
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3401593Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78730}
parent 21e51043
...@@ -423,7 +423,7 @@ extern enum MessageTemplate { ...@@ -423,7 +423,7 @@ extern enum MessageTemplate {
kWasmTrapRemByZero, kWasmTrapRemByZero,
kWasmTrapFloatUnrepresentable, kWasmTrapFloatUnrepresentable,
kWasmTrapFuncSigMismatch, kWasmTrapFuncSigMismatch,
kWasmTrapDataSegmentDropped, kWasmTrapDataSegmentOutOfBounds,
kWasmTrapElemSegmentDropped, kWasmTrapElemSegmentDropped,
kWasmTrapTableOutOfBounds, kWasmTrapTableOutOfBounds,
kWasmTrapRethrowNull, kWasmTrapRethrowNull,
......
...@@ -638,8 +638,8 @@ builtin ThrowWasmTrapFuncSigMismatch(): JSAny { ...@@ -638,8 +638,8 @@ builtin ThrowWasmTrapFuncSigMismatch(): JSAny {
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapFuncSigMismatch)); tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapFuncSigMismatch));
} }
builtin ThrowWasmTrapDataSegmentDropped(): JSAny { builtin ThrowWasmTrapDataSegmentOutOfBounds(): JSAny {
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapDataSegmentDropped)); tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapDataSegmentOutOfBounds));
} }
builtin ThrowWasmTrapElemSegmentDropped(): JSAny { builtin ThrowWasmTrapElemSegmentDropped(): JSAny {
......
...@@ -1761,7 +1761,7 @@ enum IsolateAddressId { ...@@ -1761,7 +1761,7 @@ enum IsolateAddressId {
V(TrapRemByZero) \ V(TrapRemByZero) \
V(TrapFloatUnrepresentable) \ V(TrapFloatUnrepresentable) \
V(TrapFuncSigMismatch) \ V(TrapFuncSigMismatch) \
V(TrapDataSegmentDropped) \ V(TrapDataSegmentOutOfBounds) \
V(TrapElemSegmentDropped) \ V(TrapElemSegmentDropped) \
V(TrapTableOutOfBounds) \ V(TrapTableOutOfBounds) \
V(TrapRethrowNull) \ V(TrapRethrowNull) \
......
...@@ -590,7 +590,7 @@ namespace internal { ...@@ -590,7 +590,7 @@ namespace internal {
T(WasmTrapFuncSigMismatch, "null function or function signature mismatch") \ T(WasmTrapFuncSigMismatch, "null function or function signature mismatch") \
T(WasmTrapMultiReturnLengthMismatch, "multi-return length mismatch") \ T(WasmTrapMultiReturnLengthMismatch, "multi-return length mismatch") \
T(WasmTrapJSTypeError, "type incompatibility when transforming from/to JS") \ T(WasmTrapJSTypeError, "type incompatibility when transforming from/to JS") \
T(WasmTrapDataSegmentDropped, "data segment has been dropped") \ T(WasmTrapDataSegmentOutOfBounds, "data segment out of bounds") \
T(WasmTrapElemSegmentDropped, "element segment has been dropped") \ T(WasmTrapElemSegmentDropped, "element segment has been dropped") \
T(WasmTrapRethrowNull, "rethrowing null value") \ T(WasmTrapRethrowNull, "rethrowing null value") \
T(WasmTrapNullDereference, "dereferencing a null pointer") \ T(WasmTrapNullDereference, "dereferencing a null pointer") \
......
...@@ -5393,6 +5393,7 @@ void WasmGraphBuilder::MemoryInit(uint32_t data_segment_index, Node* dst, ...@@ -5393,6 +5393,7 @@ void WasmGraphBuilder::MemoryInit(uint32_t data_segment_index, Node* dst,
MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()}; MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()};
MachineSignature sig(1, 1, sig_types); MachineSignature sig(1, 1, sig_types);
Node* call = BuildCCall(&sig, function, stack_slot); Node* call = BuildCCall(&sig, function, stack_slot);
// TODO(manoskouk): Also throw kDataSegmentOutOfBounds.
TrapIfFalse(wasm::kTrapMemOutOfBounds, call, position); TrapIfFalse(wasm::kTrapMemOutOfBounds, call, position);
} }
...@@ -5602,8 +5603,7 @@ Node* WasmGraphBuilder::ArrayNewWithRtt(uint32_t array_index, ...@@ -5602,8 +5603,7 @@ Node* WasmGraphBuilder::ArrayNewWithRtt(uint32_t array_index,
return a; return a;
} }
Node* WasmGraphBuilder::ArrayInit(uint32_t array_index, Node* WasmGraphBuilder::ArrayInit(const wasm::ArrayType* type, Node* rtt,
const wasm::ArrayType* type, Node* rtt,
base::Vector<Node*> elements) { base::Vector<Node*> elements) {
wasm::ValueType element_type = type->element_type(); wasm::ValueType element_type = type->element_type();
// TODO(7748): Consider using gasm_->Allocate(). // TODO(7748): Consider using gasm_->Allocate().
......
...@@ -505,7 +505,7 @@ class WasmGraphBuilder { ...@@ -505,7 +505,7 @@ class WasmGraphBuilder {
void ArrayCopy(Node* dst_array, Node* dst_index, CheckForNull dst_null_check, void ArrayCopy(Node* dst_array, Node* dst_index, CheckForNull dst_null_check,
Node* src_array, Node* src_index, CheckForNull src_null_check, Node* src_array, Node* src_index, CheckForNull src_null_check,
Node* length, wasm::WasmCodePosition position); Node* length, wasm::WasmCodePosition position);
Node* ArrayInit(uint32_t array_index, const wasm::ArrayType* type, Node* rtt, Node* ArrayInit(const wasm::ArrayType* type, Node* rtt,
base::Vector<Node*> elements); base::Vector<Node*> elements);
Node* I31New(Node* input); Node* I31New(Node* input);
Node* I31GetS(Node* input); Node* I31GetS(Node* input);
......
...@@ -1620,12 +1620,13 @@ Handle<WasmCapiFunctionData> Factory::NewWasmCapiFunctionData( ...@@ -1620,12 +1620,13 @@ Handle<WasmCapiFunctionData> Factory::NewWasmCapiFunctionData(
return handle(result, isolate()); return handle(result, isolate());
} }
Handle<WasmArray> Factory::NewWasmArray( Handle<WasmArray> Factory::NewWasmArrayFromElements(
const wasm::ArrayType* type, const std::vector<wasm::WasmValue>& elements, const wasm::ArrayType* type, const std::vector<wasm::WasmValue>& elements,
Handle<Map> map) { Handle<Map> map) {
uint32_t length = static_cast<uint32_t>(elements.size()); uint32_t length = static_cast<uint32_t>(elements.size());
HeapObject raw = HeapObject raw =
AllocateRaw(WasmArray::SizeFor(*map, length), AllocationType::kYoung); AllocateRaw(WasmArray::SizeFor(*map, length), AllocationType::kYoung);
DisallowGarbageCollection no_gc;
raw.set_map_after_allocation(*map); raw.set_map_after_allocation(*map);
WasmArray result = WasmArray::cast(raw); WasmArray result = WasmArray::cast(raw);
result.set_raw_properties_or_hash(*empty_fixed_array(), kRelaxedStore); result.set_raw_properties_or_hash(*empty_fixed_array(), kRelaxedStore);
......
...@@ -615,9 +615,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> { ...@@ -615,9 +615,9 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
Handle<HeapObject> suspender); Handle<HeapObject> suspender);
Handle<WasmStruct> NewWasmStruct(const wasm::StructType* type, Handle<WasmStruct> NewWasmStruct(const wasm::StructType* type,
wasm::WasmValue* args, Handle<Map> map); wasm::WasmValue* args, Handle<Map> map);
Handle<WasmArray> NewWasmArray(const wasm::ArrayType* type, Handle<WasmArray> NewWasmArrayFromElements(
const std::vector<wasm::WasmValue>& elements, const wasm::ArrayType* type, const std::vector<wasm::WasmValue>& elements,
Handle<Map> map); Handle<Map> map);
Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmExportedFunction( Handle<SharedFunctionInfo> NewSharedFunctionInfoForWasmExportedFunction(
Handle<String> name, Handle<WasmExportedFunctionData> data); Handle<String> name, Handle<WasmExportedFunctionData> data);
......
...@@ -4844,6 +4844,7 @@ class LiftoffCompiler { ...@@ -4844,6 +4844,7 @@ class LiftoffCompiler {
// register for the result. // register for the result.
LiftoffRegister result(instance); LiftoffRegister result(instance);
GenerateCCall(&result, &sig, kVoid, args, ext_ref); GenerateCCall(&result, &sig, kVoid, args, ext_ref);
// TODO(manoskouk): Also throw kDataSegmentOutOfBounds.
Label* trap_label = Label* trap_label =
AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapMemOutOfBounds); AddOutOfLineTrap(decoder, WasmCode::kThrowWasmTrapMemOutOfBounds);
__ emit_cond_jump(kEqual, trap_label, kI32, result.gp()); __ emit_cond_jump(kEqual, trap_label, kI32, result.gp());
......
...@@ -1108,8 +1108,8 @@ class WasmGraphBuildingInterface { ...@@ -1108,8 +1108,8 @@ class WasmGraphBuildingInterface {
for (uint32_t i = 0; i < elements.size(); i++) { for (uint32_t i = 0; i < elements.size(); i++) {
element_nodes[i] = elements[i].node; element_nodes[i] = elements[i].node;
} }
result->node = builder_->ArrayInit(imm.index, imm.array_type, rtt.node, result->node =
VectorOf(element_nodes)); builder_->ArrayInit(imm.array_type, rtt.node, VectorOf(element_nodes));
} }
void I31New(FullDecoder* decoder, const Value& input, Value* result) { void I31New(FullDecoder* decoder, const Value& input, Value* result) {
......
...@@ -19,34 +19,34 @@ namespace wasm { ...@@ -19,34 +19,34 @@ namespace wasm {
void InitExprInterface::I32Const(FullDecoder* decoder, Value* result, void InitExprInterface::I32Const(FullDecoder* decoder, Value* result,
int32_t value) { int32_t value) {
if (isolate_ != nullptr) result->runtime_value = WasmValue(value); if (generate_result()) result->runtime_value = WasmValue(value);
} }
void InitExprInterface::I64Const(FullDecoder* decoder, Value* result, void InitExprInterface::I64Const(FullDecoder* decoder, Value* result,
int64_t value) { int64_t value) {
if (isolate_ != nullptr) result->runtime_value = WasmValue(value); if (generate_result()) result->runtime_value = WasmValue(value);
} }
void InitExprInterface::F32Const(FullDecoder* decoder, Value* result, void InitExprInterface::F32Const(FullDecoder* decoder, Value* result,
float value) { float value) {
if (isolate_ != nullptr) result->runtime_value = WasmValue(value); if (generate_result()) result->runtime_value = WasmValue(value);
} }
void InitExprInterface::F64Const(FullDecoder* decoder, Value* result, void InitExprInterface::F64Const(FullDecoder* decoder, Value* result,
double value) { double value) {
if (isolate_ != nullptr) result->runtime_value = WasmValue(value); if (generate_result()) result->runtime_value = WasmValue(value);
} }
void InitExprInterface::S128Const(FullDecoder* decoder, void InitExprInterface::S128Const(FullDecoder* decoder,
Simd128Immediate<validate>& imm, Simd128Immediate<validate>& imm,
Value* result) { Value* result) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
result->runtime_value = WasmValue(imm.value, kWasmS128); result->runtime_value = WasmValue(imm.value, kWasmS128);
} }
void InitExprInterface::RefNull(FullDecoder* decoder, ValueType type, void InitExprInterface::RefNull(FullDecoder* decoder, ValueType type,
Value* result) { Value* result) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
result->runtime_value = WasmValue(isolate_->factory()->null_value(), type); result->runtime_value = WasmValue(isolate_->factory()->null_value(), type);
} }
...@@ -56,6 +56,7 @@ void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index, ...@@ -56,6 +56,7 @@ void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index,
outer_module_->functions[function_index].declared = true; outer_module_->functions[function_index].declared = true;
return; return;
} }
if (!generate_result()) return;
ValueType type = ValueType::Ref(module_->functions[function_index].sig_index, ValueType type = ValueType::Ref(module_->functions[function_index].sig_index,
kNonNullable); kNonNullable);
Handle<WasmInternalFunction> internal = Handle<WasmInternalFunction> internal =
...@@ -66,7 +67,7 @@ void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index, ...@@ -66,7 +67,7 @@ void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index,
void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result, void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result,
const GlobalIndexImmediate<validate>& imm) { const GlobalIndexImmediate<validate>& imm) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
const WasmGlobal& global = module_->globals[imm.index]; const WasmGlobal& global = module_->globals[imm.index];
DCHECK(!global.mutability); DCHECK(!global.mutability);
result->runtime_value = result->runtime_value =
...@@ -85,7 +86,7 @@ void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result, ...@@ -85,7 +86,7 @@ void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result,
void InitExprInterface::StructNewWithRtt( void InitExprInterface::StructNewWithRtt(
FullDecoder* decoder, const StructIndexImmediate<validate>& imm, FullDecoder* decoder, const StructIndexImmediate<validate>& imm,
const Value& rtt, const Value args[], Value* result) { const Value& rtt, const Value args[], Value* result) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
std::vector<WasmValue> field_values(imm.struct_type->field_count()); std::vector<WasmValue> field_values(imm.struct_type->field_count());
for (size_t i = 0; i < field_values.size(); i++) { for (size_t i = 0; i < field_values.size(); i++) {
field_values[i] = args[i].runtime_value; field_values[i] = args[i].runtime_value;
...@@ -127,7 +128,7 @@ WasmValue DefaultValueForType(ValueType type, Isolate* isolate) { ...@@ -127,7 +128,7 @@ WasmValue DefaultValueForType(ValueType type, Isolate* isolate) {
void InitExprInterface::StructNewDefault( void InitExprInterface::StructNewDefault(
FullDecoder* decoder, const StructIndexImmediate<validate>& imm, FullDecoder* decoder, const StructIndexImmediate<validate>& imm,
const Value& rtt, Value* result) { const Value& rtt, Value* result) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
std::vector<WasmValue> field_values(imm.struct_type->field_count()); std::vector<WasmValue> field_values(imm.struct_type->field_count());
for (uint32_t i = 0; i < field_values.size(); i++) { for (uint32_t i = 0; i < field_values.size(); i++) {
field_values[i] = DefaultValueForType(imm.struct_type->field(i), isolate_); field_values[i] = DefaultValueForType(imm.struct_type->field(i), isolate_);
...@@ -143,11 +144,11 @@ void InitExprInterface::ArrayInit(FullDecoder* decoder, ...@@ -143,11 +144,11 @@ void InitExprInterface::ArrayInit(FullDecoder* decoder,
const ArrayIndexImmediate<validate>& imm, const ArrayIndexImmediate<validate>& imm,
const base::Vector<Value>& elements, const base::Vector<Value>& elements,
const Value& rtt, Value* result) { const Value& rtt, Value* result) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
std::vector<WasmValue> element_values; std::vector<WasmValue> element_values;
for (Value elem : elements) element_values.push_back(elem.runtime_value); for (Value elem : elements) element_values.push_back(elem.runtime_value);
result->runtime_value = result->runtime_value =
WasmValue(isolate_->factory()->NewWasmArray( WasmValue(isolate_->factory()->NewWasmArrayFromElements(
imm.array_type, element_values, imm.array_type, element_values,
Handle<Map>::cast(rtt.runtime_value.to_ref())), Handle<Map>::cast(rtt.runtime_value.to_ref())),
ValueType::Ref(HeapType(imm.index), kNonNullable)); ValueType::Ref(HeapType(imm.index), kNonNullable));
...@@ -155,7 +156,7 @@ void InitExprInterface::ArrayInit(FullDecoder* decoder, ...@@ -155,7 +156,7 @@ void InitExprInterface::ArrayInit(FullDecoder* decoder,
void InitExprInterface::RttCanon(FullDecoder* decoder, uint32_t type_index, void InitExprInterface::RttCanon(FullDecoder* decoder, uint32_t type_index,
Value* result) { Value* result) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
result->runtime_value = WasmValue( result->runtime_value = WasmValue(
handle(instance_->managed_object_maps().get(type_index), isolate_), handle(instance_->managed_object_maps().get(type_index), isolate_),
ValueType::Rtt(type_index, 0)); ValueType::Rtt(type_index, 0));
...@@ -164,7 +165,7 @@ void InitExprInterface::RttCanon(FullDecoder* decoder, uint32_t type_index, ...@@ -164,7 +165,7 @@ void InitExprInterface::RttCanon(FullDecoder* decoder, uint32_t type_index,
void InitExprInterface::RttSub(FullDecoder* decoder, uint32_t type_index, void InitExprInterface::RttSub(FullDecoder* decoder, uint32_t type_index,
const Value& parent, Value* result, const Value& parent, Value* result,
WasmRttSubMode mode) { WasmRttSubMode mode) {
if (isolate_ == nullptr) return; if (!generate_result()) return;
ValueType type = parent.type.has_depth() ValueType type = parent.type.has_depth()
? ValueType::Rtt(type_index, parent.type.depth() + 1) ? ValueType::Rtt(type_index, parent.type.depth() + 1)
: ValueType::Rtt(type_index); : ValueType::Rtt(type_index);
...@@ -180,7 +181,7 @@ void InitExprInterface::DoReturn(FullDecoder* decoder, ...@@ -180,7 +181,7 @@ void InitExprInterface::DoReturn(FullDecoder* decoder,
end_found_ = true; end_found_ = true;
// End decoding on "end". // End decoding on "end".
decoder->set_end(decoder->pc() + 1); decoder->set_end(decoder->pc() + 1);
if (isolate_ != nullptr) result_ = decoder->stack_value(1)->runtime_value; if (generate_result()) result_ = decoder->stack_value(1)->runtime_value;
} }
} // namespace wasm } // namespace wasm
......
...@@ -75,9 +75,13 @@ class InitExprInterface { ...@@ -75,9 +75,13 @@ class InitExprInterface {
return result_; return result_;
} }
bool end_found() { return end_found_; } bool end_found() { return end_found_; }
bool runtime_error() { return error_ != nullptr; }
const char* runtime_error_msg() { return error_; }
private: private:
bool generate_result() { return isolate_ != nullptr && !runtime_error(); }
bool end_found_ = false; bool end_found_ = false;
const char* error_ = nullptr;
WasmValue result_; WasmValue result_;
const WasmModule* module_; const WasmModule* module_;
WasmModule* outer_module_; WasmModule* outer_module_;
......
...@@ -409,15 +409,20 @@ class ModuleDecoderImpl : public Decoder { ...@@ -409,15 +409,20 @@ class ModuleDecoderImpl : public Decoder {
break; break;
case kDataCountSectionCode: case kDataCountSectionCode:
if (!CheckUnorderedSection(section_code)) return; if (!CheckUnorderedSection(section_code)) return;
if (!CheckSectionOrder(section_code, kElementSectionCode, // If wasm-gc is enabled, we allow the data cound section anywhere in
kCodeSectionCode)) // the module.
if (!enabled_features_.has_gc() &&
!CheckSectionOrder(section_code, kElementSectionCode,
kCodeSectionCode)) {
return; return;
}
break; break;
case kTagSectionCode: case kTagSectionCode:
if (!CheckUnorderedSection(section_code)) return; if (!CheckUnorderedSection(section_code)) return;
if (!CheckSectionOrder(section_code, kMemorySectionCode, if (!CheckSectionOrder(section_code, kMemorySectionCode,
kGlobalSectionCode)) kGlobalSectionCode)) {
return; return;
}
break; break;
case kNameSectionCode: case kNameSectionCode:
// TODO(titzer): report out of place name section as a warning. // TODO(titzer): report out of place name section as a warning.
......
...@@ -936,9 +936,10 @@ bool HasDefaultToNumberBehaviour(Isolate* isolate, ...@@ -936,9 +936,10 @@ bool HasDefaultToNumberBehaviour(Isolate* isolate,
return true; return true;
} }
V8_INLINE WasmValue V8_INLINE WasmValue EvaluateInitExpression(Zone* zone, ConstantExpression expr,
EvaluateInitExpression(Zone* zone, ConstantExpression expr, ValueType expected, ValueType expected, Isolate* isolate,
Isolate* isolate, Handle<WasmInstanceObject> instance) { Handle<WasmInstanceObject> instance,
ErrorThrower* thrower) {
switch (expr.kind()) { switch (expr.kind()) {
case ConstantExpression::kEmpty: case ConstantExpression::kEmpty:
UNREACHABLE(); UNREACHABLE();
...@@ -976,6 +977,11 @@ EvaluateInitExpression(Zone* zone, ConstantExpression expr, ValueType expected, ...@@ -976,6 +977,11 @@ EvaluateInitExpression(Zone* zone, ConstantExpression expr, ValueType expected,
decoder.DecodeFunctionBody(); decoder.DecodeFunctionBody();
if (decoder.interface().runtime_error()) {
thrower->RuntimeError("%s", decoder.interface().runtime_error_msg());
return {};
}
return decoder.interface().result(); return decoder.interface().result();
} }
} }
...@@ -1042,17 +1048,20 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) { ...@@ -1042,17 +1048,20 @@ void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
if (module_->is_memory64) { if (module_->is_memory64) {
uint64_t dest_offset_64 = uint64_t dest_offset_64 =
EvaluateInitExpression(&init_expr_zone_, segment.dest_addr, kWasmI64, EvaluateInitExpression(&init_expr_zone_, segment.dest_addr, kWasmI64,
isolate_, instance) isolate_, instance, thrower_)
.to_u64(); .to_u64();
if (thrower_->error()) return;
// Clamp to {std::numeric_limits<size_t>::max()}, which is always an // Clamp to {std::numeric_limits<size_t>::max()}, which is always an
// invalid offset. // invalid offset.
DCHECK_GT(std::numeric_limits<size_t>::max(), instance->memory_size()); DCHECK_GT(std::numeric_limits<size_t>::max(), instance->memory_size());
dest_offset = static_cast<size_t>(std::min( dest_offset = static_cast<size_t>(std::min(
dest_offset_64, uint64_t{std::numeric_limits<size_t>::max()})); dest_offset_64, uint64_t{std::numeric_limits<size_t>::max()}));
} else { } else {
dest_offset = EvaluateInitExpression(&init_expr_zone_, segment.dest_addr, dest_offset =
kWasmI32, isolate_, instance) EvaluateInitExpression(&init_expr_zone_, segment.dest_addr, kWasmI32,
.to_u32(); isolate_, instance, thrower_)
.to_u32();
if (thrower_->error()) return;
} }
if (!base::IsInBounds<size_t>(dest_offset, size, instance->memory_size())) { if (!base::IsInBounds<size_t>(dest_offset, size, instance->memory_size())) {
...@@ -1749,8 +1758,10 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) { ...@@ -1749,8 +1758,10 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
// Happens with imported globals. // Happens with imported globals.
if (!global.init.is_set()) continue; if (!global.init.is_set()) continue;
WasmValue value = EvaluateInitExpression(&init_expr_zone_, global.init, WasmValue value =
global.type, isolate_, instance); EvaluateInitExpression(&init_expr_zone_, global.init, global.type,
isolate_, instance, thrower_);
if (thrower_->error()) return;
if (global.type.is_reference()) { if (global.type.is_reference()) {
tagged_globals_->set(global.offset, *value.to_ref()); tagged_globals_->set(global.offset, *value.to_ref());
...@@ -2014,13 +2025,14 @@ void InstanceBuilder::InitializeNonDefaultableTables( ...@@ -2014,13 +2025,14 @@ void InstanceBuilder::InitializeNonDefaultableTables(
SetFunctionTableNullEntry(isolate_, table_object, entry_index); SetFunctionTableNullEntry(isolate_, table_object, entry_index);
} }
} else { } else {
Handle<Object> value = WasmValue value =
EvaluateInitExpression(&init_expr_zone_, table.initial_value, EvaluateInitExpression(&init_expr_zone_, table.initial_value,
table.type, isolate_, instance) table.type, isolate_, instance, thrower_);
.to_ref(); if (thrower_->error()) return;
for (uint32_t entry_index = 0; entry_index < table.initial_size; for (uint32_t entry_index = 0; entry_index < table.initial_size;
entry_index++) { entry_index++) {
WasmTableObject::Set(isolate_, table_object, entry_index, value); WasmTableObject::Set(isolate_, table_object, entry_index,
value.to_ref());
} }
} }
} }
...@@ -2050,6 +2062,8 @@ bool LoadElemSegmentImpl(Zone* zone, Isolate* isolate, ...@@ -2050,6 +2062,8 @@ bool LoadElemSegmentImpl(Zone* zone, Isolate* isolate,
bool is_function_table = bool is_function_table =
IsSubtypeOf(table_object->type(), kWasmFuncRef, instance->module()); IsSubtypeOf(table_object->type(), kWasmFuncRef, instance->module());
ErrorThrower thrower(isolate, "LoadElemSegment");
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
ConstantExpression entry = elem_segment.entries[src + i]; ConstantExpression entry = elem_segment.entries[src + i];
int entry_index = static_cast<int>(dst + i); int entry_index = static_cast<int>(dst + i);
...@@ -2060,11 +2074,10 @@ bool LoadElemSegmentImpl(Zone* zone, Isolate* isolate, ...@@ -2060,11 +2074,10 @@ bool LoadElemSegmentImpl(Zone* zone, Isolate* isolate,
entry.kind() == ConstantExpression::kRefNull) { entry.kind() == ConstantExpression::kRefNull) {
SetFunctionTableNullEntry(isolate, table_object, entry_index); SetFunctionTableNullEntry(isolate, table_object, entry_index);
} else { } else {
Handle<Object> value = WasmValue value = EvaluateInitExpression(zone, entry, elem_segment.type,
EvaluateInitExpression(zone, entry, elem_segment.type, isolate, isolate, instance, &thrower);
instance) if (thrower.error()) return false;
.to_ref(); WasmTableObject::Set(isolate, table_object, entry_index, value.to_ref());
WasmTableObject::Set(isolate, table_object, entry_index, value);
} }
} }
return true; return true;
...@@ -2079,9 +2092,11 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) { ...@@ -2079,9 +2092,11 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
if (elem_segment.status != WasmElemSegment::kStatusActive) continue; if (elem_segment.status != WasmElemSegment::kStatusActive) continue;
uint32_t table_index = elem_segment.table_index; uint32_t table_index = elem_segment.table_index;
uint32_t dst = EvaluateInitExpression(&init_expr_zone_, elem_segment.offset, uint32_t dst =
kWasmI32, isolate_, instance) EvaluateInitExpression(&init_expr_zone_, elem_segment.offset, kWasmI32,
.to_u32(); isolate_, instance, thrower_)
.to_u32();
if (thrower_->error()) return;
uint32_t src = 0; uint32_t src = 0;
size_t count = elem_segment.entries.size(); size_t count = elem_segment.entries.size();
......
...@@ -967,12 +967,15 @@ class WasmArray : public TorqueGeneratedWasmArray<WasmArray, WasmObject> { ...@@ -967,12 +967,15 @@ class WasmArray : public TorqueGeneratedWasmArray<WasmArray, WasmObject> {
inline uint32_t element_offset(uint32_t index); inline uint32_t element_offset(uint32_t index);
inline Address ElementAddress(uint32_t index); inline Address ElementAddress(uint32_t index);
static int MaxLength(const wasm::ArrayType* type) { static int MaxLength(uint32_t element_size_log2) {
// The total object size must fit into a Smi, for filler objects. To make // The total object size must fit into a Smi, for filler objects. To make
// the behavior of Wasm programs independent from the Smi configuration, // the behavior of Wasm programs independent from the Smi configuration,
// we hard-code the smaller of the two supported ranges. // we hard-code the smaller of the two supported ranges.
int element_shift = type->element_type().element_size_log2(); return (SmiTagging<4>::kSmiMaxValue - kHeaderSize) >> element_size_log2;
return (SmiTagging<4>::kSmiMaxValue - kHeaderSize) >> element_shift; }
static int MaxLength(const wasm::ArrayType* type) {
return MaxLength(type->element_type().element_size_log2());
} }
static inline void EncodeElementSizeInMap(int element_size, Map map); static inline void EncodeElementSizeInMap(int element_size, Map map);
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
(function() { (function TestNominalTypesBasic() {
print(arguments.callee.name);
var builder = new WasmModuleBuilder(); var builder = new WasmModuleBuilder();
let struct1 = builder.addStructSubtype([makeField(kWasmI32, true)]); let struct1 = builder.addStructSubtype([makeField(kWasmI32, true)]);
let struct2 = builder.addStructSubtype( let struct2 = builder.addStructSubtype(
...@@ -42,13 +43,14 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -42,13 +43,14 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
builder.instantiate(); builder.instantiate();
})(); })();
(function () { (function TestSubtypingDepthTooLarge() {
let builder = new WasmModuleBuilder(); print(arguments.callee.name);
let t0 = builder.addStructSubtype([]); let builder = new WasmModuleBuilder();
for (let i = 0; i < 32; i++) { builder.addStructSubtype([]);
builder.addStructSubtype([], i); for (let i = 0; i < 32; i++) {
} builder.addStructSubtype([], i);
assertThrows( }
() => builder.instantiate(), WebAssembly.CompileError, assertThrows(
/subtyping depth is greater than allowed/); () => builder.instantiate(), WebAssembly.CompileError,
/subtyping depth is greater than allowed/);
})(); })();
...@@ -867,9 +867,10 @@ let kTrapFloatUnrepresentable = 5; ...@@ -867,9 +867,10 @@ let kTrapFloatUnrepresentable = 5;
let kTrapTableOutOfBounds = 6; let kTrapTableOutOfBounds = 6;
let kTrapFuncSigMismatch = 7; let kTrapFuncSigMismatch = 7;
let kTrapUnalignedAccess = 8; let kTrapUnalignedAccess = 8;
let kTrapDataSegmentDropped = 9; let kTrapDataSegmentOutOfBounds = 9;
let kTrapElemSegmentDropped = 10; let kTrapElemSegmentDropped = 10;
let kTrapRethrowNull = 11; let kTrapRethrowNull = 11;
let kTrapArrayTooLarge = 12;
let kTrapMsgs = [ let kTrapMsgs = [
'unreachable', // -- 'unreachable', // --
...@@ -881,9 +882,10 @@ let kTrapMsgs = [ ...@@ -881,9 +882,10 @@ let kTrapMsgs = [
'table index is out of bounds', // -- 'table index is out of bounds', // --
'null function or function signature mismatch', // -- 'null function or function signature mismatch', // --
'operation does not support unaligned accesses', // -- 'operation does not support unaligned accesses', // --
'data segment has been dropped', // -- 'data segment out of bounds', // --
'element segment has been dropped', // -- 'element segment has been dropped', // --
'rethrowing null value' // -- 'rethrowing null value', // --
'requested new array is too large' // --
]; ];
// This requires test/mjsunit/mjsunit.js. // This requires test/mjsunit/mjsunit.js.
...@@ -1364,6 +1366,7 @@ class WasmModuleBuilder { ...@@ -1364,6 +1366,7 @@ class WasmModuleBuilder {
this.num_imported_globals = 0; this.num_imported_globals = 0;
this.num_imported_tables = 0; this.num_imported_tables = 0;
this.num_imported_tags = 0; this.num_imported_tags = 0;
this.early_data_count_section = false;
return this; return this;
} }
...@@ -1768,6 +1771,14 @@ class WasmModuleBuilder { ...@@ -1768,6 +1771,14 @@ class WasmModuleBuilder {
}); });
} }
// If there are any passive data segments, add the DataCount section.
if (this.early_data_count_section &&
wasm.data_segments.some(seg => !seg.is_active)) {
binary.emit_section(kDataCountSectionCode, section => {
section.emit_u32v(wasm.data_segments.length);
});
}
// Add table section // Add table section
if (wasm.tables.length > 0) { if (wasm.tables.length > 0) {
if (debug) print('emitting tables @ ' + binary.length); if (debug) print('emitting tables @ ' + binary.length);
...@@ -1930,7 +1941,8 @@ class WasmModuleBuilder { ...@@ -1930,7 +1941,8 @@ class WasmModuleBuilder {
} }
// If there are any passive data segments, add the DataCount section. // If there are any passive data segments, add the DataCount section.
if (wasm.data_segments.some(seg => !seg.is_active)) { if (!this.early_data_count_section &&
wasm.data_segments.some(seg => !seg.is_active)) {
binary.emit_section(kDataCountSectionCode, section => { binary.emit_section(kDataCountSectionCode, section => {
section.emit_u32v(wasm.data_segments.length); section.emit_u32v(wasm.data_segments.length);
}); });
......
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