1// Copyright 2021 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/wasm/init-expr-interface.h" 6 7#include "src/execution/isolate.h" 8#include "src/handles/handles-inl.h" 9#include "src/objects/fixed-array-inl.h" 10#include "src/objects/oddball.h" 11#include "src/roots/roots-inl.h" 12#include "src/wasm/decoder.h" 13#include "src/wasm/function-body-decoder-impl.h" 14#include "src/wasm/wasm-objects.h" 15 16namespace v8 { 17namespace internal { 18namespace wasm { 19 20void InitExprInterface::I32Const(FullDecoder* decoder, Value* result, 21 int32_t value) { 22 if (generate_result()) result->runtime_value = WasmValue(value); 23} 24 25void InitExprInterface::I64Const(FullDecoder* decoder, Value* result, 26 int64_t value) { 27 if (generate_result()) result->runtime_value = WasmValue(value); 28} 29 30void InitExprInterface::F32Const(FullDecoder* decoder, Value* result, 31 float value) { 32 if (generate_result()) result->runtime_value = WasmValue(value); 33} 34 35void InitExprInterface::F64Const(FullDecoder* decoder, Value* result, 36 double value) { 37 if (generate_result()) result->runtime_value = WasmValue(value); 38} 39 40void InitExprInterface::S128Const(FullDecoder* decoder, 41 Simd128Immediate<validate>& imm, 42 Value* result) { 43 if (!generate_result()) return; 44 result->runtime_value = WasmValue(imm.value, kWasmS128); 45} 46 47void InitExprInterface::BinOp(FullDecoder* decoder, WasmOpcode opcode, 48 const Value& lhs, const Value& rhs, 49 Value* result) { 50 if (!generate_result()) return; 51 switch (opcode) { 52 case kExprI32Add: 53 result->runtime_value = 54 WasmValue(lhs.runtime_value.to_i32() + rhs.runtime_value.to_i32()); 55 break; 56 case kExprI32Sub: 57 result->runtime_value = 58 WasmValue(lhs.runtime_value.to_i32() - rhs.runtime_value.to_i32()); 59 break; 60 case kExprI32Mul: 61 result->runtime_value = 62 WasmValue(lhs.runtime_value.to_i32() * rhs.runtime_value.to_i32()); 63 break; 64 case kExprI64Add: 65 result->runtime_value = 66 WasmValue(lhs.runtime_value.to_i64() + rhs.runtime_value.to_i64()); 67 break; 68 case kExprI64Sub: 69 result->runtime_value = 70 WasmValue(lhs.runtime_value.to_i64() - rhs.runtime_value.to_i64()); 71 break; 72 case kExprI64Mul: 73 result->runtime_value = 74 WasmValue(lhs.runtime_value.to_i64() * rhs.runtime_value.to_i64()); 75 break; 76 default: 77 UNREACHABLE(); 78 } 79} 80 81void InitExprInterface::RefNull(FullDecoder* decoder, ValueType type, 82 Value* result) { 83 if (!generate_result()) return; 84 result->runtime_value = WasmValue(isolate_->factory()->null_value(), type); 85} 86 87void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index, 88 Value* result) { 89 if (isolate_ == nullptr) { 90 outer_module_->functions[function_index].declared = true; 91 return; 92 } 93 if (!generate_result()) return; 94 ValueType type = ValueType::Ref(module_->functions[function_index].sig_index, 95 kNonNullable); 96 Handle<WasmInternalFunction> internal = 97 WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate_, instance_, 98 function_index); 99 result->runtime_value = WasmValue(internal, type); 100} 101 102void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result, 103 const GlobalIndexImmediate<validate>& imm) { 104 if (!generate_result()) return; 105 const WasmGlobal& global = module_->globals[imm.index]; 106 DCHECK(!global.mutability); 107 result->runtime_value = 108 global.type.is_numeric() 109 ? WasmValue( 110 reinterpret_cast<byte*>( 111 instance_->untagged_globals_buffer().backing_store()) + 112 global.offset, 113 global.type) 114 : WasmValue( 115 handle(instance_->tagged_globals_buffer().get(global.offset), 116 isolate_), 117 global.type); 118} 119 120void InitExprInterface::StructNewWithRtt( 121 FullDecoder* decoder, const StructIndexImmediate<validate>& imm, 122 const Value& rtt, const Value args[], Value* result) { 123 if (!generate_result()) return; 124 std::vector<WasmValue> field_values(imm.struct_type->field_count()); 125 for (size_t i = 0; i < field_values.size(); i++) { 126 field_values[i] = args[i].runtime_value; 127 } 128 result->runtime_value = 129 WasmValue(isolate_->factory()->NewWasmStruct( 130 imm.struct_type, field_values.data(), 131 Handle<Map>::cast(rtt.runtime_value.to_ref())), 132 ValueType::Ref(HeapType(imm.index), kNonNullable)); 133} 134 135namespace { 136WasmValue DefaultValueForType(ValueType type, Isolate* isolate) { 137 switch (type.kind()) { 138 case kI32: 139 case kI8: 140 case kI16: 141 return WasmValue(0); 142 case kI64: 143 return WasmValue(int64_t{0}); 144 case kF32: 145 return WasmValue(0.0f); 146 case kF64: 147 return WasmValue(0.0); 148 case kS128: 149 return WasmValue(Simd128()); 150 case kOptRef: 151 return WasmValue(isolate->factory()->null_value(), type); 152 case kVoid: 153 case kRtt: 154 case kRef: 155 case kBottom: 156 UNREACHABLE(); 157 } 158} 159} // namespace 160 161void InitExprInterface::StructNewDefault( 162 FullDecoder* decoder, const StructIndexImmediate<validate>& imm, 163 const Value& rtt, Value* result) { 164 if (!generate_result()) return; 165 std::vector<WasmValue> field_values(imm.struct_type->field_count()); 166 for (uint32_t i = 0; i < field_values.size(); i++) { 167 field_values[i] = DefaultValueForType(imm.struct_type->field(i), isolate_); 168 } 169 result->runtime_value = 170 WasmValue(isolate_->factory()->NewWasmStruct( 171 imm.struct_type, field_values.data(), 172 Handle<Map>::cast(rtt.runtime_value.to_ref())), 173 ValueType::Ref(HeapType(imm.index), kNonNullable)); 174} 175 176void InitExprInterface::ArrayInit(FullDecoder* decoder, 177 const ArrayIndexImmediate<validate>& imm, 178 const base::Vector<Value>& elements, 179 const Value& rtt, Value* result) { 180 if (!generate_result()) return; 181 std::vector<WasmValue> element_values; 182 for (Value elem : elements) element_values.push_back(elem.runtime_value); 183 result->runtime_value = 184 WasmValue(isolate_->factory()->NewWasmArrayFromElements( 185 imm.array_type, element_values, 186 Handle<Map>::cast(rtt.runtime_value.to_ref())), 187 ValueType::Ref(HeapType(imm.index), kNonNullable)); 188} 189 190void InitExprInterface::ArrayInitFromData( 191 FullDecoder* decoder, const ArrayIndexImmediate<validate>& array_imm, 192 const IndexImmediate<validate>& data_segment_imm, const Value& offset_value, 193 const Value& length_value, const Value& rtt, Value* result) { 194 if (!generate_result()) return; 195 196 uint32_t length = length_value.runtime_value.to_u32(); 197 uint32_t offset = offset_value.runtime_value.to_u32(); 198 const WasmDataSegment& data_segment = 199 module_->data_segments[data_segment_imm.index]; 200 uint32_t length_in_bytes = 201 length * array_imm.array_type->element_type().value_kind_size(); 202 203 // Error handling. 204 if (length > 205 static_cast<uint32_t>(WasmArray::MaxLength(array_imm.array_type))) { 206 error_ = "length for array.init_from_data too large"; 207 return; 208 } 209 if (!base::IsInBounds<uint32_t>(offset, length_in_bytes, 210 data_segment.source.length())) { 211 error_ = "data segment is out of bounds"; 212 return; 213 } 214 215 Address source = 216 instance_->data_segment_starts()[data_segment_imm.index] + offset; 217 Handle<WasmArray> array_value = isolate_->factory()->NewWasmArrayFromMemory( 218 length, Handle<Map>::cast(rtt.runtime_value.to_ref()), source); 219 result->runtime_value = WasmValue( 220 array_value, ValueType::Ref(HeapType(array_imm.index), kNonNullable)); 221} 222 223void InitExprInterface::RttCanon(FullDecoder* decoder, uint32_t type_index, 224 Value* result) { 225 if (!generate_result()) return; 226 result->runtime_value = WasmValue( 227 handle(instance_->managed_object_maps().get(type_index), isolate_), 228 ValueType::Rtt(type_index)); 229} 230 231void InitExprInterface::DoReturn(FullDecoder* decoder, 232 uint32_t /*drop_values*/) { 233 end_found_ = true; 234 // End decoding on "end". 235 decoder->set_end(decoder->pc() + 1); 236 if (generate_result()) result_ = decoder->stack_value(1)->runtime_value; 237} 238 239} // namespace wasm 240} // namespace internal 241} // namespace v8 242