Compare commits

...

2 Commits

Author SHA1 Message Date
Bananymous 90820f24a4 BAN: Make HashMap::{insert,emplace}{,_or_assign} return an iterator
This reduces the number of lookups done into the hash map :)
2024-12-09 03:37:13 +02:00
Bananymous 12a37500b0 Kernel: Fix triple-fault in vitual tty
This was happening when printing non-utf8 data while having virtual tty
as the debug console.
2024-12-09 03:35:51 +02:00
3 changed files with 44 additions and 40 deletions

View File

@ -45,27 +45,27 @@ namespace BAN
HashMap<Key, T, HASH>& operator=(const HashMap<Key, T, HASH>&); HashMap<Key, T, HASH>& operator=(const HashMap<Key, T, HASH>&);
HashMap<Key, T, HASH>& operator=(HashMap<Key, T, HASH>&&); HashMap<Key, T, HASH>& operator=(HashMap<Key, T, HASH>&&);
ErrorOr<void> insert(const Key& key, const T& value) { return emplace(key, value); } ErrorOr<iterator> insert(const Key& key, const T& value) { return emplace(key, value); }
ErrorOr<void> insert(const Key& key, T&& value) { return emplace(key, move(value)); } ErrorOr<iterator> insert(const Key& key, T&& value) { return emplace(key, move(value)); }
ErrorOr<void> insert(Key&& key, const T& value) { return emplace(move(key), value); } ErrorOr<iterator> insert(Key&& key, const T& value) { return emplace(move(key), value); }
ErrorOr<void> insert(Key&& key, T&& value) { return emplace(move(key), move(value)); } ErrorOr<iterator> insert(Key&& key, T&& value) { return emplace(move(key), move(value)); }
ErrorOr<void> insert_or_assign(const Key& key, const T& value) { return emplace_or_assign(key, value); } ErrorOr<iterator> insert_or_assign(const Key& key, const T& value) { return emplace_or_assign(key, value); }
ErrorOr<void> insert_or_assign(const Key& key, T&& value) { return emplace_or_assign(key, move(value)); } ErrorOr<iterator> insert_or_assign(const Key& key, T&& value) { return emplace_or_assign(key, move(value)); }
ErrorOr<void> insert_or_assign(Key&& key, const T& value) { return emplace_or_assign(move(key), value); } ErrorOr<iterator> insert_or_assign(Key&& key, const T& value) { return emplace_or_assign(move(key), value); }
ErrorOr<void> insert_or_assign(Key&& key, T&& value) { return emplace_or_assign(move(key), move(value)); } ErrorOr<iterator> insert_or_assign(Key&& key, T&& value) { return emplace_or_assign(move(key), move(value)); }
template<typename... Args> template<typename... Args>
ErrorOr<void> emplace(const Key& key, Args&&... args) requires is_constructible_v<T, Args...> ErrorOr<iterator> emplace(const Key& key, Args&&... args) requires is_constructible_v<T, Args...>
{ return emplace(Key(key), forward<Args>(args)...); } { return emplace(Key(key), forward<Args>(args)...); }
template<typename... Args> template<typename... Args>
ErrorOr<void> emplace(Key&&, Args&&...) requires is_constructible_v<T, Args...>; ErrorOr<iterator> emplace(Key&&, Args&&...) requires is_constructible_v<T, Args...>;
template<typename... Args> template<typename... Args>
ErrorOr<void> emplace_or_assign(const Key& key, Args&&... args) requires is_constructible_v<T, Args...> ErrorOr<iterator> emplace_or_assign(const Key& key, Args&&... args) requires is_constructible_v<T, Args...>
{ return emplace_or_assign(Key(key), forward<Args>(args)...); } { return emplace_or_assign(Key(key), forward<Args>(args)...); }
template<typename... Args> template<typename... Args>
ErrorOr<void> emplace_or_assign(Key&&, Args&&...) requires is_constructible_v<T, Args...>; ErrorOr<iterator> emplace_or_assign(Key&&, Args&&...) requires is_constructible_v<T, Args...>;
iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); } iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); }
iterator end() { return iterator(m_buckets.end(), m_buckets.end()); } iterator end() { return iterator(m_buckets.end(), m_buckets.end()); }
@ -141,34 +141,35 @@ namespace BAN
template<typename Key, typename T, typename HASH> template<typename Key, typename T, typename HASH>
template<typename... Args> template<typename... Args>
ErrorOr<void> HashMap<Key, T, HASH>::emplace(Key&& key, Args&&... args) requires is_constructible_v<T, Args...> ErrorOr<typename HashMap<Key, T, HASH>::iterator> HashMap<Key, T, HASH>::emplace(Key&& key, Args&&... args) requires is_constructible_v<T, Args...>
{ {
ASSERT(!contains(key)); ASSERT(!contains(key));
TRY(rebucket(m_size + 1)); TRY(rebucket(m_size + 1));
auto& bucket = get_bucket(key);
TRY(bucket.emplace_back(move(key), forward<Args>(args)...)); auto bucket_it = get_bucket_iterator(key);
TRY(bucket_it->emplace_back(move(key), forward<Args>(args)...));
m_size++; m_size++;
return {};
return iterator(m_buckets.end(), bucket_it, prev(bucket_it->end(), 1));
} }
template<typename Key, typename T, typename HASH> template<typename Key, typename T, typename HASH>
template<typename... Args> template<typename... Args>
ErrorOr<void> HashMap<Key, T, HASH>::emplace_or_assign(Key&& key, Args&&... args) requires is_constructible_v<T, Args...> ErrorOr<typename HashMap<Key, T, HASH>::iterator> HashMap<Key, T, HASH>::emplace_or_assign(Key&& key, Args&&... args) requires is_constructible_v<T, Args...>
{ {
if (empty()) if (empty())
return emplace(move(key), forward<Args>(args)...); return emplace(move(key), forward<Args>(args)...);
auto& bucket = get_bucket(key);
for (Entry& entry : bucket) auto bucket_it = get_bucket_iterator(key);
for (auto entry_it = bucket_it->begin(); entry_it != bucket_it->end(); entry_it++)
{ {
if (entry.key == key) if (entry_it->key != key)
{ continue;
entry.value = T(forward<Args>(args)...); entry_it->value = T(forward<Args>(args)...);
return {}; return iterator(m_buckets.end(), bucket_it, entry_it);
}
} }
TRY(bucket.emplace_back(move(key), forward<Args>(args)...));
m_size++; return emplace(move(key), forward<Args>(args)...);
return {};
} }
template<typename Key, typename T, typename HASH> template<typename Key, typename T, typename HASH>
@ -208,7 +209,7 @@ namespace BAN
for (Entry& entry : bucket) for (Entry& entry : bucket)
if (entry.key == key) if (entry.key == key)
return entry.value; return entry.value;
ASSERT(false); ASSERT_NOT_REACHED();
} }
template<typename Key, typename T, typename HASH> template<typename Key, typename T, typename HASH>
@ -219,7 +220,7 @@ namespace BAN
for (const Entry& entry : bucket) for (const Entry& entry : bucket)
if (entry.key == key) if (entry.key == key)
return entry.value; return entry.value;
ASSERT(false); ASSERT_NOT_REACHED();
} }
template<typename Key, typename T, typename HASH> template<typename Key, typename T, typename HASH>

