init-expr-interface.cc 8.67 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/wasm/init-expr-interface.h"

#include "src/execution/isolate.h"
#include "src/handles/handles-inl.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/oddball.h"
#include "src/roots/roots-inl.h"
#include "src/wasm/decoder.h"
#include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/wasm-objects.h"

namespace v8 {
namespace internal {
namespace wasm {

void InitExprInterface::I32Const(FullDecoder* decoder, Value* result,
                                 int32_t value) {
22
  if (generate_result()) result->runtime_value = WasmValue(value);
23 24 25 26
}

void InitExprInterface::I64Const(FullDecoder* decoder, Value* result,
                                 int64_t value) {
27
  if (generate_result()) result->runtime_value = WasmValue(value);
28 29 30 31
}

void InitExprInterface::F32Const(FullDecoder* decoder, Value* result,
                                 float value) {
32
  if (generate_result()) result->runtime_value = WasmValue(value);
33 34 35 36
}

void InitExprInterface::F64Const(FullDecoder* decoder, Value* result,
                                 double value) {
37
  if (generate_result()) result->runtime_value = WasmValue(value);
38 39 40 41 42
}

void InitExprInterface::S128Const(FullDecoder* decoder,
                                  Simd128Immediate<validate>& imm,
                                  Value* result) {
43
  if (!generate_result()) return;
44 45 46
  result->runtime_value = WasmValue(imm.value, kWasmS128);
}

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
void InitExprInterface::BinOp(FullDecoder* decoder, WasmOpcode opcode,
                              const Value& lhs, const Value& rhs,
                              Value* result) {
  if (!generate_result()) return;
  switch (opcode) {
    case kExprI32Add:
      result->runtime_value =
          WasmValue(lhs.runtime_value.to_i32() + rhs.runtime_value.to_i32());
      break;
    case kExprI32Sub:
      result->runtime_value =
          WasmValue(lhs.runtime_value.to_i32() - rhs.runtime_value.to_i32());
      break;
    case kExprI32Mul:
      result->runtime_value =
          WasmValue(lhs.runtime_value.to_i32() * rhs.runtime_value.to_i32());
      break;
    case kExprI64Add:
      result->runtime_value =
          WasmValue(lhs.runtime_value.to_i64() + rhs.runtime_value.to_i64());
      break;
    case kExprI64Sub:
      result->runtime_value =
          WasmValue(lhs.runtime_value.to_i64() - rhs.runtime_value.to_i64());
      break;
    case kExprI64Mul:
      result->runtime_value =
          WasmValue(lhs.runtime_value.to_i64() * rhs.runtime_value.to_i64());
      break;
    default:
      UNREACHABLE();
  }
}

81 82
void InitExprInterface::RefNull(FullDecoder* decoder, ValueType type,
                                Value* result) {
83
  if (!generate_result()) return;
84 85 86 87 88
  result->runtime_value = WasmValue(isolate_->factory()->null_value(), type);
}

void InitExprInterface::RefFunc(FullDecoder* decoder, uint32_t function_index,
                                Value* result) {
89
  if (isolate_ == nullptr) {
90
    outer_module_->functions[function_index].declared = true;
91 92
    return;
  }
93
  if (!generate_result()) return;
94 95
  ValueType type = ValueType::Ref(module_->functions[function_index].sig_index,
                                  kNonNullable);
96 97 98 99
  Handle<WasmInternalFunction> internal =
      WasmInstanceObject::GetOrCreateWasmInternalFunction(isolate_, instance_,
                                                          function_index);
  result->runtime_value = WasmValue(internal, type);
100 101 102 103
}

void InitExprInterface::GlobalGet(FullDecoder* decoder, Value* result,
                                  const GlobalIndexImmediate<validate>& imm) {
104
  if (!generate_result()) return;
105
  const WasmGlobal& global = module_->globals[imm.index];
106
  DCHECK(!global.mutability);
107 108
  result->runtime_value =
      global.type.is_numeric()
109 110 111 112 113 114 115 116 117
          ? WasmValue(
                reinterpret_cast<byte*>(
                    instance_->untagged_globals_buffer().backing_store()) +
                    global.offset,
                global.type)
          : WasmValue(
                handle(instance_->tagged_globals_buffer().get(global.offset),
                       isolate_),
                global.type);
118 119 120 121 122
}

void InitExprInterface::StructNewWithRtt(
    FullDecoder* decoder, const StructIndexImmediate<validate>& imm,
    const Value& rtt, const Value args[], Value* result) {
123
  if (!generate_result()) return;
124 125 126 127 128 129 130 131 132 133 134
  std::vector<WasmValue> field_values(imm.struct_type->field_count());
  for (size_t i = 0; i < field_values.size(); i++) {
    field_values[i] = args[i].runtime_value;
  }
  result->runtime_value =
      WasmValue(isolate_->factory()->NewWasmStruct(
                    imm.struct_type, field_values.data(),
                    Handle<Map>::cast(rtt.runtime_value.to_ref())),
                ValueType::Ref(HeapType(imm.index), kNonNullable));
}

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
namespace {
WasmValue DefaultValueForType(ValueType type, Isolate* isolate) {
  switch (type.kind()) {
    case kI32:
    case kI8:
    case kI16:
      return WasmValue(0);
    case kI64:
      return WasmValue(int64_t{0});
    case kF32:
      return WasmValue(0.0f);
    case kF64:
      return WasmValue(0.0);
    case kS128:
      return WasmValue(Simd128());
    case kOptRef:
      return WasmValue(isolate->factory()->null_value(), type);
    case kVoid:
    case kRtt:
    case kRef:
    case kBottom:
      UNREACHABLE();
  }
}
}  // namespace

void InitExprInterface::StructNewDefault(
    FullDecoder* decoder, const StructIndexImmediate<validate>& imm,
    const Value& rtt, Value* result) {
164
  if (!generate_result()) return;
165 166 167 168 169 170 171 172 173 174 175
  std::vector<WasmValue> field_values(imm.struct_type->field_count());
  for (uint32_t i = 0; i < field_values.size(); i++) {
    field_values[i] = DefaultValueForType(imm.struct_type->field(i), isolate_);
  }
  result->runtime_value =
      WasmValue(isolate_->factory()->NewWasmStruct(
                    imm.struct_type, field_values.data(),
                    Handle<Map>::cast(rtt.runtime_value.to_ref())),
                ValueType::Ref(HeapType(imm.index), kNonNullable));
}

176 177 178 179
void InitExprInterface::ArrayInit(FullDecoder* decoder,
                                  const ArrayIndexImmediate<validate>& imm,
                                  const base::Vector<Value>& elements,
                                  const Value& rtt, Value* result) {
180
  if (!generate_result()) return;
181 182 183
  std::vector<WasmValue> element_values;
  for (Value elem : elements) element_values.push_back(elem.runtime_value);
  result->runtime_value =
184
      WasmValue(isolate_->factory()->NewWasmArrayFromElements(
185 186 187 188 189
                    imm.array_type, element_values,
                    Handle<Map>::cast(rtt.runtime_value.to_ref())),
                ValueType::Ref(HeapType(imm.index), kNonNullable));
}

190 191 192 193 194 195 196 197 198 199 200
void InitExprInterface::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) {
  if (!generate_result()) return;

  uint32_t length = length_value.runtime_value.to_u32();
  uint32_t offset = offset_value.runtime_value.to_u32();
  const WasmDataSegment& data_segment =
      module_->data_segments[data_segment_imm.index];
  uint32_t length_in_bytes =
201
      length * array_imm.array_type->element_type().value_kind_size();
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222

  // Error handling.
  if (length >
      static_cast<uint32_t>(WasmArray::MaxLength(array_imm.array_type))) {
    error_ = "length for array.init_from_data too large";
    return;
  }
  if (!base::IsInBounds<uint32_t>(offset, length_in_bytes,
                                  data_segment.source.length())) {
    error_ = "data segment is out of bounds";
    return;
  }

  Address source =
      instance_->data_segment_starts()[data_segment_imm.index] + offset;
  Handle<WasmArray> array_value = isolate_->factory()->NewWasmArrayFromMemory(
      length, Handle<Map>::cast(rtt.runtime_value.to_ref()), source);
  result->runtime_value = WasmValue(
      array_value, ValueType::Ref(HeapType(array_imm.index), kNonNullable));
}

223 224
void InitExprInterface::RttCanon(FullDecoder* decoder, uint32_t type_index,
                                 Value* result) {
225
  if (!generate_result()) return;
226 227
  result->runtime_value = WasmValue(
      handle(instance_->managed_object_maps().get(type_index), isolate_),
228
      ValueType::Rtt(type_index));
229 230 231 232 233 234 235
}

void InitExprInterface::DoReturn(FullDecoder* decoder,
                                 uint32_t /*drop_values*/) {
  end_found_ = true;
  // End decoding on "end".
  decoder->set_end(decoder->pc() + 1);
236
  if (generate_result()) result_ = decoder->stack_value(1)->runtime_value;
237 238 239 240 241
}

}  // namespace wasm
}  // namespace internal
}  // namespace v8