Skip to content

Commit c192e5c

Browse files
committed
Allow OOM strategy for RBTree
1 parent 124575b commit c192e5c

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

src/hotspot/share/utilities/rbTree.hpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -468,13 +468,17 @@ class RBTree : public AbstractRBTree<K, RBNode<K, V>, COMPARATOR> {
468468

469469
RBNode<K, V>* allocate_node(const K& key) {
470470
void* node_place = _allocator.allocate(sizeof(RBNode<K, V>));
471-
assert(node_place != nullptr, "rb-tree allocator must exit on failure");
471+
if (node_place == nullptr) {
472+
return nullptr;
473+
}
472474
return new (node_place) RBNode<K, V>(key);
473475
}
474476

475477
RBNode<K, V>* allocate_node(const K& key, const V& val) {
476478
void* node_place = _allocator.allocate(sizeof(RBNode<K, V>));
477-
assert(node_place != nullptr, "rb-tree allocator must exit on failure");
479+
if (node_place == nullptr) {
480+
return nullptr;
481+
}
478482
return new (node_place) RBNode<K, V>(key, val);
479483
}
480484

@@ -485,16 +489,21 @@ class RBTree : public AbstractRBTree<K, RBNode<K, V>, COMPARATOR> {
485489

486490
// Inserts a node with the given key/value into the tree,
487491
// if the key already exist, the value is updated instead.
488-
void upsert(const K& key, const V& val, const RBNode<K, V>* hint_node = nullptr) {
492+
// Returns false if and only if allocation of a new node failed.
493+
bool upsert(const K& key, const V& val, const RBNode<K, V>* hint_node = nullptr) {
489494
Cursor node_cursor = cursor(key, hint_node);
490495
RBNode<K, V>* node = node_cursor.node();
491496
if (node != nullptr) {
492497
node->set_val(val);
493-
return;
498+
return true;
494499
}
495500

496501
node = allocate_node(key, val);
502+
if (node == nullptr) {
503+
return false;
504+
}
497505
insert_at_cursor(node, node_cursor);
506+
return true;
498507
}
499508

500509
// Finds the value of the node associated with the given key.
@@ -545,12 +554,12 @@ class RBTree : public AbstractRBTree<K, RBNode<K, V>, COMPARATOR> {
545554
}
546555
};
547556

548-
template <MemTag mem_tag>
557+
template <MemTag mem_tag, AllocFailType strategy>
549558
class RBTreeCHeapAllocator {
550559
public:
551560
void* allocate(size_t sz) {
552561
void* allocation = os::malloc(sz, mem_tag);
553-
if (allocation == nullptr) {
562+
if (allocation == nullptr && strategy == AllocFailStrategy::EXIT_OOM) {
554563
vm_exit_out_of_memory(sz, OOM_MALLOC_ERROR,
555564
"red-black tree failed allocation");
556565
}
@@ -560,8 +569,8 @@ class RBTreeCHeapAllocator {
560569
void free(void* ptr) { os::free(ptr); }
561570
};
562571

563-
template <typename K, typename V, typename COMPARATOR, MemTag mem_tag>
564-
using RBTreeCHeap = RBTree<K, V, COMPARATOR, RBTreeCHeapAllocator<mem_tag>>;
572+
template <typename K, typename V, typename COMPARATOR, MemTag mem_tag, AllocFailStrategy strategy = AllocFailStrategy::EXIT_OOM>
573+
using RBTreeCHeap = RBTree<K, V, COMPARATOR, RBTreeCHeapAllocator<mem_tag, strategy>>;
565574

566575
template <typename K, typename COMPARATOR>
567576
using IntrusiveRBTree = AbstractRBTree<K, IntrusiveRBNode, COMPARATOR>;

test/hotspot/gtest/utilities/test_rbtree.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,3 +1079,15 @@ TEST_VM_F(RBTreeTest, VerifyItThroughStressTest) {
10791079
}
10801080
}
10811081

1082+
struct OomAllocator {
1083+
void* allocate(size_t sz) {
1084+
return nullptr;
1085+
}
1086+
void free(void* ptr) {}
1087+
};
1088+
TEST_VM_F(RBTreeTest, AllocatorMayReturnNull) {
1089+
RBTree<int, int, Cmp, OomAllocator> rbtree;
1090+
bool success = rbtree.upsert(5, 5);
1091+
EXPECT_EQ(false, success);
1092+
// The test didn't exit the VM, so it was succesful.
1093+
}

0 commit comments

Comments
 (0)