View File

@ -47,6 +47,7 @@
#define BOCHS_BREAK() asm volatile("xchgw %bx, %bx") #define BOCHS_BREAK() asm volatile("xchgw %bx, %bx")
#define DEBUG_VTTY 1
#define DEBUG_PCI 0 #define DEBUG_PCI 0
#define DEBUG_SCHEDULER 0 #define DEBUG_SCHEDULER 0

View File

@ -251,7 +251,7 @@ namespace Kernel
return reset_ansi(); return reset_ansi();
} }
reset_ansi(); reset_ansi();
dprintln("Unsupported ANSI CSI character J"); dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character J");
return; return;
case 'K': // Erase in Line case 'K': // Erase in Line
if (m_ansi_state.nums[0] == -1 || m_ansi_state.nums[0] == 0) if (m_ansi_state.nums[0] == -1 || m_ansi_state.nums[0] == 0)
@ -261,7 +261,7 @@ namespace Kernel
return reset_ansi(); return reset_ansi();
} }
reset_ansi(); reset_ansi();
dprintln("Unsupported ANSI CSI character K"); dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character K");
return; return;
case 'L': // Insert Line case 'L': // Insert Line
if (m_ansi_state.nums[0] == -1) if (m_ansi_state.nums[0] == -1)
@ -297,15 +297,15 @@ namespace Kernel
return reset_ansi(); return reset_ansi();
case 'S': // Scroll Up case 'S': // Scroll Up
reset_ansi(); reset_ansi();
dprintln("Unsupported ANSI CSI character S"); dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character S");
return; return;
case 'T': // Scroll Down case 'T': // Scroll Down
reset_ansi(); reset_ansi();
dprintln("Unsupported ANSI CSI character T"); dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character T");
return; return;
case 'f': // Horizontal Vertical Position case 'f': // Horizontal Vertical Position
reset_ansi(); reset_ansi();
dprintln("Unsupported ANSI CSI character f"); dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character f");
return; return;
case 'm': case 'm':
handle_ansi_csi_color(); handle_ansi_csi_color();
@ -350,7 +350,7 @@ namespace Kernel
return reset_ansi(); return reset_ansi();
} }
reset_ansi(); reset_ansi();
dprintln("invalid ANSI CSI ?"); dprintln_if(DEBUG_VTTY, "invalid ANSI CSI ?");
return; return;
case 'h': case 'h':
case 'l': case 'l':
@ -360,11 +360,11 @@ namespace Kernel
return reset_ansi(); return reset_ansi();
} }
reset_ansi(); reset_ansi();
dprintln("invalid ANSI CSI ?{}{}", m_ansi_state.nums[0], (char)ch); dprintln_if(DEBUG_VTTY, "invalid ANSI CSI ?{}{}", m_ansi_state.nums[0], (char)ch);
return; return;
default: default:
reset_ansi(); reset_ansi();
dprintln("Unsupported ANSI CSI character {}", ch); dprintln_if(DEBUG_VTTY, "Unsupported ANSI CSI character {}", ch);
return; return;
} }
} }
@ -416,7 +416,9 @@ namespace Kernel
} }
else else
{ {
dprintln("invalid utf8"); reset_ansi();
dprintln_if(DEBUG_VTTY, "invalid utf8");
return;
} }
m_state = State::WaitingUTF8; m_state = State::WaitingUTF8;
return; return;
@ -425,8 +427,8 @@ namespace Kernel
m_state = State::WaitingAnsiCSI; m_state = State::WaitingAnsiCSI;
else else
{ {
dprintln("unsupported byte after ansi escape {2H}", (uint8_t)ch);
reset_ansi(); reset_ansi();
dprintln_if(DEBUG_VTTY, "unsupported byte after ansi escape {2H}", (uint8_t)ch);
} }
return; return;
case State::WaitingAnsiCSI: case State::WaitingAnsiCSI:
@ -436,8 +438,8 @@ namespace Kernel
case State::WaitingUTF8: case State::WaitingUTF8:
if ((ch & 0xC0) != 0x80) if ((ch & 0xC0) != 0x80)
{ {
dprintln("invalid utf8");
m_state = State::Normal; m_state = State::Normal;
dprintln_if(DEBUG_VTTY, "invalid utf8");
return; return;
} }
m_utf8_state.codepoint = (m_utf8_state.codepoint << 6) | (ch & 0x3F); m_utf8_state.codepoint = (m_utf8_state.codepoint << 6) | (ch & 0x3F);