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