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
16 namespace v8 {
17 namespace internal {
18 namespace wasm {
19
I32Const(FullDecoder* decoder, Value* result, int32_t value)20 void InitExprInterface::I32Const(FullDecoder* decoder, Value* result,
21 int32_t value) {
22 if (generate_result()) result->runtime_value = WasmValue(value);
23 }
24
I64Const(FullDecoder* decoder, Value* result, int64_t value)25 void InitExprInterface::I64Const(FullDecoder* decoder, Value* result,
26 int64_t value) {
27 if (generate_result()) result->runtime_value = WasmValue(value);
28 }
29
F32Const(FullDecoder* decoder, Value* result, float value)30 void InitExprInterface::F32Const(FullDecoder* decoder, Value* result,
31 float value) {
32 if (generate_result()) result->runtime_value = WasmValue(value);
33 }
34
F64Const(FullDecoder* decoder, Value* result, double value)35 void InitExprInterface::F64Const(FullDecoder* decoder, Value* result,
36 double value) {
37 if (generate_result()) result->runtime_value = WasmValue(value);
38 }
39
S128Const(FullDecoder* decoder, Simd128Immediate<validate>& imm, Value* result)40 void 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
BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs, const Value& rhs, Value* result)47 void 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
RefNull(FullDecoder* decoder, ValueType type, Value* result)81 void 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
RefFunc(FullDecoder* decoder, uint32_t function_index, Value* result)87 void 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
GlobalGet(FullDecoder* decoder, Value* result, const GlobalIndexImmediate<validate>& imm)102 void 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
StructNewWithRtt( FullDecoder* decoder, const StructIndexImmediate<validate>& imm, const Value& rtt, const Value args[], Value* result)120 void 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
135 namespace {
DefaultValueForType(ValueType type, Isolate* isolate)136 WasmValue 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
StructNewDefault( FullDecoder* decoder, const StructIndexImmediate<validate>& imm, const Value& rtt, Value* result)161 void 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
ArrayInit(FullDecoder* decoder, const ArrayIndexImmediate<validate>& imm, const base::Vector<Value>& elements, const Value& rtt, Value* result)176 void 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
ArrayInitFromData( FullDecoder* decoder, const ArrayIndexImmediate<validate>& array_imm, const IndexImmediate<validate>& data_segment_imm, const Value& offset_value, const Value& length_value, const Value& rtt, Value* result)190 void 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
RttCanon(FullDecoder* decoder, uint32_t type_index, Value* result)223 void 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
DoReturn(FullDecoder* decoder, uint32_t )231 void 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