diff --git a/BUILD.bazel b/BUILD.bazel index cf21c089ed..bd4b45eb9a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -2153,6 +2153,7 @@ filegroup( "src/asmjs/asm-types.h", "src/compiler/int64-lowering.h", "src/compiler/wasm-compiler.h", + "src/compiler/wasm-escape-analysis.h", "src/compiler/wasm-inlining.h", "src/debug/debug-wasm-objects.cc", "src/debug/debug-wasm-objects.h", @@ -2538,6 +2539,7 @@ filegroup( ":is_v8_enable_webassembly": [ "src/compiler/int64-lowering.cc", "src/compiler/wasm-compiler.cc", + "src/compiler/wasm-escape-analysis.cc", "src/compiler/wasm-inlining.cc", ], "//conditions:default": [], diff --git a/BUILD.gn b/BUILD.gn index 5d22495640..352c7af9d8 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -3412,6 +3412,7 @@ v8_header_set("v8_internal_headers") { "src/asmjs/asm-types.h", "src/compiler/int64-lowering.h", "src/compiler/wasm-compiler.h", + "src/compiler/wasm-escape-analysis.h", "src/compiler/wasm-inlining.h", "src/debug/debug-wasm-objects-inl.h", "src/debug/debug-wasm-objects.h", @@ -3881,6 +3882,7 @@ if (v8_enable_webassembly) { v8_compiler_sources += [ "src/compiler/int64-lowering.cc", "src/compiler/wasm-compiler.cc", + "src/compiler/wasm-escape-analysis.cc", "src/compiler/wasm-inlining.cc", ] } diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index 9b9a4a4cbe..a4ad7244f9 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc @@ -96,6 +96,7 @@ #if V8_ENABLE_WEBASSEMBLY #include "src/compiler/wasm-compiler.h" +#include "src/compiler/wasm-escape-analysis.h" #include "src/compiler/wasm-inlining.h" #include "src/wasm/function-body-decoder.h" #include "src/wasm/function-compiler.h" @@ -2013,12 +2014,14 @@ struct WasmOptimizationPhase { WasmInliner inliner(&graph_reducer, env, function_index, data->source_positions(), data->node_origins(), data->mcgraph(), wire_bytes); + WasmEscapeAnalysis escape(&graph_reducer, data->mcgraph()); AddReducer(data, &graph_reducer, &machine_reducer); AddReducer(data, &graph_reducer, &dead_code_elimination); AddReducer(data, &graph_reducer, &common_reducer); AddReducer(data, &graph_reducer, &value_numbering); if (FLAG_experimental_wasm_gc) { AddReducer(data, &graph_reducer, &load_elimination); + AddReducer(data, &graph_reducer, &escape); } if (FLAG_wasm_inlining && !WasmInliner::any_inlining_impossible(data->graph()->NodeCount())) { diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 6a44b6a9e0..51f48c21dd 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -293,6 +293,24 @@ class WasmGraphAssembler : public GraphAssembler { } // Maps and their contents. + Node* LoadMap(Node* object) { + Node* map_word = LoadFromObject(MachineType::TaggedPointer(), object, + HeapObject::kMapOffset - kHeapObjectTag); +#ifdef V8_MAP_PACKING + return UnpackMapWord(map_word); +#else + return map_word; +#endif + } + + void StoreMap(Node* heap_object, Node* map) { + ObjectAccess access(MachineType::TaggedPointer(), kMapWriteBarrier); +#ifdef V8_MAP_PACKING + map = PackMapWord(map); +#endif + StoreToObject(access, heap_object, HeapObject::kMapOffset - kHeapObjectTag, + map); + } Node* LoadInstanceType(Node* map) { return LoadFromObject( @@ -5573,7 +5591,7 @@ Node* WasmGraphBuilder::StructNewWithRtt(uint32_t struct_index, base::Vector fields) { int size = WasmStruct::Size(type); Node* s = gasm_->Allocate(size); - gasm_->StoreMap(s, TNode::UncheckedCast(rtt)); + gasm_->StoreMap(s, rtt); gasm_->StoreToObject( ObjectAccess(MachineType::TaggedPointer(), kNoWriteBarrier), s, wasm::ObjectAccess::ToTagged(JSReceiver::kPropertiesOrHashOffset), diff --git a/src/compiler/wasm-escape-analysis.cc b/src/compiler/wasm-escape-analysis.cc new file mode 100644 index 0000000000..f2057f77ef --- /dev/null +++ b/src/compiler/wasm-escape-analysis.cc @@ -0,0 +1,58 @@ +// 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/compiler/wasm-escape-analysis.h" + +#include "src/compiler/js-graph.h" +#include "src/compiler/node-properties.h" + +namespace v8 { +namespace internal { +namespace compiler { + +Reduction WasmEscapeAnalysis::Reduce(Node* node) { + switch (node->opcode()) { + case IrOpcode::kAllocateRaw: + return ReduceAllocateRaw(node); + default: + return NoChange(); + } +} + +Reduction WasmEscapeAnalysis::ReduceAllocateRaw(Node* node) { + DCHECK_EQ(node->opcode(), IrOpcode::kAllocateRaw); + + // TODO(manoskouk): Account for phis. + std::vector use_edges; + for (Edge edge : node->use_edges()) { + if (NodeProperties::IsValueEdge(edge)) { + if (edge.index() != 0 || + edge.from()->opcode() != IrOpcode::kStoreToObject) { + return NoChange(); + } + } + use_edges.push_back(edge); + } + + // Remove all stores from the effect chain. + for (Edge edge : use_edges) { + if (NodeProperties::IsValueEdge(edge)) { + Node* use = edge.from(); + DCHECK_EQ(edge.index(), 0); + DCHECK_EQ(use->opcode(), IrOpcode::kStoreToObject); + ReplaceWithValue(use, mcgraph_->Dead(), + NodeProperties::GetEffectInput(use), mcgraph_->Dead()); + } + } + + // Remove the allocation from the effect and control chains. + ReplaceWithValue(node, mcgraph_->Dead(), NodeProperties::GetEffectInput(node), + NodeProperties::GetControlInput(node)); + + return NoChange(); +} + +} // namespace compiler +} // namespace internal +} // namespace v8 diff --git a/src/compiler/wasm-escape-analysis.h b/src/compiler/wasm-escape-analysis.h new file mode 100644 index 0000000000..bc29438f5b --- /dev/null +++ b/src/compiler/wasm-escape-analysis.h @@ -0,0 +1,41 @@ +// 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. + +#if !V8_ENABLE_WEBASSEMBLY +#error This header should only be included if WebAssembly is enabled. +#endif // !V8_ENABLE_WEBASSEMBLY + +#ifndef V8_COMPILER_WASM_ESCAPE_ANALYSIS_H_ +#define V8_COMPILER_WASM_ESCAPE_ANALYSIS_H_ + +#include "src/compiler/graph-reducer.h" + +namespace v8 { +namespace internal { +namespace compiler { + +class MachineGraph; + +// Eliminate allocated objects which are only assigned to. +// Current restrictions: Does not work for arrays (until they are also allocated +// with AllocateRaw). Does not work if the allocated object is passed to a phi. +class WasmEscapeAnalysis final : public AdvancedReducer { + public: + WasmEscapeAnalysis(Editor* editor, MachineGraph* mcgraph) + : AdvancedReducer(editor), mcgraph_(mcgraph) {} + + const char* reducer_name() const override { return "WasmEscapeAnalysis"; } + + Reduction Reduce(Node* node) final; + + private: + Reduction ReduceAllocateRaw(Node* call); + MachineGraph* const mcgraph_; +}; + +} // namespace compiler +} // namespace internal +} // namespace v8 + +#endif // V8_COMPILER_WASM_ESCAPE_ANALYSIS_H_