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
14namespace v8 {
15namespace internal {
16
17RUNTIME_FUNCTION(Runtime_TheHole) {
18  SealHandleScope shs(isolate);
19  DCHECK_EQ(0, args.length());
20  return ReadOnlyRoots(isolate).the_hole_value();
21}
22
23RUNTIME_FUNCTION(Runtime_SetGrow) {
24  HandleScope scope(isolate);
25  DCHECK_EQ(1, args.length());
26  Handle<JSSet> holder = args.at<JSSet>(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,
33        NewRangeError(MessageTemplate::kCollectionGrowFailed,
34                      isolate->factory()->NewStringFromAsciiChecked("Set")));
35  }
36  holder->set_table(*table);
37  return ReadOnlyRoots(isolate).undefined_value();
38}
39
40RUNTIME_FUNCTION(Runtime_SetShrink) {
41  HandleScope scope(isolate);
42  DCHECK_EQ(1, args.length());
43  Handle<JSSet> holder = args.at<JSSet>(0);
44  Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()), isolate);
45  table = OrderedHashSet::Shrink(isolate, table);
46  holder->set_table(*table);
47  return ReadOnlyRoots(isolate).undefined_value();
48}
49
50RUNTIME_FUNCTION(Runtime_MapShrink) {
51  HandleScope scope(isolate);
52  DCHECK_EQ(1, args.length());
53  Handle<JSMap> holder = args.at<JSMap>(0);
54  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()), isolate);
55  table = OrderedHashMap::Shrink(isolate, table);
56  holder->set_table(*table);
57  return ReadOnlyRoots(isolate).undefined_value();
58}
59
60RUNTIME_FUNCTION(Runtime_MapGrow) {
61  HandleScope scope(isolate);
62  DCHECK_EQ(1, args.length());
63  Handle<JSMap> holder = args.at<JSMap>(0);
64  Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()), isolate);
65  MaybeHandle<OrderedHashMap> table_candidate =
66      OrderedHashMap::EnsureGrowable(isolate, table);
67  if (!table_candidate.ToHandle(&table)) {
68    THROW_NEW_ERROR_RETURN_FAILURE(
69        isolate,
70        NewRangeError(MessageTemplate::kCollectionGrowFailed,
71                      isolate->factory()->NewStringFromAsciiChecked("Map")));
72  }
73  holder->set_table(*table);
74  return ReadOnlyRoots(isolate).undefined_value();
75}
76
77RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
78  HandleScope scope(isolate);
79  DCHECK_EQ(3, args.length());
80  Handle<JSWeakCollection> weak_collection = args.at<JSWeakCollection>(0);
81  Handle<Object> key = args.at(1);
82  int hash = args.smi_value_at(2);
83
84#ifdef DEBUG
85  DCHECK(key->CanBeHeldWeakly());
86  DCHECK(EphemeronHashTable::IsKey(ReadOnlyRoots(isolate), *key));
87  Handle<EphemeronHashTable> table(
88      EphemeronHashTable::cast(weak_collection->table()), isolate);
89  // Should only be called when shrinking the table is necessary. See
90  // HashTable::Shrink().
91  DCHECK(table->NumberOfElements() - 1 <= (table->Capacity() >> 2) &&
92         table->NumberOfElements() - 1 >= 16);
93#endif
94
95  bool was_present = JSWeakCollection::Delete(weak_collection, key, hash);
96  return isolate->heap()->ToBoolean(was_present);
97}
98
99RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
100  HandleScope scope(isolate);
101  DCHECK_EQ(4, args.length());
102  Handle<JSWeakCollection> weak_collection = args.at<JSWeakCollection>(0);
103  Handle<Object> key = args.at(1);
104  Handle<Object> value = args.at(2);
105  int hash = args.smi_value_at(3);
106
107#ifdef DEBUG
108  DCHECK(key->CanBeHeldWeakly());
109  DCHECK(EphemeronHashTable::IsKey(ReadOnlyRoots(isolate), *key));
110  Handle<EphemeronHashTable> table(
111      EphemeronHashTable::cast(weak_collection->table()), isolate);
112  // Should only be called when rehashing or resizing the table is necessary.
113  // See EphemeronHashTable::Put() and HashTable::HasSufficientCapacityToAdd().
114  DCHECK((table->NumberOfDeletedElements() << 1) > table->NumberOfElements() ||
115         !table->HasSufficientCapacityToAdd(1));
116#endif
117
118  JSWeakCollection::Set(weak_collection, key, value, hash);
119  return *weak_collection;
120}
121
122}  // namespace internal
123}  // namespace v8
124