• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/runtime/runtime-utils.h"
6 
7 #include "src/arguments.h"
8 #include "src/conversions-inl.h"
9 #include "src/factory.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 
RUNTIME_FUNCTION(Runtime_StringGetRawHashField)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());
20 }
21 
22 
RUNTIME_FUNCTION(Runtime_TheHole)23 RUNTIME_FUNCTION(Runtime_TheHole) {
24   SealHandleScope shs(isolate);
25   DCHECK(args.length() == 0);
26   return isolate->heap()->the_hole_value();
27 }
28 
29 
RUNTIME_FUNCTION(Runtime_JSCollectionGetTable)30 RUNTIME_FUNCTION(Runtime_JSCollectionGetTable) {
31   SealHandleScope shs(isolate);
32   DCHECK(args.length() == 1);
33   CONVERT_ARG_CHECKED(JSObject, object, 0);
34   CHECK(object->IsJSSet() || object->IsJSMap());
35   return static_cast<JSCollection*>(object)->table();
36 }
37 
38 
RUNTIME_FUNCTION(Runtime_GenericHash)39 RUNTIME_FUNCTION(Runtime_GenericHash) {
40   HandleScope scope(isolate);
41   DCHECK(args.length() == 1);
42   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
43   Smi* hash = Object::GetOrCreateHash(isolate, object);
44   return hash;
45 }
46 
47 
RUNTIME_FUNCTION(Runtime_SetInitialize)48 RUNTIME_FUNCTION(Runtime_SetInitialize) {
49   HandleScope scope(isolate);
50   DCHECK(args.length() == 1);
51   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
52   JSSet::Initialize(holder, isolate);
53   return *holder;
54 }
55 
56 
RUNTIME_FUNCTION(Runtime_SetGrow)57 RUNTIME_FUNCTION(Runtime_SetGrow) {
58   HandleScope scope(isolate);
59   DCHECK(args.length() == 1);
60   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
61   Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
62   table = OrderedHashSet::EnsureGrowable(table);
63   holder->set_table(*table);
64   return isolate->heap()->undefined_value();
65 }
66 
67 
RUNTIME_FUNCTION(Runtime_SetShrink)68 RUNTIME_FUNCTION(Runtime_SetShrink) {
69   HandleScope scope(isolate);
70   DCHECK(args.length() == 1);
71   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
72   Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
73   table = OrderedHashSet::Shrink(table);
74   holder->set_table(*table);
75   return isolate->heap()->undefined_value();
76 }
77 
78 
RUNTIME_FUNCTION(Runtime_SetClear)79 RUNTIME_FUNCTION(Runtime_SetClear) {
80   HandleScope scope(isolate);
81   DCHECK(args.length() == 1);
82   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
83   JSSet::Clear(holder);
84   return isolate->heap()->undefined_value();
85 }
86 
87 
RUNTIME_FUNCTION(Runtime_SetIteratorInitialize)88 RUNTIME_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)
94   CHECK(kind == JSSetIterator::kKindValues ||
95         kind == JSSetIterator::kKindEntries);
96   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 
RUNTIME_FUNCTION(Runtime_SetIteratorClone)104 RUNTIME_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 
RUNTIME_FUNCTION(Runtime_SetIteratorNext)118 RUNTIME_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
RUNTIME_FUNCTION(Runtime_SetIteratorDetails)131 RUNTIME_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 
RUNTIME_FUNCTION(Runtime_MapInitialize)143 RUNTIME_FUNCTION(Runtime_MapInitialize) {
144   HandleScope scope(isolate);
145   DCHECK(args.length() == 1);
146   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
147   JSMap::Initialize(holder, isolate);
148   return *holder;
149 }
150 
151 
RUNTIME_FUNCTION(Runtime_MapShrink)152 RUNTIME_FUNCTION(Runtime_MapShrink) {
153   HandleScope scope(isolate);
154   DCHECK(args.length() == 1);
155   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
156   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
157   table = OrderedHashMap::Shrink(table);
158   holder->set_table(*table);
159   return isolate->heap()->undefined_value();
160 }
161 
162 
RUNTIME_FUNCTION(Runtime_MapClear)163 RUNTIME_FUNCTION(Runtime_MapClear) {
164   HandleScope scope(isolate);
165   DCHECK(args.length() == 1);
166   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
167   JSMap::Clear(holder);
168   return isolate->heap()->undefined_value();
169 }
170 
171 
RUNTIME_FUNCTION(Runtime_MapGrow)172 RUNTIME_FUNCTION(Runtime_MapGrow) {
173   HandleScope scope(isolate);
174   DCHECK(args.length() == 1);
175   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
176   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
177   table = OrderedHashMap::EnsureGrowable(table);
178   holder->set_table(*table);
179   return isolate->heap()->undefined_value();
180 }
181 
182 
RUNTIME_FUNCTION(Runtime_MapIteratorInitialize)183 RUNTIME_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)
189   CHECK(kind == JSMapIterator::kKindKeys ||
190         kind == JSMapIterator::kKindValues ||
191         kind == JSMapIterator::kKindEntries);
192   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 
RUNTIME_FUNCTION(Runtime_MapIteratorClone)200 RUNTIME_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
RUNTIME_FUNCTION(Runtime_MapIteratorDetails)218 RUNTIME_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 
RUNTIME_FUNCTION(Runtime_GetWeakMapEntries)230 RUNTIME_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]);
235   CHECK(max_entries >= 0);
236 
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);
243   // Allocation can cause GC can delete weak elements. Reload.
244   if (max_entries > table->NumberOfElements()) {
245     max_entries = table->NumberOfElements();
246   }
247 
248   {
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);
253       if (table->IsKey(isolate, *key)) {
254         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 
RUNTIME_FUNCTION(Runtime_MapIteratorNext)265 RUNTIME_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 
RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize)274 RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) {
275   HandleScope scope(isolate);
276   DCHECK(args.length() == 1);
277   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
278   JSWeakCollection::Initialize(weak_collection, isolate);
279   return *weak_collection;
280 }
281 
282 
RUNTIME_FUNCTION(Runtime_WeakCollectionGet)283 RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
284   HandleScope scope(isolate);
285   DCHECK(args.length() == 3);
286   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
287   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
288   CONVERT_SMI_ARG_CHECKED(hash, 2)
289   CHECK(key->IsJSReceiver() || key->IsSymbol());
290   Handle<ObjectHashTable> table(
291       ObjectHashTable::cast(weak_collection->table()));
292   CHECK(table->IsKey(isolate, *key));
293   Handle<Object> lookup(table->Lookup(key, hash), isolate);
294   return lookup->IsTheHole(isolate) ? isolate->heap()->undefined_value()
295                                     : *lookup;
296 }
297 
298 
RUNTIME_FUNCTION(Runtime_WeakCollectionHas)299 RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
300   HandleScope scope(isolate);
301   DCHECK(args.length() == 3);
302   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
303   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
304   CONVERT_SMI_ARG_CHECKED(hash, 2)
305   CHECK(key->IsJSReceiver() || key->IsSymbol());
306   Handle<ObjectHashTable> table(
307       ObjectHashTable::cast(weak_collection->table()));
308   CHECK(table->IsKey(isolate, *key));
309   Handle<Object> lookup(table->Lookup(key, hash), isolate);
310   return isolate->heap()->ToBoolean(!lookup->IsTheHole(isolate));
311 }
312 
313 
RUNTIME_FUNCTION(Runtime_WeakCollectionDelete)314 RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
315   HandleScope scope(isolate);
316   DCHECK(args.length() == 3);
317   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
318   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
319   CONVERT_SMI_ARG_CHECKED(hash, 2)
320   CHECK(key->IsJSReceiver() || key->IsSymbol());
321   Handle<ObjectHashTable> table(
322       ObjectHashTable::cast(weak_collection->table()));
323   CHECK(table->IsKey(isolate, *key));
324   bool was_present = JSWeakCollection::Delete(weak_collection, key, hash);
325   return isolate->heap()->ToBoolean(was_present);
326 }
327 
328 
RUNTIME_FUNCTION(Runtime_WeakCollectionSet)329 RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
330   HandleScope scope(isolate);
331   DCHECK(args.length() == 4);
332   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
333   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
334   CHECK(key->IsJSReceiver() || key->IsSymbol());
335   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
336   CONVERT_SMI_ARG_CHECKED(hash, 3)
337   Handle<ObjectHashTable> table(
338       ObjectHashTable::cast(weak_collection->table()));
339   CHECK(table->IsKey(isolate, *key));
340   JSWeakCollection::Set(weak_collection, key, value, hash);
341   return *weak_collection;
342 }
343 
344 
RUNTIME_FUNCTION(Runtime_GetWeakSetValues)345 RUNTIME_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]);
350   CHECK(max_values >= 0);
351 
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++) {
365       Object* key = table->KeyAt(i);
366       if (table->IsKey(isolate, key)) values->set(count++, key);
367     }
368     DCHECK_EQ(max_values, count);
369   }
370   return *isolate->factory()->NewJSArrayWithElements(values);
371 }
372 }  // namespace internal
373 }  // namespace v8
374