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.
7 #include "src/arguments.h"
8 #include "src/runtime/runtime-utils.h"
15 RUNTIME_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());
23 RUNTIME_FUNCTION(Runtime_TheHole) {
24 SealHandleScope shs(isolate);
25 DCHECK(args.length() == 0);
26 return isolate->heap()->the_hole_value();
30 RUNTIME_FUNCTION(Runtime_JSCollectionGetTable) {
31 SealHandleScope shs(isolate);
32 DCHECK(args.length() == 1);
33 CONVERT_ARG_CHECKED(JSObject, object, 0);
34 RUNTIME_ASSERT(object->IsJSSet() || object->IsJSMap());
35 return static_cast<JSCollection*>(object)->table();
39 RUNTIME_FUNCTION(Runtime_GenericHash) {
40 HandleScope scope(isolate);
41 DCHECK(args.length() == 1);
42 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
43 Handle<Smi> hash = Object::GetOrCreateHash(isolate, object);
48 void Runtime::JSSetInitialize(Isolate* isolate, Handle<JSSet> set) {
49 Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
50 set->set_table(*table);
54 RUNTIME_FUNCTION(Runtime_SetInitialize) {
55 HandleScope scope(isolate);
56 DCHECK(args.length() == 1);
57 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
58 Runtime::JSSetInitialize(isolate, holder);
63 RUNTIME_FUNCTION(Runtime_SetGrow) {
64 HandleScope scope(isolate);
65 DCHECK(args.length() == 1);
66 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
67 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
68 table = OrderedHashSet::EnsureGrowable(table);
69 holder->set_table(*table);
70 return isolate->heap()->undefined_value();
74 RUNTIME_FUNCTION(Runtime_SetShrink) {
75 HandleScope scope(isolate);
76 DCHECK(args.length() == 1);
77 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
78 Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
79 table = OrderedHashSet::Shrink(table);
80 holder->set_table(*table);
81 return isolate->heap()->undefined_value();
85 void Runtime::JSSetClear(Isolate* isolate, Handle<JSSet> set) {
86 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
87 table = OrderedHashSet::Clear(table);
88 set->set_table(*table);
92 RUNTIME_FUNCTION(Runtime_SetClear) {
93 HandleScope scope(isolate);
94 DCHECK(args.length() == 1);
95 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
96 Runtime::JSSetClear(isolate, holder);
97 return isolate->heap()->undefined_value();
101 RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) {
102 HandleScope scope(isolate);
103 DCHECK(args.length() == 3);
104 CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
105 CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1);
106 CONVERT_SMI_ARG_CHECKED(kind, 2)
107 RUNTIME_ASSERT(kind == JSSetIterator::kKindValues ||
108 kind == JSSetIterator::kKindEntries);
109 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
110 holder->set_table(*table);
111 holder->set_index(Smi::FromInt(0));
112 holder->set_kind(Smi::FromInt(kind));
113 return isolate->heap()->undefined_value();
117 RUNTIME_FUNCTION(Runtime_SetIteratorClone) {
118 HandleScope scope(isolate);
119 DCHECK(args.length() == 1);
120 CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
122 Handle<JSSetIterator> result = isolate->factory()->NewJSSetIterator();
123 result->set_table(holder->table());
124 result->set_index(Smi::FromInt(Smi::cast(holder->index())->value()));
125 result->set_kind(Smi::FromInt(Smi::cast(holder->kind())->value()));
131 RUNTIME_FUNCTION(Runtime_SetIteratorNext) {
132 SealHandleScope shs(isolate);
133 DCHECK(args.length() == 2);
134 CONVERT_ARG_CHECKED(JSSetIterator, holder, 0);
135 CONVERT_ARG_CHECKED(JSArray, value_array, 1);
136 return holder->Next(value_array);
140 // The array returned contains the following information:
142 // 1: Iteration index
144 RUNTIME_FUNCTION(Runtime_SetIteratorDetails) {
145 HandleScope scope(isolate);
146 DCHECK(args.length() == 1);
147 CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
148 Handle<FixedArray> details = isolate->factory()->NewFixedArray(4);
149 details->set(0, isolate->heap()->ToBoolean(holder->HasMore()));
150 details->set(1, holder->index());
151 details->set(2, holder->kind());
152 return *isolate->factory()->NewJSArrayWithElements(details);
156 void Runtime::JSMapInitialize(Isolate* isolate, Handle<JSMap> map) {
157 Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
158 map->set_table(*table);
162 RUNTIME_FUNCTION(Runtime_MapInitialize) {
163 HandleScope scope(isolate);
164 DCHECK(args.length() == 1);
165 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
166 Runtime::JSMapInitialize(isolate, holder);
171 RUNTIME_FUNCTION(Runtime_MapShrink) {
172 HandleScope scope(isolate);
173 DCHECK(args.length() == 1);
174 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
175 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
176 table = OrderedHashMap::Shrink(table);
177 holder->set_table(*table);
178 return isolate->heap()->undefined_value();
182 void Runtime::JSMapClear(Isolate* isolate, Handle<JSMap> map) {
183 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
184 table = OrderedHashMap::Clear(table);
185 map->set_table(*table);
189 RUNTIME_FUNCTION(Runtime_MapClear) {
190 HandleScope scope(isolate);
191 DCHECK(args.length() == 1);
192 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
193 Runtime::JSMapClear(isolate, holder);
194 return isolate->heap()->undefined_value();
198 RUNTIME_FUNCTION(Runtime_MapGrow) {
199 HandleScope scope(isolate);
200 DCHECK(args.length() == 1);
201 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
202 Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
203 table = OrderedHashMap::EnsureGrowable(table);
204 holder->set_table(*table);
205 return isolate->heap()->undefined_value();
209 RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) {
210 HandleScope scope(isolate);
211 DCHECK(args.length() == 3);
212 CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
213 CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1);
214 CONVERT_SMI_ARG_CHECKED(kind, 2)
215 RUNTIME_ASSERT(kind == JSMapIterator::kKindKeys ||
216 kind == JSMapIterator::kKindValues ||
217 kind == JSMapIterator::kKindEntries);
218 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
219 holder->set_table(*table);
220 holder->set_index(Smi::FromInt(0));
221 holder->set_kind(Smi::FromInt(kind));
222 return isolate->heap()->undefined_value();
226 RUNTIME_FUNCTION(Runtime_MapIteratorClone) {
227 HandleScope scope(isolate);
228 DCHECK(args.length() == 1);
229 CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
231 Handle<JSMapIterator> result = isolate->factory()->NewJSMapIterator();
232 result->set_table(holder->table());
233 result->set_index(Smi::FromInt(Smi::cast(holder->index())->value()));
234 result->set_kind(Smi::FromInt(Smi::cast(holder->kind())->value()));
240 // The array returned contains the following information:
242 // 1: Iteration index
244 RUNTIME_FUNCTION(Runtime_MapIteratorDetails) {
245 HandleScope scope(isolate);
246 DCHECK(args.length() == 1);
247 CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
248 Handle<FixedArray> details = isolate->factory()->NewFixedArray(4);
249 details->set(0, isolate->heap()->ToBoolean(holder->HasMore()));
250 details->set(1, holder->index());
251 details->set(2, holder->kind());
252 return *isolate->factory()->NewJSArrayWithElements(details);
256 RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
257 HandleScope scope(isolate);
258 DCHECK(args.length() == 2);
259 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
260 CONVERT_NUMBER_CHECKED(int, max_entries, Int32, args[1]);
261 RUNTIME_ASSERT(max_entries >= 0);
263 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
264 if (max_entries == 0 || max_entries > table->NumberOfElements()) {
265 max_entries = table->NumberOfElements();
267 Handle<FixedArray> entries =
268 isolate->factory()->NewFixedArray(max_entries * 2);
269 // Allocation can cause GC can delete weak elements. Reload.
270 if (max_entries > table->NumberOfElements()) {
271 max_entries = table->NumberOfElements();
275 DisallowHeapAllocation no_gc;
277 for (int i = 0; count / 2 < max_entries && i < table->Capacity(); i++) {
278 Handle<Object> key(table->KeyAt(i), isolate);
279 if (table->IsKey(*key)) {
280 entries->set(count++, *key);
281 Object* value = table->Lookup(key);
282 entries->set(count++, value);
285 DCHECK_EQ(max_entries * 2, count);
287 return *isolate->factory()->NewJSArrayWithElements(entries);
291 RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
292 SealHandleScope shs(isolate);
293 DCHECK(args.length() == 2);
294 CONVERT_ARG_CHECKED(JSMapIterator, holder, 0);
295 CONVERT_ARG_CHECKED(JSArray, value_array, 1);
296 return holder->Next(value_array);
300 void Runtime::WeakCollectionInitialize(
301 Isolate* isolate, Handle<JSWeakCollection> weak_collection) {
302 DCHECK(weak_collection->map()->inobject_properties() == 0);
303 Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
304 weak_collection->set_table(*table);
308 RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) {
309 HandleScope scope(isolate);
310 DCHECK(args.length() == 1);
311 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
312 Runtime::WeakCollectionInitialize(isolate, weak_collection);
313 return *weak_collection;
317 RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
318 HandleScope scope(isolate);
319 DCHECK(args.length() == 3);
320 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
321 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
322 CONVERT_SMI_ARG_CHECKED(hash, 2)
323 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
324 Handle<ObjectHashTable> table(
325 ObjectHashTable::cast(weak_collection->table()));
326 RUNTIME_ASSERT(table->IsKey(*key));
327 Handle<Object> lookup(table->Lookup(key, hash), isolate);
328 return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
332 RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
333 HandleScope scope(isolate);
334 DCHECK(args.length() == 3);
335 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
336 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
337 CONVERT_SMI_ARG_CHECKED(hash, 2)
338 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
339 Handle<ObjectHashTable> table(
340 ObjectHashTable::cast(weak_collection->table()));
341 RUNTIME_ASSERT(table->IsKey(*key));
342 Handle<Object> lookup(table->Lookup(key, hash), isolate);
343 return isolate->heap()->ToBoolean(!lookup->IsTheHole());
347 bool Runtime::WeakCollectionDelete(Handle<JSWeakCollection> weak_collection,
348 Handle<Object> key) {
350 Object::GetOrCreateHash(weak_collection->GetIsolate(), key)->value();
351 return WeakCollectionDelete(weak_collection, key, hash);
355 bool Runtime::WeakCollectionDelete(Handle<JSWeakCollection> weak_collection,
356 Handle<Object> key, int32_t hash) {
357 DCHECK(key->IsJSReceiver() || key->IsSymbol());
358 Handle<ObjectHashTable> table(
359 ObjectHashTable::cast(weak_collection->table()));
360 DCHECK(table->IsKey(*key));
361 bool was_present = false;
362 Handle<ObjectHashTable> new_table =
363 ObjectHashTable::Remove(table, key, &was_present, hash);
364 weak_collection->set_table(*new_table);
365 if (*table != *new_table) {
366 // Zap the old table since we didn't record slots for its elements.
367 table->FillWithHoles(0, table->length());
373 RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
374 HandleScope scope(isolate);
375 DCHECK(args.length() == 3);
376 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
377 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
378 CONVERT_SMI_ARG_CHECKED(hash, 2)
379 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
380 Handle<ObjectHashTable> table(
381 ObjectHashTable::cast(weak_collection->table()));
382 RUNTIME_ASSERT(table->IsKey(*key));
383 bool was_present = Runtime::WeakCollectionDelete(weak_collection, key, hash);
384 return isolate->heap()->ToBoolean(was_present);
388 void Runtime::WeakCollectionSet(Handle<JSWeakCollection> weak_collection,
389 Handle<Object> key, Handle<Object> value,
391 DCHECK(key->IsJSReceiver() || key->IsSymbol());
392 Handle<ObjectHashTable> table(
393 ObjectHashTable::cast(weak_collection->table()));
394 DCHECK(table->IsKey(*key));
395 Handle<ObjectHashTable> new_table =
396 ObjectHashTable::Put(table, key, value, hash);
397 weak_collection->set_table(*new_table);
398 if (*table != *new_table) {
399 // Zap the old table since we didn't record slots for its elements.
400 table->FillWithHoles(0, table->length());
405 RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
406 HandleScope scope(isolate);
407 DCHECK(args.length() == 4);
408 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
409 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
410 RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
411 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
412 CONVERT_SMI_ARG_CHECKED(hash, 3)
413 Handle<ObjectHashTable> table(
414 ObjectHashTable::cast(weak_collection->table()));
415 RUNTIME_ASSERT(table->IsKey(*key));
416 Runtime::WeakCollectionSet(weak_collection, key, value, hash);
417 return *weak_collection;
421 RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
422 HandleScope scope(isolate);
423 DCHECK(args.length() == 2);
424 CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
425 CONVERT_NUMBER_CHECKED(int, max_values, Int32, args[1]);
426 RUNTIME_ASSERT(max_values >= 0);
428 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
429 if (max_values == 0 || max_values > table->NumberOfElements()) {
430 max_values = table->NumberOfElements();
432 Handle<FixedArray> values = isolate->factory()->NewFixedArray(max_values);
433 // Recompute max_values because GC could have removed elements from the table.
434 if (max_values > table->NumberOfElements()) {
435 max_values = table->NumberOfElements();
438 DisallowHeapAllocation no_gc;
440 for (int i = 0; count < max_values && i < table->Capacity(); i++) {
441 Handle<Object> key(table->KeyAt(i), isolate);
442 if (table->IsKey(*key)) values->set(count++, *key);
444 DCHECK_EQ(max_values, count);
446 return *isolate->factory()->NewJSArrayWithElements(values);
450 RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) {
451 HandleScope scope(isolate);
452 DCHECK(args.length() == 0);
453 Handle<JSWeakMap> weakmap = isolate->factory()->NewJSWeakMap();
454 Runtime::WeakCollectionInitialize(isolate, weakmap);
457 } // namespace internal