### Godot version

4.1.stable

### System information

Godot v4.1.stable - elementary OS 7 Horus 7 (Ubuntu 22.04) - Vulkan (Mobile) - dedicated AMD Radeon RX 6600 (RADV NAVI23) () - Intel(R) Core(TM) i5-8500 CPU @ 3.00GHz (6 Threads)

### Issue description

Tilemap has a memory leak where if you repeatedly change the tile (that has collidable physics) of cells, the static memory (shown in the debugger) increases and stays there. This only happens if you have a physics layer in the Tileset and one of the tiles is collidable.

Also the memory usage is extremely high even when generating the map once. A 1000x1000 tiles map uses 1.4 GB of memory!

Workaround is simple. Simply clear the tilemap with `clear()` before you change the map.

### Steps to reproduce

1. Create a TileMap node
2. Create a TileSet containing two tiles on the atlas coordinates `(0, 0)` and `(1, 0)`
3. Create a Physics Layer in the TileSet and make one of the tiles fully collidable
4. Attach a script to the TileMap
5. Set the script to this
```
extends TileMap

func _process(delta):
	if Input.is_key_pressed(KEY_SPACE):
		for i in range(5000):
			set_cell(0, Vector2i(i, 0), 0, Vector2i(randi_range(0, 1), 0))
```
6. Run the scene
7. Go into "Debugger" tab in the editor while the scene is running
8. Press the "Monitors" tab press and observe the "Static" memory
9. Now hold down the space bar and observe the static memory climbing but never coming down
10. To workaround the problem simply add `clear()` before the loop like this:
```
extends TileMap

func _process(delta):
	if Input.is_key_pressed(KEY_SPACE):
		clear()
		for i in range(5000):
			set_cell(0, Vector2i(i, 0), 0, Vector2i(randi_range(0, 1), 0))
```

### Minimal reproduction project

[tilemapmemoryleak.zip](https://github.com/godotengine/godot/files/12064640/tilemapmemoryleak.zip)
TileSet::TerrainsPattern _get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern);
	RBSet<TerrainConstraint> _get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const;
	RBSet<TerrainConstraint> _get_terrain_constraints_from_painted_cells_list(int p_layer, const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const;
	
	void _set_tile_data(int p_layer, const Vector<int> &p_data);
	Vector<int> _get_tile_data(int p_layer) const;
	void _build_runtime_update_tile_data(SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list);
	void _tile_set_changed();
	bool _tile_set_changed_deferred_update_needed = false;
	void _tile_set_changed_deferred_update();
protected:
	bool _set(const StringName &p_name, const Variant &p_value);
	bool _get(const StringName &p_name, Variant &r_ret) const;
	void _get_property_list(List<PropertyInfo> *p_list) const;
	void _notification(int p_what);
	static void _bind_methods();
public:
	static Vector2i transform_coords_layout(const Vector2i &p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout);
	enum {
		INVALID_CELL = -1
	};
#ifdef TOOLS_ENABLED
	virtual Rect2 _edit_get_rect() const override;
#endif
	void set_tileset(const Ref<TileSet> &p_tileset);
	Ref<TileSet> get_tileset() const;
	void set_quadrant_size(int p_size);
	int get_quadrant_size() const;
	static void draw_tile(RID p_canvas_item, const Vector2 &p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile, int p_frame = -1, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0), const TileData *p_tile_data_override = nullptr, real_t p_animation_offset = 0.0);