jdk

Форк
0
/
icache.cpp 
111 строк · 4.4 Кб
1
/*
2
 * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
 *
5
 * This code is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.
8
 *
9
 * This code is distributed in the hope that it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 * version 2 for more details (a copy is included in the LICENSE file that
13
 * accompanied this code).
14
 *
15
 * You should have received a copy of the GNU General Public License version
16
 * 2 along with this work; if not, write to the Free Software Foundation,
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
 * or visit www.oracle.com if you need additional information or have any
21
 * questions.
22
 *
23
 */
24

25
#include "precompiled.hpp"
26
#include "code/codeBlob.hpp"
27
#include "memory/resourceArea.hpp"
28
#include "runtime/icache.hpp"
29
#include "utilities/align.hpp"
30

31
// The flush stub function address
32
AbstractICache::flush_icache_stub_t AbstractICache::_flush_icache_stub = nullptr;
33

34
void AbstractICache::initialize() {
35
  // Making this stub must be FIRST use of assembler
36
  ResourceMark rm;
37

38
  BufferBlob* b = BufferBlob::create("flush_icache_stub", ICache::stub_size);
39
  if (b == nullptr) {
40
    vm_exit_out_of_memory(ICache::stub_size, OOM_MALLOC_ERROR, "CodeCache: no space for flush_icache_stub");
41
  }
42
  CodeBuffer c(b);
43

44
  ICacheStubGenerator g(&c);
45
  g.generate_icache_flush(&_flush_icache_stub);
46

47
  // The first use of flush_icache_stub must apply it to itself.
48
  // The StubCodeMark destructor in generate_icache_flush will
49
  // call Assembler::flush, which in turn will call invalidate_range,
50
  // which will in turn call the flush stub.  Thus we don't need an
51
  // explicit call to invalidate_range here.  This assumption is
52
  // checked in invalidate_range.
53
}
54

55
void AbstractICache::call_flush_stub(address start, int lines) {
56
  // The business with the magic number is just a little security.
57
  // We cannot call the flush stub when generating the flush stub
58
  // because it isn't there yet.  So, the stub also returns its third
59
  // parameter.  This is a cheap check that the stub was really executed.
60
  static int magic = 0xbaadbabe;
61

62
  int auto_magic = magic; // Make a local copy to avoid race condition
63
  int r = (*_flush_icache_stub)(start, lines, auto_magic);
64
  guarantee(r == auto_magic, "flush stub routine did not execute");
65
  ++magic;
66
}
67

68
void AbstractICache::invalidate_word(address addr) {
69
  // Because this is called for instruction patching on the fly, long after
70
  // bootstrapping, we execute the stub directly.  Account for a 4-byte word
71
  // spanning two cache lines by computing a start line address by rounding
72
  // addr down to a line_size boundary, and an end line address by adding
73
  // the word size - 1 and rounding the result down to a line_size boundary.
74
  // If we just added word size, we'd mistakenly flush the next cache line
75
  // if the word to be flushed started in the last 4 bytes of the line.
76
  // Doing that would segv if the next line weren't mapped.
77

78
  const int word_size_in_bytes = 4; // Always, regardless of platform
79

80
  intptr_t start_line = ((intptr_t)addr + 0) & ~(ICache::line_size - 1);
81
  intptr_t end_line   = ((intptr_t)addr + word_size_in_bytes - 1)
82
                                             & ~(ICache::line_size - 1);
83
  (*_flush_icache_stub)((address)start_line, start_line == end_line ? 1 : 2, 0);
84
}
85

86
void AbstractICache::invalidate_range(address start, int nbytes) {
87
  static bool firstTime = true;
88
  if (firstTime) {
89
    guarantee(start == CAST_FROM_FN_PTR(address, _flush_icache_stub),
90
              "first flush should be for flush stub");
91
    firstTime = false;
92
    return;
93
  }
94
  if (nbytes == 0) {
95
    return;
96
  }
97
  // Align start address to an icache line boundary and transform
98
  // nbytes to an icache line count.
99
  const uint line_offset = uintptr_t(start) & (ICache::line_size-1);
100
  if (line_offset != 0) {
101
    start -= line_offset;
102
    nbytes += line_offset;
103
  }
104
  call_flush_stub(start, align_up(nbytes, (int)ICache::line_size) >>
105
                         ICache::log2_line_size);
106
}
107

108
// For init.cpp
109
void icache_init() {
110
  ICache::initialize();
111
}
112

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.