1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/execution/arguments-inl.h"
6 #include "src/heap/factory.h"
7 #include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
8 #include "src/logging/counters.h"
9 #include "src/numbers/conversions-inl.h"
10 #include "src/objects/hash-table-inl.h"
11 #include "src/objects/js-collection-inl.h"
12 #include "src/runtime/runtime-utils.h"
13
14 namespace v8 {
15 namespace internal {
16
RUNTIME_FUNCTION(Runtime_TheHole)17 RUNTIME_FUNCTION(Runtime_TheHole) {
18 SealHandleScope shs(isolate);
19 DCHECK_EQ(0, args.length());
20 return ReadOnlyRoots(isolate).the_hole_value();
21 }
22
RUNTIME_FUNCTION(Runtime_SetGrow)23 RUNTIME_FUNCTION(Runtime_SetGrow) {
24 HandleScope scope(isolate);
25 DCHECK_EQ(1, args.length());
26 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
27 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()), isolate);
28 MaybeHandle<OrderedHashSet> table_candidate =
29 OrderedHashSet::EnsureGrowable(isolate, table);
30 if (!table_candidate.ToHandle(&table)) {
31 THROW_NEW_ERROR_RETURN_FAILURE(
32 isolate, NewRangeError(MessageTemplate::kValueOutOfRange));
33 }
34 holder->set_table(*table);
35 return ReadOnlyRoots(isolate).undefined_value();
36 }
37
RUNTIME_FUNCTION(Runtime_SetShrink)38 RUNTIME_FUNCTION(Runtime_SetShrink) {
39 HandleScope scope(isolate);
40 DCHECK_EQ(1, args.length());
41 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
42 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()), isolate);
43 table = OrderedHashSet::Shrink(isolate, table);
44 holder->set_table(*table);
45 return ReadOnlyRoots(isolate).undefined_value();
46 }
47
RUNTIME_FUNCTION(Runtime_MapShrink)48 RUNTIME_FUNCTION(Runtime_MapShrink) {
49 HandleScope scope(isolate);
50 DCHECK_EQ(1, args.length());
51 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
52 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()), isolate);
53 table = OrderedHashMap::Shrink(isolate, table);
54 holder->set_table(*table);
55 return ReadOnlyRoots(isolate).undefined_value();
56 }
57
RUNTIME_FUNCTION(Runtime_MapGrow)58 RUNTIME_FUNCTION(Runtime_MapGrow) {
59 HandleScope scope(isolate);
60 DCHECK_EQ(1, args.length());
61 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
62 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()), isolate);
63 MaybeHandle<OrderedHashMap> table_candidate =
64 OrderedHashMap::EnsureGrowable(isolate, table);
65 if (!table_candidate.ToHandle(&table)) {
66 THROW_NEW_ERROR_RETURN_FAILURE(
67 isolate, NewRangeError(MessageTemplate::kValueOutOfRange));
68 }
69 holder->set_table(*table);
70 return ReadOnlyRoots(isolate).undefined_value();
71 }
72
RUNTIME_FUNCTION(Runtime_WeakCollectionDelete)73 RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
74 HandleScope scope(isolate);
75 DCHECK_EQ(3, args.length());
76 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
77 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
78 CONVERT_SMI_ARG_CHECKED(hash, 2)
79
80 #ifdef DEBUG
81 DCHECK(key->IsJSReceiver());
82 DCHECK(EphemeronHashTable::IsKey(ReadOnlyRoots(isolate), *key));
83 Handle<EphemeronHashTable> table(
84 EphemeronHashTable::cast(weak_collection->table()), isolate);
85 // Should only be called when shrinking the table is necessary. See
86 // HashTable::Shrink().
87 DCHECK(table->NumberOfElements() - 1 <= (table->Capacity() >> 2) &&
88 table->NumberOfElements() - 1 >= 16);
89 #endif
90
91 bool was_present = JSWeakCollection::Delete(weak_collection, key, hash);
92 return isolate->heap()->ToBoolean(was_present);
93 }
94
RUNTIME_FUNCTION(Runtime_WeakCollectionSet)95 RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
96 HandleScope scope(isolate);
97 DCHECK_EQ(4, args.length());
98 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
99 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
100 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
101 CONVERT_SMI_ARG_CHECKED(hash, 3)
102
103 #ifdef DEBUG
104 DCHECK(key->IsJSReceiver());
105 DCHECK(EphemeronHashTable::IsKey(ReadOnlyRoots(isolate), *key));
106 Handle<EphemeronHashTable> table(
107 EphemeronHashTable::cast(weak_collection->table()), isolate);
108 // Should only be called when rehashing or resizing the table is necessary.
109 // See EphemeronHashTable::Put() and HashTable::HasSufficientCapacityToAdd().
110 DCHECK((table->NumberOfDeletedElements() << 1) > table->NumberOfElements() ||
111 !table->HasSufficientCapacityToAdd(1));
112 #endif
113
114 JSWeakCollection::Set(weak_collection, key, value, hash);
115 return *weak_collection;
116 }
117
118 } // namespace internal
119 } // namespace v8
120