21using wasm::WasmOpcodes;
25class WasmIntoJSInlinerImpl :
private wasm::Decoder {
26 using ValidationTag = NoValidationTag;
34 WasmIntoJSInlinerImpl(
Zone* zone,
const wasm::WasmModule* module,
35 MachineGraph* mcgraph,
const wasm::FunctionBody& body,
36 base::Vector<const uint8_t> bytes,
37 SourcePositionTable* source_position_table,
48 size_t params = body.sig->parameter_count() + 1;
50 graph_->NewNode(mcgraph->common()->Start(
static_cast<int>(params)));
52 graph_->SetEnd(
graph_->NewNode(mcgraph->common()->End(0)));
58 size_t params_extended = params + 1;
59 parameters_ = zone->AllocateArray<Node*>(params_extended);
60 for (
unsigned i = 0;
i < params_extended;
i++) {
67 Node* Param(
int index,
const char* debug_name =
nullptr) {
72 if (parameters_[array_index] ==
nullptr) {
73 Node* param =
graph_->NewNode(
74 mcgraph_->common()->Parameter(index, debug_name),
graph_->start());
78 wasm::ValueType type =
body_.sig->GetParam(index - 1);
79 Type tf_type = compiler::Type::Wasm(type, module_,
graph_->zone());
80 param =
gasm_.TypeGuard(tf_type, param);
88 if (
body_.sig->return_count() > 1) {
92 if (consume_u32v() != 0) {
97 base::SmallVector<Value, 4>
stack;
98 while (is_inlineable_) {
101 case wasm::kExprAnyConvertExtern:
103 stack.back() = ParseAnyConvertExtern(stack.back());
105 case wasm::kExprExternConvertAny:
107 stack.back() = ParseExternConvertAny(stack.back());
109 case wasm::kExprRefCast:
110 case wasm::kExprRefCastNull:
113 ParseRefCast(stack.back(), opcode == wasm::kExprRefCastNull);
115 case wasm::kExprArrayLen:
117 stack.back() = ParseArrayLen(stack.back());
119 case wasm::kExprArrayGet:
120 case wasm::kExprArrayGetS:
121 case wasm::kExprArrayGetU: {
123 Value index = stack.back();
125 Value array = stack.back();
126 stack.back() = ParseArrayGet(array, index, opcode);
129 case wasm::kExprArraySet: {
131 Value value = stack.back();
133 Value index = stack.back();
135 Value array = stack.back();
137 ParseArraySet(array, index, value);
140 case wasm::kExprStructGet:
141 case wasm::kExprStructGetS:
142 case wasm::kExprStructGetU:
144 stack.back() = ParseStructGet(stack.back(), opcode);
146 case wasm::kExprStructSet: {
148 Value value = stack.back();
150 Value wasm_struct = stack.back();
152 ParseStructSet(wasm_struct, value);
155 case wasm::kExprLocalGet:
156 stack.push_back(ParseLocalGet());
158 case wasm::kExprDrop:
162 case wasm::kExprEnd: {
164 int return_count =
static_cast<int>(stack.size());
165 base::SmallVector<Node*, 8> buf(return_count + 3);
166 buf[0] =
mcgraph_->Int32Constant(0);
168 buf[1] = stack.back().node;
170 buf[return_count + 1] =
gasm_.effect();
171 buf[return_count + 2] =
gasm_.control();
172 Node* ret =
graph_->NewNode(
mcgraph_->common()->Return(return_count),
173 return_count + 3, buf.data());
175 gasm_.MergeControlToEnd(ret);
188 Value ParseAnyConvertExtern(Value input) {
192 wasm::GenericKind::kAny, input.type.nullability(),
kNotShared);
193 Node* internalized =
gasm_.WasmAnyConvertExtern(input.node);
194 return TypeNode(internalized, result_type);
197 Value ParseExternConvertAny(Value input) {
198 DCHECK(input.type.is_reference());
200 wasm::GenericKind::kExtern, input.type.nullability(),
kNotShared);
201 Node* internalized =
gasm_.WasmExternConvertAny(input.node);
202 return TypeNode(internalized, result_type);
205 Value ParseLocalGet() {
206 uint32_t index = consume_u32v();
208 return TypeNode(Param(index + 1),
body_.sig->GetParam(index));
211 Value ParseStructGet(Value struct_val,
WasmOpcode opcode) {
212 wasm::ModuleTypeIndex struct_index{consume_u32v()};
214 const wasm::StructType* struct_type =
module_->struct_type(struct_index);
215 uint32_t field_index = consume_u32v();
216 DCHECK_GT(struct_type->field_count(), field_index);
217 const bool is_signed = opcode == wasm::kExprStructGetS;
220 Node* member =
gasm_.StructGet(struct_val.node, struct_type, field_index,
222 SetSourcePosition(member);
223 return TypeNode(member, struct_type->field(field_index).Unpacked());
226 void ParseStructSet(Value wasm_struct, Value value) {
227 wasm::ModuleTypeIndex struct_index{consume_u32v()};
229 const wasm::StructType* struct_type =
module_->struct_type(struct_index);
230 uint32_t field_index = consume_u32v();
231 DCHECK_GT(struct_type->field_count(), field_index);
234 gasm_.StructSet(wasm_struct.node, value.node, struct_type, field_index,
236 SetSourcePosition(
gasm_.effect());
240 auto [heap_index,
length] = read_i33v<ValidationTag>(
pc_);
242 if (heap_index < 0) {
248 auto done =
gasm_.MakeLabel();
251 gasm_.GotoIf(
gasm_.IsNull(input.node, input.type), &done);
253 gasm_.TrapIf(
gasm_.IsSmi(input.node), TrapId::kTrapIllegalCast);
254 gasm_.TrapUnless(
gasm_.HasInstanceType(input.node, WASM_ARRAY_TYPE),
255 TrapId::kTrapIllegalCast);
256 SetSourcePosition(
gasm_.effect());
262 wasm::GenericKind::kArray,
265 graph->NewNode(
mcgraph_->common()->TypeGuard(
266 Type::Wasm(result_type, module_, graph->zone())),
268 gasm_.InitializeEffectControl(type_guard,
gasm_.control());
269 return TypeNode(type_guard, result_type);
271 wasm::ModuleTypeIndex target_type_index{
static_cast<uint32_t
>(heap_index)};
272 if (
module_->has_signature(target_type_index)) {
277 module_->heap_type(target_type_index),
279 Node* rtt =
mcgraph_->graph()->NewNode(
280 gasm_.simplified()->RttCanon(target_type.ref_index()),
289 {input.type, target_type,
290 module_->type(target_type_index).is_final ? kExactMatchOnly
292 SetSourcePosition(
cast);
293 return TypeNode(
cast, target_type);
296 Value ParseArrayLen(Value input) {
301 Node* len =
gasm_.ArrayLength(input.node, null_check);
302 SetSourcePosition(len);
306 Value ParseArrayGet(Value array, Value index,
WasmOpcode opcode) {
307 wasm::ModuleTypeIndex array_index{consume_u32v()};
309 const wasm::ArrayType* array_type =
module_->array_type(array_index);
310 const bool is_signed = opcode == WasmOpcode::kExprArrayGetS;
314 Node* length =
gasm_.ArrayLength(array.node, null_check);
315 SetSourcePosition(length);
316 gasm_.TrapUnless(
gasm_.Uint32LessThan(index.node, length),
317 TrapId::kTrapArrayOutOfBounds);
318 SetSourcePosition(
gasm_.effect());
322 return TypeNode(element, array_type->element_type().Unpacked());
325 void ParseArraySet(Value array, Value index, Value value) {
326 wasm::ModuleTypeIndex array_index{consume_u32v()};
328 const wasm::ArrayType* array_type =
module_->array_type(array_index);
332 Node* length =
gasm_.ArrayLength(array.node, null_check);
333 SetSourcePosition(length);
334 gasm_.TrapUnless(
gasm_.Uint32LessThan(index.node, length),
335 TrapId::kTrapArrayOutOfBounds);
336 SetSourcePosition(
gasm_.effect());
338 gasm_.ArraySet(array.node, index.node, value.node, array_type);
345 if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
349 auto [opcode_with_prefix,
length] =
350 read_prefixed_opcode<ValidationTag>(
pc_);
352 return opcode_with_prefix;
355 Value TypeNode(Node* node, wasm::ValueType type) {
357 node, compiler::Type::Wasm(type, module_,
graph_->zone()));
361 void SetSourcePosition(Node* node) {
365 node, SourcePosition(
offset, inlining_id_));
389 WasmIntoJSInlinerImpl inliner(zone, module, mcgraph, body, bytes,
390 source_position_table, inlining_id);
391 return inliner.TryInlining();
static void SetType(Node *node, Type type)
static bool TryInlining(Zone *zone, const wasm::WasmModule *module, MachineGraph *mcgraph, const wasm::FunctionBody &body, base::Vector< const uint8_t > bytes, SourcePositionTable *source_position_table, int inlining_id)
constexpr HeapType heap_type() const
static constexpr ValueType Generic(GenericKind kind, Nullability nullable, bool shared)
static constexpr ValueType Ref(ModuleTypeIndex index, bool shared, RefTypeKind kind)
static constexpr ValueType RefMaybeNull(ModuleTypeIndex index, Nullability nullable, bool shared, RefTypeKind kind)
const v8::base::TimeTicks end_
ZoneStack< RpoNumber > & stack
Node::Uses::const_iterator begin(const Node::Uses &uses)
constexpr int kWasmInstanceDataParameterIndex
V8_INLINE bool IsHeapSubtypeOf(HeapType subtype, HeapType supertype, const WasmModule *sub_module, const WasmModule *super_module)
constexpr IndependentValueType kWasmI32
constexpr IndependentHeapType kWasmBottom
constexpr IndependentHeapType kWasmArrayRef
constexpr int kMinParameterIndex
bool is_signed(Condition cond)
#define DCHECK_NOT_NULL(val)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_GT(v1, v2)
Node * trusted_data_node_
const uint8_t * instruction_start_
const wasm::FunctionBody & body_
SourcePositionTable * source_position_table_
const wasm::WasmModule * module_