gear_backend_common/lazy_pages.rs
1// This file is part of Gear.
2
3// Copyright (C) 2022-2023 Gear Technologies Inc.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Core logic for usage both in runtime and in lazy-pages native part.
20
21use core::fmt::Debug;
22
23use core::any::Any;
24use gear_core::{costs::CostPerPage, memory::HostPointer, pages::GearPage};
25use scale_info::scale::{self, Decode, Encode};
26
27use crate::utils::LimitedStr;
28
29/// Informs lazy-pages whether they work with native or WASM runtime.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)]
31#[codec(crate = scale)]
32pub enum GlobalsAccessMod {
33 /// Is wasm runtime.
34 WasmRuntime,
35 /// Is native runtime.
36 NativeRuntime,
37}
38
39/// Lazy-pages cases weights.
40#[derive(Debug, Default, Clone, PartialEq, Eq, Encode, Decode)]
41#[codec(crate = scale)]
42pub struct LazyPagesWeights {
43 /// First read page access cost.
44 pub signal_read: CostPerPage<GearPage>,
45 /// First write page access cost.
46 pub signal_write: CostPerPage<GearPage>,
47 /// First write access cost for page, which has been already read accessed.
48 pub signal_write_after_read: CostPerPage<GearPage>,
49 /// First read page access cost from host function call.
50 pub host_func_read: CostPerPage<GearPage>,
51 /// First write page access cost from host function call.
52 pub host_func_write: CostPerPage<GearPage>,
53 /// First write page access cost from host function call.
54 pub host_func_write_after_read: CostPerPage<GearPage>,
55 /// Loading page data from storage cost.
56 pub load_page_storage_data: CostPerPage<GearPage>,
57}
58
59/// Globals ctx for lazy-pages initialization for program.
60#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
61#[codec(crate = scale)]
62pub struct GlobalsAccessConfig {
63 /// Raw pointer to the globals access provider.
64 pub access_ptr: HostPointer,
65 /// Access mod, currently two: native or WASM runtime.
66 pub access_mod: GlobalsAccessMod,
67}
68
69/// Globals access error.
70#[derive(Debug)]
71pub struct GlobalsAccessError;
72
73/// Globals access trait.
74pub trait GlobalsAccessor {
75 /// Returns global `name` value, if `name` is I64 global export.
76 fn get_i64(&self, name: &LimitedStr) -> Result<i64, GlobalsAccessError>;
77 /// Set global `name` == `value`, if `name` is I64 global export.
78 fn set_i64(&mut self, name: &LimitedStr, value: i64) -> Result<(), GlobalsAccessError>;
79 /// Returns global `name` value, if `name` is I32 global export.
80 fn get_i32(&self, _name: &LimitedStr) -> Result<i32, GlobalsAccessError> {
81 unimplemented!("Currently has no i32 system globals")
82 }
83 /// Set global `name` == `value`, if `name` is I32 global export.
84 fn set_i32(&mut self, _name: &LimitedStr, _value: i32) -> Result<(), GlobalsAccessError> {
85 unimplemented!("Currently has no i32 system globals")
86 }
87 /// Returns as `&mut dyn Any`.
88 fn as_any_mut(&mut self) -> &mut dyn Any;
89}
90
91/// Lazy-pages status.
92/// By default in program initialization status is set as `Normal`.
93/// If nothing bad happens in lazy-pages, then status remains to be `Normal`.
94/// If gas limit exceed, then status is set as `GasLimitExceeded`, and lazy-pages
95/// starts to skips all signals processing until the end of execution.
96/// The same is for gas allowance exceed, except it sets status as `GasAllowanceExceed`.
97/// In the end of execution this status is checked and if it's not `Normal` then
98/// termination reason sets as `gas limit exceeded` or `gas allowance exceeded`, depending on status.
99/// NOTE: `repr(i64)` is important to be able add additional fields, without old runtimes separate support logic.
100#[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Eq)]
101#[codec(crate = scale)]
102#[repr(i64)]
103// TODO: consider removal of two exceed options in favor of one global (issue #3018).
104// Will require bump of many RI func's versions.
105pub enum Status {
106 /// Lazy-pages works in normal mode.
107 Normal = 0_i64,
108 /// Skips signals processing until the end of execution, set termination reason as `gas limit exceeded`.
109 GasLimitExceeded,
110}
111
112impl Status {
113 /// Returns bool defining if status is `Normal`.
114 pub fn is_normal(&self) -> bool {
115 *self == Self::Normal
116 }
117}