diff options
Diffstat (limited to 'deps/v8/src/compiler/wasm-gc-operator-reducer.cc')
-rw-r--r-- | deps/v8/src/compiler/wasm-gc-operator-reducer.cc | 129 |
1 files changed, 111 insertions, 18 deletions
diff --git a/deps/v8/src/compiler/wasm-gc-operator-reducer.cc b/deps/v8/src/compiler/wasm-gc-operator-reducer.cc index cbda5422e8..40aaa43bb3 100644 --- a/deps/v8/src/compiler/wasm-gc-operator-reducer.cc +++ b/deps/v8/src/compiler/wasm-gc-operator-reducer.cc @@ -25,6 +25,11 @@ Reduction WasmGCOperatorReducer::Reduce(Node* node) { switch (node->opcode()) { case IrOpcode::kStart: return ReduceStart(node); + case IrOpcode::kWasmStructGet: + case IrOpcode::kWasmStructSet: + return ReduceWasmStructOperation(node); + case IrOpcode::kWasmArrayLength: + return ReduceWasmArrayLength(node); case IrOpcode::kAssertNotNull: return ReduceAssertNotNull(node); case IrOpcode::kIsNull: @@ -34,12 +39,16 @@ Reduction WasmGCOperatorReducer::Reduce(Node* node) { return ReduceWasmTypeCheck(node); case IrOpcode::kWasmTypeCast: return ReduceWasmTypeCast(node); + case IrOpcode::kWasmExternInternalize: + return ReduceWasmExternInternalize(node); case IrOpcode::kMerge: return ReduceMerge(node); case IrOpcode::kIfTrue: return ReduceIf(node, true); case IrOpcode::kIfFalse: return ReduceIf(node, false); + case IrOpcode::kDead: + return NoChange(); case IrOpcode::kLoop: return TakeStatesFromFirstControl(node); default: @@ -60,7 +69,7 @@ bool InDeadBranch(Node* node) { Node* GetAlias(Node* node) { switch (node->opcode()) { - case IrOpcode::kWasmTypeCheck: + case IrOpcode::kWasmTypeCast: case IrOpcode::kTypeGuard: case IrOpcode::kAssertNotNull: return NodeProperties::GetValueInput(node, 0); @@ -117,6 +126,58 @@ wasm::TypeInModule WasmGCOperatorReducer::ObjectTypeFromContext(Node* object, : type_from_node; } +Reduction WasmGCOperatorReducer::ReduceWasmStructOperation(Node* node) { + DCHECK(node->opcode() == IrOpcode::kWasmStructGet || + node->opcode() == IrOpcode::kWasmStructSet); + Node* control = NodeProperties::GetControlInput(node); + if (!IsReduced(control)) return NoChange(); + Node* object = NodeProperties::GetValueInput(node, 0); + + wasm::TypeInModule object_type = ObjectTypeFromContext(object, control); + if (object_type.type.is_bottom()) return NoChange(); + + if (object_type.type.is_non_nullable()) { + // If the object is known to be non-nullable in the context, remove the null + // check. + auto op_params = OpParameter<WasmFieldInfo>(node->op()); + const Operator* new_op = + node->opcode() == IrOpcode::kWasmStructGet + ? simplified()->WasmStructGet(op_params.type, op_params.field_index, + op_params.is_signed, + kWithoutNullCheck) + : simplified()->WasmStructSet(op_params.type, op_params.field_index, + kWithoutNullCheck); + NodeProperties::ChangeOp(node, new_op); + } + + object_type.type = object_type.type.AsNonNull(); + + return UpdateNodeAndAliasesTypes(node, GetState(control), object, object_type, + false); +} + +Reduction WasmGCOperatorReducer::ReduceWasmArrayLength(Node* node) { + DCHECK_EQ(node->opcode(), IrOpcode::kWasmArrayLength); + Node* control = NodeProperties::GetControlInput(node); + if (!IsReduced(control)) return NoChange(); + Node* object = NodeProperties::GetValueInput(node, 0); + + wasm::TypeInModule object_type = ObjectTypeFromContext(object, control); + if (object_type.type.is_bottom()) return NoChange(); + + if (object_type.type.is_non_nullable()) { + // If the object is known to be non-nullable in the context, remove the null + // check. + const Operator* new_op = simplified()->WasmArrayLength(kWithoutNullCheck); + NodeProperties::ChangeOp(node, new_op); + } + + object_type.type = object_type.type.AsNonNull(); + + return UpdateNodeAndAliasesTypes(node, GetState(control), object, object_type, + false); +} + // If the condition of this node's branch is a type check or a null check, // add the additional information about the type-checked node to the path // state. @@ -202,13 +263,15 @@ Reduction WasmGCOperatorReducer::ReduceAssertNotNull(Node* node) { // Optimize the check away if the argument is known to be non-null. if (object_type.type.is_non_nullable()) { - ReplaceWithValue(node, object); - node->Kill(); - return Replace(object); + // First, relax control. + ReplaceWithValue(node, node, node, control); + // Use a TypeGuard node to not lose any type information. + NodeProperties::ChangeOp( + node, common()->TypeGuard(NodeProperties::GetType(node))); + return Changed(node); } object_type.type = object_type.type.AsNonNull(); - return UpdateNodeAndAliasesTypes(node, GetState(control), node, object_type, false); } @@ -224,16 +287,20 @@ Reduction WasmGCOperatorReducer::ReduceCheckNull(Node* node) { // Optimize the check away if the argument is known to be non-null. if (object_type.type.is_non_nullable()) { - ReplaceWithValue( - node, gasm_.Int32Constant(node->opcode() == IrOpcode::kIsNull ? 0 : 1)); + ReplaceWithValue(node, + SetType(gasm_.Int32Constant( + node->opcode() == IrOpcode::kIsNull ? 0 : 1), + wasm::kWasmI32)); node->Kill(); return Replace(object); // Irrelevant replacement. } // Optimize the check away if the argument is known to be null. if (object->opcode() == IrOpcode::kNull) { - ReplaceWithValue( - node, gasm_.Int32Constant(node->opcode() == IrOpcode::kIsNull ? 1 : 0)); + ReplaceWithValue(node, + SetType(gasm_.Int32Constant( + node->opcode() == IrOpcode::kIsNull ? 1 : 0), + wasm::kWasmI32)); node->Kill(); return Replace(object); // Irrelevant replacement. } @@ -241,6 +308,23 @@ Reduction WasmGCOperatorReducer::ReduceCheckNull(Node* node) { return NoChange(); } +Reduction WasmGCOperatorReducer::ReduceWasmExternInternalize(Node* node) { + DCHECK_EQ(node->opcode(), IrOpcode::kWasmExternInternalize); + // Remove redundant extern.internalize(extern.externalize(...)) pattern. + // TODO(mliedtke): Currently this doesn't get fully removed, probably due to + // not running dead code elimination in this pipeline step. What would it cost + // us to run it here? + if (NodeProperties::GetValueInput(node, 0)->opcode() == + IrOpcode::kWasmExternExternalize) { + Node* externalize = node->InputAt(0); + Node* input = externalize->InputAt(0); + ReplaceWithValue(node, input); + node->Kill(); + return Replace(input); + } + return TakeStatesFromFirstControl(node); +} + Reduction WasmGCOperatorReducer::ReduceWasmTypeCast(Node* node) { DCHECK_EQ(node->opcode(), IrOpcode::kWasmTypeCast); Node* effect = NodeProperties::GetEffectInput(node); @@ -259,13 +343,20 @@ Reduction WasmGCOperatorReducer::ReduceWasmTypeCast(Node* node) { wasm::HeapType(rtt_type.type.ref_index()), object_type.module, rtt_type.module)) { if (to_nullable) { - // Type cast will always succeed. Remove it. - ReplaceWithValue(node, object); - node->Kill(); - return Replace(object); + // Type cast will always succeed. Turn it into a TypeGuard to not lose any + // type information. + // First, relax control. + ReplaceWithValue(node, node, node, control); + // Remove rtt input. + node->RemoveInput(1); + NodeProperties::ChangeOp( + node, common()->TypeGuard(NodeProperties::GetType(node))); + return Changed(node); } else { gasm_.InitializeEffectControl(effect, control); - return Replace(gasm_.AssertNotNull(object)); + return Replace(SetType(gasm_.AssertNotNull(object, object_type.type, + TrapId::kTrapIllegalCast), + object_type.type.AsNonNull())); } } @@ -276,11 +367,12 @@ Reduction WasmGCOperatorReducer::ReduceWasmTypeCast(Node* node) { // A cast between unrelated types can only succeed if the argument is null. // Otherwise, it always fails. Node* non_trapping_condition = object_type.type.is_nullable() && to_nullable - ? gasm_.IsNull(object) + ? gasm_.IsNull(object, object_type.type) : gasm_.Int32Constant(0); gasm_.TrapUnless(SetType(non_trapping_condition, wasm::kWasmI32), TrapId::kTrapIllegalCast); - Node* null_node = SetType(gasm_.Null(), wasm::ToNullSentinel(object_type)); + Node* null_node = SetType(gasm_.Null(object_type.type), + wasm::ToNullSentinel(object_type)); ReplaceWithValue(node, null_node, gasm_.effect(), gasm_.control()); node->Kill(); return Replace(null_node); @@ -322,7 +414,7 @@ Reduction WasmGCOperatorReducer::ReduceWasmTypeCheck(Node* node) { // Type cast will fail only on null. gasm_.InitializeEffectControl(effect, control); Node* condition = SetType(object_type.type.is_nullable() && !null_succeeds - ? gasm_.IsNotNull(object) + ? gasm_.IsNotNull(object, object_type.type) : gasm_.Int32Constant(1), wasm::kWasmI32); ReplaceWithValue(node, condition); @@ -339,7 +431,8 @@ Reduction WasmGCOperatorReducer::ReduceWasmTypeCheck(Node* node) { if (null_succeeds && object_type.type.is_nullable()) { // The cast only succeeds in case of null. gasm_.InitializeEffectControl(effect, control); - condition = SetType(gasm_.IsNull(object), wasm::kWasmI32); + condition = + SetType(gasm_.IsNull(object, object_type.type), wasm::kWasmI32); } else { // The cast never succeeds. condition = SetType(gasm_.Int32Constant(0), wasm::kWasmI32); |