Home | History | Annotate | Download | only in runtime
      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 
     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 
     23 RUNTIME_FUNCTION(Runtime_TheHole) {
     24   SealHandleScope shs(isolate);
     25   DCHECK(args.length() == 0);
     26   return isolate->heap()->the_hole_value();
     27 }
     28 
     29 
     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();
     36 }
     37 
     38 
     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);
     44   return *hash;
     45 }
     46 
     47 
     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 
     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 
     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 
     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 
     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   RUNTIME_ASSERT(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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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   RUNTIME_ASSERT(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 
    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
    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 
    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   RUNTIME_ASSERT(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(*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 
    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 
    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 
    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   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
    290   Handle<ObjectHashTable> table(
    291       ObjectHashTable::cast(weak_collection->table()));
    292   RUNTIME_ASSERT(table->IsKey(*key));
    293   Handle<Object> lookup(table->Lookup(key, hash), isolate);
    294   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
    295 }
    296 
    297 
    298 RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
    299   HandleScope scope(isolate);
    300   DCHECK(args.length() == 3);
    301   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
    302   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    303   CONVERT_SMI_ARG_CHECKED(hash, 2)
    304   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
    305   Handle<ObjectHashTable> table(
    306       ObjectHashTable::cast(weak_collection->table()));
    307   RUNTIME_ASSERT(table->IsKey(*key));
    308   Handle<Object> lookup(table->Lookup(key, hash), isolate);
    309   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
    310 }
    311 
    312 
    313 RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
    314   HandleScope scope(isolate);
    315   DCHECK(args.length() == 3);
    316   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
    317   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    318   CONVERT_SMI_ARG_CHECKED(hash, 2)
    319   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
    320   Handle<ObjectHashTable> table(
    321       ObjectHashTable::cast(weak_collection->table()));
    322   RUNTIME_ASSERT(table->IsKey(*key));
    323   bool was_present = JSWeakCollection::Delete(weak_collection, key, hash);
    324   return isolate->heap()->ToBoolean(was_present);
    325 }
    326 
    327 
    328 RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
    329   HandleScope scope(isolate);
    330   DCHECK(args.length() == 4);
    331   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
    332   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
    333   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
    334   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
    335   CONVERT_SMI_ARG_CHECKED(hash, 3)
    336   Handle<ObjectHashTable> table(
    337       ObjectHashTable::cast(weak_collection->table()));
    338   RUNTIME_ASSERT(table->IsKey(*key));
    339   JSWeakCollection::Set(weak_collection, key, value, hash);
    340   return *weak_collection;
    341 }
    342 
    343 
    344 RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
    345   HandleScope scope(isolate);
    346   DCHECK(args.length() == 2);
    347   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
    348   CONVERT_NUMBER_CHECKED(int, max_values, Int32, args[1]);
    349   RUNTIME_ASSERT(max_values >= 0);
    350 
    351   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
    352   if (max_values == 0 || max_values > table->NumberOfElements()) {
    353     max_values = table->NumberOfElements();
    354   }
    355   Handle<FixedArray> values = isolate->factory()->NewFixedArray(max_values);
    356   // Recompute max_values because GC could have removed elements from the table.
    357   if (max_values > table->NumberOfElements()) {
    358     max_values = table->NumberOfElements();
    359   }
    360   {
    361     DisallowHeapAllocation no_gc;
    362     int count = 0;
    363     for (int i = 0; count < max_values && i < table->Capacity(); i++) {
    364       Handle<Object> key(table->KeyAt(i), isolate);
    365       if (table->IsKey(*key)) values->set(count++, *key);
    366     }
    367     DCHECK_EQ(max_values, count);
    368   }
    369   return *isolate->factory()->NewJSArrayWithElements(values);
    370 }
    371 
    372 
    373 RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) {
    374   HandleScope scope(isolate);
    375   DCHECK(args.length() == 0);
    376   Handle<JSWeakMap> weakmap = isolate->factory()->NewJSWeakMap();
    377   JSWeakCollection::Initialize(weakmap, isolate);
    378   return *weakmap;
    379 }
    380 }  // namespace internal
    381 }  // namespace v8
    382