1/*
2 * Copyright (C) 2014 Apple Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "FunctionHasExecutedCache.h"
28
29#include <limits.h>
30
31namespace JSC {
32
33bool FunctionHasExecutedCache::hasExecutedAtOffset(intptr_t id, unsigned offset)
34{
35 if (m_rangeMap.find(id) == m_rangeMap.end())
36 return false;
37
38 RangeMap& map = m_rangeMap.find(id)->second;
39 unsigned distance = UINT_MAX;
40 bool hasExecuted = false;
41 for (auto& pair : map) {
42 const FunctionRange& range = pair.first;
43 if (range.m_start <= offset && offset <= range.m_end && range.m_end - range.m_start < distance) {
44 hasExecuted = pair.second;
45 distance = range.m_end - range.m_start;
46 }
47 }
48
49 return hasExecuted;
50}
51
52void FunctionHasExecutedCache::insertUnexecutedRange(intptr_t id, unsigned start, unsigned end)
53{
54 if (m_rangeMap.find(id) == m_rangeMap.end()) {
55 RangeMap map;
56 m_rangeMap[id] = map;
57 }
58
59 RangeMap& map = m_rangeMap.find(id)->second;
60 FunctionRange range;
61 range.m_start = start;
62 range.m_end = end;
63 // Only insert unexecuted ranges once for a given sourceID because we may run into a situation where an executable executes, then is GCed, and then is allocated again,
64 // and tries to reinsert itself, claiming it has never run, but this is false because it indeed already executed.
65 if (map.find(range) == map.end())
66 map[range] = false;
67}
68
69void FunctionHasExecutedCache::removeUnexecutedRange(intptr_t id, unsigned start, unsigned end)
70{
71 // FIXME: We should never have an instance where we return here, but currently do in some situations. Find out why.
72 if (m_rangeMap.find(id) == m_rangeMap.end())
73 return;
74
75 RangeMap& map = m_rangeMap.find(id)->second;
76
77 FunctionRange range;
78 range.m_start = start;
79 range.m_end = end;
80 map[range] = true;
81}
82
83Vector<std::tuple<bool, unsigned, unsigned>> FunctionHasExecutedCache::getFunctionRanges(intptr_t id)
84{
85 Vector<std::tuple<bool, unsigned, unsigned>> ranges(0);
86 auto findResult = m_rangeMap.find(id);
87 if (findResult == m_rangeMap.end())
88 return ranges;
89
90 RangeMap& map = m_rangeMap.find(id)->second;
91 for (auto& pair : map) {
92 const FunctionRange& range = pair.first;
93 bool hasExecuted = pair.second;
94 ranges.append(std::tuple<bool, unsigned, unsigned>(hasExecuted, range.m_start, range.m_end));
95 }
96
97 return ranges;
98}
99
100} // namespace JSC
101