LCOV - code coverage report
Current view: top level - test/cctest - test-object.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 109 109 100.0 %
Date: 2017-10-20 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright 2016 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/api.h"
       6             : #include "src/factory.h"
       7             : #include "src/handles-inl.h"
       8             : #include "src/handles.h"
       9             : #include "src/isolate.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/objects.h"
      12             : #include "src/v8.h"
      13             : #include "test/cctest/cctest.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18          78 : static void CheckObject(Isolate* isolate, Handle<Object> obj,
      19             :                         const char* string) {
      20         156 :   Object* print_string = *Object::NoSideEffectsToString(isolate, obj);
      21          78 :   CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
      22          78 : }
      23             : 
      24           6 : static void CheckSmi(Isolate* isolate, int value, const char* string) {
      25             :   Handle<Object> handle(Smi::FromInt(value), isolate);
      26           6 :   CheckObject(isolate, handle, string);
      27           6 : }
      28             : 
      29           6 : static void CheckString(Isolate* isolate, const char* value,
      30             :                         const char* string) {
      31           6 :   Handle<String> handle(isolate->factory()->NewStringFromAsciiChecked(value));
      32           6 :   CheckObject(isolate, handle, string);
      33           6 : }
      34             : 
      35           6 : static void CheckNumber(Isolate* isolate, double value, const char* string) {
      36           6 :   Handle<Object> number = isolate->factory()->NewNumber(value);
      37           6 :   CHECK(number->IsNumber());
      38           6 :   CheckObject(isolate, number, string);
      39           6 : }
      40             : 
      41             : static void CheckBoolean(Isolate* isolate, bool value, const char* string) {
      42             :   CheckObject(isolate, value ? isolate->factory()->true_value()
      43             :                              : isolate->factory()->false_value(),
      44          18 :               string);
      45             : }
      46             : 
      47       23724 : TEST(NoSideEffectsToString) {
      48           6 :   CcTest::InitializeVM();
      49             :   Isolate* isolate = CcTest::i_isolate();
      50             :   Factory* factory = isolate->factory();
      51             : 
      52             :   HandleScope scope(isolate);
      53             : 
      54           6 :   CheckString(isolate, "fisk hest", "fisk hest");
      55           6 :   CheckNumber(isolate, 42.3, "42.3");
      56           6 :   CheckSmi(isolate, 42, "42");
      57             :   CheckBoolean(isolate, true, "true");
      58             :   CheckBoolean(isolate, false, "false");
      59             :   CheckBoolean(isolate, false, "false");
      60           6 :   CheckObject(isolate, factory->undefined_value(), "undefined");
      61           6 :   CheckObject(isolate, factory->null_value(), "null");
      62             : 
      63           6 :   CheckObject(isolate, factory->error_to_string(), "[object Error]");
      64             :   CheckObject(isolate, factory->unscopables_symbol(),
      65           6 :               "Symbol(Symbol.unscopables)");
      66             :   CheckObject(isolate, factory->NewError(isolate->error_function(),
      67             :                                          factory->empty_string()),
      68           6 :               "Error");
      69             :   CheckObject(isolate, factory->NewError(
      70             :                            isolate->error_function(),
      71             :                            factory->NewStringFromAsciiChecked("fisk hest")),
      72           6 :               "Error: fisk hest");
      73             :   CheckObject(isolate, factory->NewJSObject(isolate->object_function()),
      74          12 :               "#<Object>");
      75           6 : }
      76             : 
      77       23724 : TEST(EnumCache) {
      78           6 :   LocalContext env;
      79           6 :   v8::Isolate* isolate = env->GetIsolate();
      80             :   i::Factory* factory = CcTest::i_isolate()->factory();
      81          12 :   v8::HandleScope scope(isolate);
      82             : 
      83             :   // Create a nice transition tree:
      84             :   // (a) --> (b) --> (c)   shared DescriptorArray 1
      85             :   //          |
      86             :   //          +---> (cc)   shared DescriptorArray 2
      87             :   CompileRun(
      88             :       "function O(a) { this.a = 1 };"
      89             : 
      90             :       "a = new O();"
      91             : 
      92             :       "b = new O();"
      93             :       "b.b = 2;"
      94             : 
      95             :       "c = new O();"
      96             :       "c.b = 2;"
      97             :       "c.c = 3;"
      98             : 
      99             :       "cc = new O();"
     100             :       "cc.b = 2;"
     101             :       "cc.cc = 4;");
     102             : 
     103             :   Handle<JSObject> a = Handle<JSObject>::cast(v8::Utils::OpenHandle(
     104          30 :       *env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked()));
     105             :   Handle<JSObject> b = Handle<JSObject>::cast(v8::Utils::OpenHandle(
     106          30 :       *env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked()));
     107             :   Handle<JSObject> c = Handle<JSObject>::cast(v8::Utils::OpenHandle(
     108          30 :       *env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked()));
     109             :   Handle<JSObject> cc = Handle<JSObject>::cast(v8::Utils::OpenHandle(
     110          30 :       *env->Global()->Get(env.local(), v8_str("cc")).ToLocalChecked()));
     111             : 
     112             :   // Check the transition tree.
     113           6 :   CHECK_EQ(a->map()->instance_descriptors(), b->map()->instance_descriptors());
     114           6 :   CHECK_EQ(b->map()->instance_descriptors(), c->map()->instance_descriptors());
     115           6 :   CHECK_NE(c->map()->instance_descriptors(), cc->map()->instance_descriptors());
     116           6 :   CHECK_NE(b->map()->instance_descriptors(), cc->map()->instance_descriptors());
     117             : 
     118             :   // Check that the EnumLength is unset.
     119           6 :   CHECK_EQ(a->map()->EnumLength(), kInvalidEnumCacheSentinel);
     120           6 :   CHECK_EQ(b->map()->EnumLength(), kInvalidEnumCacheSentinel);
     121           6 :   CHECK_EQ(c->map()->EnumLength(), kInvalidEnumCacheSentinel);
     122           6 :   CHECK_EQ(cc->map()->EnumLength(), kInvalidEnumCacheSentinel);
     123             : 
     124             :   // Check that the EnumCache is empty.
     125           6 :   CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(),
     126             :            *factory->empty_enum_cache());
     127           6 :   CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(),
     128             :            *factory->empty_enum_cache());
     129           6 :   CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(),
     130             :            *factory->empty_enum_cache());
     131           6 :   CHECK_EQ(cc->map()->instance_descriptors()->GetEnumCache(),
     132             :            *factory->empty_enum_cache());
     133             : 
     134             :   // The EnumCache is shared on the DescriptorArray, creating it on {cc} has no
     135             :   // effect on the other maps.
     136             :   CompileRun("var s = 0; for (let key in cc) { s += cc[key] };");
     137             :   {
     138           6 :     CHECK_EQ(a->map()->EnumLength(), kInvalidEnumCacheSentinel);
     139           6 :     CHECK_EQ(b->map()->EnumLength(), kInvalidEnumCacheSentinel);
     140           6 :     CHECK_EQ(c->map()->EnumLength(), kInvalidEnumCacheSentinel);
     141           6 :     CHECK_EQ(cc->map()->EnumLength(), 3);
     142             : 
     143           6 :     CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(),
     144             :              *factory->empty_enum_cache());
     145           6 :     CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(),
     146             :              *factory->empty_enum_cache());
     147           6 :     CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(),
     148             :              *factory->empty_enum_cache());
     149             : 
     150             :     EnumCache* enum_cache = cc->map()->instance_descriptors()->GetEnumCache();
     151           6 :     CHECK_NE(enum_cache, *factory->empty_enum_cache());
     152           6 :     CHECK_EQ(enum_cache->keys()->length(), 3);
     153           6 :     CHECK_EQ(enum_cache->indices()->length(), 3);
     154             :   }
     155             : 
     156             :   // Initializing the EnumCache for the the topmost map {a} will not create the
     157             :   // cache for the other maps.
     158             :   CompileRun("var s = 0; for (let key in a) { s += a[key] };");
     159             :   {
     160           6 :     CHECK_EQ(a->map()->EnumLength(), 1);
     161           6 :     CHECK_EQ(b->map()->EnumLength(), kInvalidEnumCacheSentinel);
     162           6 :     CHECK_EQ(c->map()->EnumLength(), kInvalidEnumCacheSentinel);
     163           6 :     CHECK_EQ(cc->map()->EnumLength(), 3);
     164             : 
     165             :     // The enum cache is shared on the descriptor array of maps {a}, {b} and
     166             :     // {c} only.
     167             :     EnumCache* enum_cache = a->map()->instance_descriptors()->GetEnumCache();
     168           6 :     CHECK_NE(enum_cache, *factory->empty_enum_cache());
     169           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
     170             :              *factory->empty_enum_cache());
     171           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     172           6 :     CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     173           6 :     CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     174           6 :     CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     175             : 
     176           6 :     CHECK_EQ(enum_cache->keys()->length(), 1);
     177           6 :     CHECK_EQ(enum_cache->indices()->length(), 1);
     178             :   }
     179             : 
     180             :   // Creating the EnumCache for {c} will create a new EnumCache on the shared
     181             :   // DescriptorArray.
     182             :   Handle<EnumCache> previous_enum_cache(
     183             :       a->map()->instance_descriptors()->GetEnumCache());
     184             :   Handle<FixedArray> previous_keys(previous_enum_cache->keys());
     185             :   Handle<FixedArray> previous_indices(previous_enum_cache->indices());
     186             :   CompileRun("var s = 0; for (let key in c) { s += c[key] };");
     187             :   {
     188           6 :     CHECK_EQ(a->map()->EnumLength(), 1);
     189           6 :     CHECK_EQ(b->map()->EnumLength(), kInvalidEnumCacheSentinel);
     190           6 :     CHECK_EQ(c->map()->EnumLength(), 3);
     191           6 :     CHECK_EQ(cc->map()->EnumLength(), 3);
     192             : 
     193             :     EnumCache* enum_cache = c->map()->instance_descriptors()->GetEnumCache();
     194           6 :     CHECK_NE(enum_cache, *factory->empty_enum_cache());
     195             :     // The keys and indices caches are updated.
     196           6 :     CHECK_EQ(enum_cache, *previous_enum_cache);
     197           6 :     CHECK_NE(enum_cache->keys(), *previous_keys);
     198           6 :     CHECK_NE(enum_cache->indices(), *previous_indices);
     199           6 :     CHECK_EQ(previous_keys->length(), 1);
     200           6 :     CHECK_EQ(previous_indices->length(), 1);
     201           6 :     CHECK_EQ(enum_cache->keys()->length(), 3);
     202           6 :     CHECK_EQ(enum_cache->indices()->length(), 3);
     203             : 
     204             :     // The enum cache is shared on the descriptor array of maps {a}, {b} and
     205             :     // {c} only.
     206           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
     207             :              *factory->empty_enum_cache());
     208           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     209           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
     210             :              *previous_enum_cache);
     211           6 :     CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     212           6 :     CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     213           6 :     CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     214             :   }
     215             : 
     216             :   // {b} can reuse the existing EnumCache, hence we only need to set the correct
     217             :   // EnumLength on the map without modifying the cache itself.
     218             :   previous_enum_cache =
     219             :       handle(a->map()->instance_descriptors()->GetEnumCache());
     220             :   previous_keys = handle(previous_enum_cache->keys());
     221             :   previous_indices = handle(previous_enum_cache->indices());
     222             :   CompileRun("var s = 0; for (let key in b) { s += b[key] };");
     223             :   {
     224           6 :     CHECK_EQ(a->map()->EnumLength(), 1);
     225           6 :     CHECK_EQ(b->map()->EnumLength(), 2);
     226           6 :     CHECK_EQ(c->map()->EnumLength(), 3);
     227           6 :     CHECK_EQ(cc->map()->EnumLength(), 3);
     228             : 
     229             :     EnumCache* enum_cache = c->map()->instance_descriptors()->GetEnumCache();
     230           6 :     CHECK_NE(enum_cache, *factory->empty_enum_cache());
     231             :     // The keys and indices caches are not updated.
     232           6 :     CHECK_EQ(enum_cache, *previous_enum_cache);
     233           6 :     CHECK_EQ(enum_cache->keys(), *previous_keys);
     234           6 :     CHECK_EQ(enum_cache->indices(), *previous_indices);
     235           6 :     CHECK_EQ(enum_cache->keys()->length(), 3);
     236           6 :     CHECK_EQ(enum_cache->indices()->length(), 3);
     237             : 
     238             :     // The enum cache is shared on the descriptor array of maps {a}, {b} and
     239             :     // {c} only.
     240           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
     241             :              *factory->empty_enum_cache());
     242           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     243           6 :     CHECK_NE(cc->map()->instance_descriptors()->GetEnumCache(),
     244             :              *previous_enum_cache);
     245           6 :     CHECK_EQ(a->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     246           6 :     CHECK_EQ(b->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     247           6 :     CHECK_EQ(c->map()->instance_descriptors()->GetEnumCache(), enum_cache);
     248           6 :   }
     249           6 : }
     250             : 
     251             : }  // namespace internal
     252       71154 : }  // namespace v8

Generated by: LCOV version 1.10