blob: b25a5ef5c2f5a531bae09267200621b49a2638da [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/runtime/runtime-utils.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/arguments.h"
8#include "src/conversions-inl.h"
9#include "src/factory.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010
11namespace v8 {
12namespace internal {
13
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014
15RUNTIME_FUNCTION(Runtime_StringGetRawHashField) {
16 HandleScope scope(isolate);
17 DCHECK(args.length() == 1);
18 CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
19 return *isolate->factory()->NewNumberFromUint(string->hash_field());
20}
21
22
23RUNTIME_FUNCTION(Runtime_TheHole) {
24 SealHandleScope shs(isolate);
25 DCHECK(args.length() == 0);
26 return isolate->heap()->the_hole_value();
27}
28
29
30RUNTIME_FUNCTION(Runtime_JSCollectionGetTable) {
31 SealHandleScope shs(isolate);
32 DCHECK(args.length() == 1);
33 CONVERT_ARG_CHECKED(JSObject, object, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +010034 CHECK(object->IsJSSet() || object->IsJSMap());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 return static_cast<JSCollection*>(object)->table();
36}
37
38
39RUNTIME_FUNCTION(Runtime_GenericHash) {
40 HandleScope scope(isolate);
41 DCHECK(args.length() == 1);
42 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +010043 Smi* hash = Object::GetOrCreateHash(isolate, object);
44 return hash;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045}
46
47
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048RUNTIME_FUNCTION(Runtime_SetInitialize) {
49 HandleScope scope(isolate);
50 DCHECK(args.length() == 1);
51 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 JSSet::Initialize(holder, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053 return *holder;
54}
55
56
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057RUNTIME_FUNCTION(Runtime_SetGrow) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 DCHECK(args.length() == 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040060 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040061 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 table = OrderedHashSet::EnsureGrowable(table);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063 holder->set_table(*table);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065}
66
67
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068RUNTIME_FUNCTION(Runtime_SetShrink) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040069 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 DCHECK(args.length() == 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040071 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 table = OrderedHashSet::Shrink(table);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074 holder->set_table(*table);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076}
77
78
79RUNTIME_FUNCTION(Runtime_SetClear) {
80 HandleScope scope(isolate);
81 DCHECK(args.length() == 1);
82 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 JSSet::Clear(holder);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084 return isolate->heap()->undefined_value();
85}
86
87
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) {
89 HandleScope scope(isolate);
90 DCHECK(args.length() == 3);
91 CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
92 CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1);
93 CONVERT_SMI_ARG_CHECKED(kind, 2)
Ben Murdoch61f157c2016-09-16 13:49:30 +010094 CHECK(kind == JSSetIterator::kKindValues ||
95 kind == JSSetIterator::kKindEntries);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
97 holder->set_table(*table);
98 holder->set_index(Smi::FromInt(0));
99 holder->set_kind(Smi::FromInt(kind));
100 return isolate->heap()->undefined_value();
101}
102
103
104RUNTIME_FUNCTION(Runtime_SetIteratorClone) {
105 HandleScope scope(isolate);
106 DCHECK(args.length() == 1);
107 CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
108
109 Handle<JSSetIterator> result = isolate->factory()->NewJSSetIterator();
110 result->set_table(holder->table());
111 result->set_index(Smi::FromInt(Smi::cast(holder->index())->value()));
112 result->set_kind(Smi::FromInt(Smi::cast(holder->kind())->value()));
113
114 return *result;
115}
116
117
118RUNTIME_FUNCTION(Runtime_SetIteratorNext) {
119 SealHandleScope shs(isolate);
120 DCHECK(args.length() == 2);
121 CONVERT_ARG_CHECKED(JSSetIterator, holder, 0);
122 CONVERT_ARG_CHECKED(JSArray, value_array, 1);
123 return holder->Next(value_array);
124}
125
126
127// The array returned contains the following information:
128// 0: HasMore flag
129// 1: Iteration index
130// 2: Iteration kind
131RUNTIME_FUNCTION(Runtime_SetIteratorDetails) {
132 HandleScope scope(isolate);
133 DCHECK(args.length() == 1);
134 CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
135 Handle<FixedArray> details = isolate->factory()->NewFixedArray(4);
136 details->set(0, isolate->heap()->ToBoolean(holder->HasMore()));
137 details->set(1, holder->index());
138 details->set(2, holder->kind());
139 return *isolate->factory()->NewJSArrayWithElements(details);
140}
141
142
143RUNTIME_FUNCTION(Runtime_MapInitialize) {
144 HandleScope scope(isolate);
145 DCHECK(args.length() == 1);
146 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 JSMap::Initialize(holder, isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400148 return *holder;
149}
150
151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152RUNTIME_FUNCTION(Runtime_MapShrink) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400153 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 DCHECK(args.length() == 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 table = OrderedHashMap::Shrink(table);
158 holder->set_table(*table);
159 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400160}
161
162
163RUNTIME_FUNCTION(Runtime_MapClear) {
164 HandleScope scope(isolate);
165 DCHECK(args.length() == 1);
166 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 JSMap::Clear(holder);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 return isolate->heap()->undefined_value();
169}
170
171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172RUNTIME_FUNCTION(Runtime_MapGrow) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173 HandleScope scope(isolate);
174 DCHECK(args.length() == 1);
175 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
176 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 table = OrderedHashMap::EnsureGrowable(table);
178 holder->set_table(*table);
179 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400180}
181
182
183RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) {
184 HandleScope scope(isolate);
185 DCHECK(args.length() == 3);
186 CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
187 CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1);
188 CONVERT_SMI_ARG_CHECKED(kind, 2)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100189 CHECK(kind == JSMapIterator::kKindKeys ||
190 kind == JSMapIterator::kKindValues ||
191 kind == JSMapIterator::kKindEntries);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
193 holder->set_table(*table);
194 holder->set_index(Smi::FromInt(0));
195 holder->set_kind(Smi::FromInt(kind));
196 return isolate->heap()->undefined_value();
197}
198
199
200RUNTIME_FUNCTION(Runtime_MapIteratorClone) {
201 HandleScope scope(isolate);
202 DCHECK(args.length() == 1);
203 CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
204
205 Handle<JSMapIterator> result = isolate->factory()->NewJSMapIterator();
206 result->set_table(holder->table());
207 result->set_index(Smi::FromInt(Smi::cast(holder->index())->value()));
208 result->set_kind(Smi::FromInt(Smi::cast(holder->kind())->value()));
209
210 return *result;
211}
212
213
214// The array returned contains the following information:
215// 0: HasMore flag
216// 1: Iteration index
217// 2: Iteration kind
218RUNTIME_FUNCTION(Runtime_MapIteratorDetails) {
219 HandleScope scope(isolate);
220 DCHECK(args.length() == 1);
221 CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
222 Handle<FixedArray> details = isolate->factory()->NewFixedArray(4);
223 details->set(0, isolate->heap()->ToBoolean(holder->HasMore()));
224 details->set(1, holder->index());
225 details->set(2, holder->kind());
226 return *isolate->factory()->NewJSArrayWithElements(details);
227}
228
229
230RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
231 HandleScope scope(isolate);
232 DCHECK(args.length() == 2);
233 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
234 CONVERT_NUMBER_CHECKED(int, max_entries, Int32, args[1]);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100235 CHECK(max_entries >= 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400236
237 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
238 if (max_entries == 0 || max_entries > table->NumberOfElements()) {
239 max_entries = table->NumberOfElements();
240 }
241 Handle<FixedArray> entries =
242 isolate->factory()->NewFixedArray(max_entries * 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 // Allocation can cause GC can delete weak elements. Reload.
244 if (max_entries > table->NumberOfElements()) {
245 max_entries = table->NumberOfElements();
246 }
247
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248 {
249 DisallowHeapAllocation no_gc;
250 int count = 0;
251 for (int i = 0; count / 2 < max_entries && i < table->Capacity(); i++) {
252 Handle<Object> key(table->KeyAt(i), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100253 if (table->IsKey(isolate, *key)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400254 entries->set(count++, *key);
255 Object* value = table->Lookup(key);
256 entries->set(count++, value);
257 }
258 }
259 DCHECK_EQ(max_entries * 2, count);
260 }
261 return *isolate->factory()->NewJSArrayWithElements(entries);
262}
263
264
265RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
266 SealHandleScope shs(isolate);
267 DCHECK(args.length() == 2);
268 CONVERT_ARG_CHECKED(JSMapIterator, holder, 0);
269 CONVERT_ARG_CHECKED(JSArray, value_array, 1);
270 return holder->Next(value_array);
271}
272
273
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400274RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) {
275 HandleScope scope(isolate);
276 DCHECK(args.length() == 1);
277 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 JSWeakCollection::Initialize(weak_collection, isolate);
279 return *weak_collection;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400280}
281
282
283RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
284 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 DCHECK(args.length() == 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400286 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
287 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 CONVERT_SMI_ARG_CHECKED(hash, 2)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100289 CHECK(key->IsJSReceiver() || key->IsSymbol());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290 Handle<ObjectHashTable> table(
291 ObjectHashTable::cast(weak_collection->table()));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100292 CHECK(table->IsKey(isolate, *key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 Handle<Object> lookup(table->Lookup(key, hash), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100294 return lookup->IsTheHole(isolate) ? isolate->heap()->undefined_value()
295 : *lookup;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400296}
297
298
299RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
300 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 DCHECK(args.length() == 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400302 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
303 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 CONVERT_SMI_ARG_CHECKED(hash, 2)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100305 CHECK(key->IsJSReceiver() || key->IsSymbol());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400306 Handle<ObjectHashTable> table(
307 ObjectHashTable::cast(weak_collection->table()));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100308 CHECK(table->IsKey(isolate, *key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 Handle<Object> lookup(table->Lookup(key, hash), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100310 return isolate->heap()->ToBoolean(!lookup->IsTheHole(isolate));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311}
312
313
314RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
315 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316 DCHECK(args.length() == 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400317 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
318 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 CONVERT_SMI_ARG_CHECKED(hash, 2)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100320 CHECK(key->IsJSReceiver() || key->IsSymbol());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400321 Handle<ObjectHashTable> table(
322 ObjectHashTable::cast(weak_collection->table()));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100323 CHECK(table->IsKey(isolate, *key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 bool was_present = JSWeakCollection::Delete(weak_collection, key, hash);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400325 return isolate->heap()->ToBoolean(was_present);
326}
327
328
329RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
330 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 DCHECK(args.length() == 4);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400332 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
333 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100334 CHECK(key->IsJSReceiver() || key->IsSymbol());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400335 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 CONVERT_SMI_ARG_CHECKED(hash, 3)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337 Handle<ObjectHashTable> table(
338 ObjectHashTable::cast(weak_collection->table()));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100339 CHECK(table->IsKey(isolate, *key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 JSWeakCollection::Set(weak_collection, key, value, hash);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 return *weak_collection;
342}
343
344
345RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
346 HandleScope scope(isolate);
347 DCHECK(args.length() == 2);
348 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
349 CONVERT_NUMBER_CHECKED(int, max_values, Int32, args[1]);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100350 CHECK(max_values >= 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400351
352 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
353 if (max_values == 0 || max_values > table->NumberOfElements()) {
354 max_values = table->NumberOfElements();
355 }
356 Handle<FixedArray> values = isolate->factory()->NewFixedArray(max_values);
357 // Recompute max_values because GC could have removed elements from the table.
358 if (max_values > table->NumberOfElements()) {
359 max_values = table->NumberOfElements();
360 }
361 {
362 DisallowHeapAllocation no_gc;
363 int count = 0;
364 for (int i = 0; count < max_values && i < table->Capacity(); i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100365 Object* key = table->KeyAt(i);
366 if (table->IsKey(isolate, key)) values->set(count++, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400367 }
368 DCHECK_EQ(max_values, count);
369 }
370 return *isolate->factory()->NewJSArrayWithElements(values);
371}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372} // namespace internal
373} // namespace v8