      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104

    // Copyright 2015-2017 Parity Technologies (UK) Ltd.
    // This file is part of Parity.

    // Parity is free software: you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
    // (at your option) any later version.

    // Parity is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.

    // You should have received a copy of the GNU General Public License
    // along with Parity.  If not, see <http://www.gnu.org/licenses/>.

    use std::sync::Arc;
    use util::{H256, HeapSizeOf, Mutex};
    use util::sha3::*;
    use util::cache::MemoryLruCache;
    use bit_set::BitSet;
    use super::super::instructions;

    const DEFAULT_CACHE_SIZE: usize = 4 * 1024 * 1024;

    // stub for a HeapSizeOf implementation.
    struct Bits(Arc<BitSet>);

    impl HeapSizeOf for Bits {
    	fn heap_size_of_children(&self) -> usize {
    		// dealing in bits here
    		self.0.capacity() * 8
    	}
    }

    /// Global cache for EVM interpreter
    pub struct SharedCache {
    	jump_destinations: Mutex<MemoryLruCache<H256, Bits>>,
    }

    impl SharedCache {
    	/// Create a jump destinations cache with a maximum size in bytes
    	/// to cache.
    	pub fn new(max_size: usize) -> Self {
    		SharedCache {
    			jump_destinations: Mutex::new(MemoryLruCache::new(max_size)),
    		}
    	}

    	/// Get jump destinations bitmap for a contract.
    	pub fn jump_destinations(&self, code_hash: &H256, code: &[u8]) -> Arc<BitSet> {
    		if code_hash == &SHA3_EMPTY {
    			return Self::find_jump_destinations(code);
    		}

    		if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) {
    			return d.0.clone();
    		}

    		let d = Self::find_jump_destinations(code);
    		self.jump_destinations.lock().insert(code_hash.clone(), Bits(d.clone()));

    		d
    	}

    	fn find_jump_destinations(code: &[u8]) -> Arc<BitSet> {
    		let mut jump_dests = BitSet::with_capacity(code.len());
    		let mut position = 0;

    		while position < code.len() {
    			let instruction = code[position];

    			if instruction == instructions::JUMPDEST {
    				jump_dests.insert(position);
    			} else if instructions::is_push(instruction) {
    				position += instructions::get_push_bytes(instruction);
    			}
    			position += 1;
    		}

    		jump_dests.shrink_to_fit();
    		Arc::new(jump_dests)
    	}
    }

    impl Default for SharedCache {
    	fn default() -> Self {
    		SharedCache::new(DEFAULT_CACHE_SIZE)
    	}
    }

    #[test]
    fn test_find_jump_destinations() {
    	use util::FromHex;
    	// given
    	let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b01600055".from_hex().unwrap();

    	// when
    	let valid_jump_destinations = SharedCache::find_jump_destinations(&code);

    	// then
    	assert!(valid_jump_destinations.contains(66));
    }

# Help

## Keyboard Shortcuts

?
  Show this help dialog
S
  Focus the search field
⇤
  Move up in search results
⇥
  Move down in search results
⏎
  Go to active search result
+
  Collapse/expand all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)