LCOV - code coverage report
Current view: top level - test/cctest - test-inobject-slack-tracking.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 510 515 99.0 %
Date: 2017-10-20 Functions: 58 58 100.0 %

          Line data    Source code
       1             : // Copyright 2015 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 <stdlib.h>
       6             : #include <sstream>
       7             : #include <utility>
       8             : 
       9             : #include "src/api.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/objects.h"
      12             : #include "src/v8.h"
      13             : 
      14             : #include "test/cctest/cctest.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : namespace test_inobject_slack_tracking {
      19             : 
      20             : static const int kMaxInobjectProperties = JSObject::kMaxInObjectProperties;
      21             : 
      22             : template <typename T>
      23             : static Handle<T> OpenHandle(v8::Local<v8::Value> value) {
      24             :   Handle<Object> obj = v8::Utils::OpenHandle(*value);
      25             :   return Handle<T>::cast(obj);
      26             : }
      27             : 
      28             : 
      29        6615 : static inline v8::Local<v8::Value> Run(v8::Local<v8::Script> script) {
      30             :   v8::Local<v8::Value> result;
      31       13230 :   if (script->Run(v8::Isolate::GetCurrent()->GetCurrentContext())
      32        6615 :           .ToLocal(&result)) {
      33        6615 :     return result;
      34             :   }
      35           0 :   return v8::Local<v8::Value>();
      36             : }
      37             : 
      38             : 
      39             : 
      40             : template <typename T = Object>
      41         935 : Handle<T> GetLexical(const char* name) {
      42             :   Isolate* isolate = CcTest::i_isolate();
      43             :   Factory* factory = isolate->factory();
      44             : 
      45         935 :   Handle<String> str_name = factory->InternalizeUtf8String(name);
      46             :   Handle<ScriptContextTable> script_contexts(
      47        1870 :       isolate->native_context()->script_context_table());
      48             : 
      49             :   ScriptContextTable::LookupResult lookup_result;
      50         935 :   if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
      51             :     Handle<Object> result =
      52             :         FixedArray::get(*ScriptContextTable::GetContext(
      53         935 :                             script_contexts, lookup_result.context_index),
      54        2805 :                         lookup_result.slot_index, isolate);
      55             :     return Handle<T>::cast(result);
      56             :   }
      57           0 :   return Handle<T>();
      58             : }
      59             : 
      60             : 
      61             : template <typename T = Object>
      62             : Handle<T> GetLexical(const std::string& name) {
      63         525 :   return GetLexical<T>(name.c_str());
      64             : }
      65             : 
      66             : template <typename T>
      67             : static inline Handle<T> RunI(v8::Local<v8::Script> script) {
      68        6605 :   return OpenHandle<T>(Run(script));
      69             : }
      70             : 
      71             : template <typename T>
      72          60 : static inline Handle<T> CompileRunI(const char* script) {
      73          60 :   return OpenHandle<T>(CompileRun(script));
      74             : }
      75             : 
      76             : 
      77      316570 : static Object* GetFieldValue(JSObject* obj, int property_index) {
      78      316570 :   FieldIndex index = FieldIndex::ForPropertyIndex(obj->map(), property_index);
      79      316570 :   return obj->RawFastPropertyAt(index);
      80             : }
      81             : 
      82             : 
      83         440 : static double GetDoubleFieldValue(JSObject* obj, FieldIndex field_index) {
      84         440 :   if (obj->IsUnboxedDoubleField(field_index)) {
      85         440 :     return obj->RawFastDoublePropertyAt(field_index);
      86             :   } else {
      87           0 :     Object* value = obj->RawFastPropertyAt(field_index);
      88           0 :     CHECK(value->IsMutableHeapNumber());
      89           0 :     return HeapNumber::cast(value)->value();
      90             :   }
      91             : }
      92             : 
      93             : 
      94         440 : static double GetDoubleFieldValue(JSObject* obj, int property_index) {
      95         440 :   FieldIndex index = FieldIndex::ForPropertyIndex(obj->map(), property_index);
      96         440 :   return GetDoubleFieldValue(obj, index);
      97             : }
      98             : 
      99             : 
     100        6745 : bool IsObjectShrinkable(JSObject* obj) {
     101             :   Handle<Map> filler_map =
     102             :       CcTest::i_isolate()->factory()->one_pointer_filler_map();
     103             : 
     104             :   int inobject_properties = obj->map()->GetInObjectProperties();
     105             :   int unused = obj->map()->unused_property_fields();
     106        6745 :   if (unused == 0) return false;
     107             : 
     108      320455 :   for (int i = inobject_properties - unused; i < inobject_properties; i++) {
     109      315690 :     if (*filler_map != GetFieldValue(obj, i)) {
     110             :       return false;
     111             :     }
     112             :   }
     113             :   return true;
     114             : }
     115             : 
     116             : 
     117       23728 : TEST(JSObjectBasic) {
     118             :   // Avoid eventual completion of in-object slack tracking.
     119          10 :   FLAG_always_opt = false;
     120          10 :   CcTest::InitializeVM();
     121          10 :   v8::HandleScope scope(CcTest::isolate());
     122             :   const char* source =
     123             :       "function A() {"
     124             :       "  this.a = 42;"
     125             :       "  this.d = 4.2;"
     126             :       "  this.o = this;"
     127             :       "}";
     128             :   CompileRun(source);
     129             : 
     130          10 :   Handle<JSFunction> func = GetGlobal<JSFunction>("A");
     131             : 
     132             :   // Zero instances were created so far.
     133          10 :   CHECK(!func->has_initial_map());
     134             : 
     135             :   v8::Local<v8::Script> new_A_script = v8_compile("new A();");
     136             : 
     137             :   Handle<JSObject> obj = RunI<JSObject>(new_A_script);
     138             : 
     139          10 :   CHECK(func->has_initial_map());
     140             :   Handle<Map> initial_map(func->initial_map());
     141             : 
     142             :   // One instance created.
     143          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     144             :            initial_map->construction_counter());
     145          10 :   CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     146             : 
     147             :   // There must be at least some slack.
     148          10 :   CHECK_LT(5, obj->map()->GetInObjectProperties());
     149          10 :   CHECK_EQ(Smi::FromInt(42), GetFieldValue(*obj, 0));
     150          10 :   CHECK_EQ(4.2, GetDoubleFieldValue(*obj, 1));
     151          20 :   CHECK_EQ(*obj, GetFieldValue(*obj, 2));
     152          10 :   CHECK(IsObjectShrinkable(*obj));
     153             : 
     154             :   // Create several objects to complete the tracking.
     155          60 :   for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     156          60 :     CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     157             :     Handle<JSObject> tmp = RunI<JSObject>(new_A_script);
     158         120 :     CHECK_EQ(initial_map->IsInobjectSlackTrackingInProgress(),
     159             :              IsObjectShrinkable(*tmp));
     160             :   }
     161          10 :   CHECK(!initial_map->IsInobjectSlackTrackingInProgress());
     162          10 :   CHECK(!IsObjectShrinkable(*obj));
     163             : 
     164             :   // No slack left.
     165          10 :   CHECK_EQ(3, obj->map()->GetInObjectProperties());
     166          10 : }
     167             : 
     168             : 
     169       23723 : TEST(JSObjectBasicNoInlineNew) {
     170           5 :   FLAG_inline_new = false;
     171           5 :   TestJSObjectBasic();
     172           5 : }
     173             : 
     174             : 
     175       23728 : TEST(JSObjectComplex) {
     176             :   // Avoid eventual completion of in-object slack tracking.
     177          10 :   FLAG_always_opt = false;
     178          10 :   CcTest::InitializeVM();
     179          10 :   v8::HandleScope scope(CcTest::isolate());
     180             :   const char* source =
     181             :       "function A(n) {"
     182             :       "  if (n > 0) this.a = 42;"
     183             :       "  if (n > 1) this.d = 4.2;"
     184             :       "  if (n > 2) this.o1 = this;"
     185             :       "  if (n > 3) this.o2 = this;"
     186             :       "  if (n > 4) this.o3 = this;"
     187             :       "  if (n > 5) this.o4 = this;"
     188             :       "}";
     189             :   CompileRun(source);
     190             : 
     191          10 :   Handle<JSFunction> func = GetGlobal<JSFunction>("A");
     192             : 
     193             :   // Zero instances were created so far.
     194          10 :   CHECK(!func->has_initial_map());
     195             : 
     196          10 :   Handle<JSObject> obj1 = CompileRunI<JSObject>("new A(1);");
     197          10 :   Handle<JSObject> obj3 = CompileRunI<JSObject>("new A(3);");
     198          10 :   Handle<JSObject> obj5 = CompileRunI<JSObject>("new A(5);");
     199             : 
     200          10 :   CHECK(func->has_initial_map());
     201             :   Handle<Map> initial_map(func->initial_map());
     202             : 
     203             :   // Three instances created.
     204          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 3,
     205             :            initial_map->construction_counter());
     206          10 :   CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     207             : 
     208             :   // There must be at least some slack.
     209          10 :   CHECK_LT(5, obj3->map()->GetInObjectProperties());
     210          10 :   CHECK_EQ(Smi::FromInt(42), GetFieldValue(*obj3, 0));
     211          10 :   CHECK_EQ(4.2, GetDoubleFieldValue(*obj3, 1));
     212          20 :   CHECK_EQ(*obj3, GetFieldValue(*obj3, 2));
     213          10 :   CHECK(IsObjectShrinkable(*obj1));
     214          10 :   CHECK(IsObjectShrinkable(*obj3));
     215          10 :   CHECK(IsObjectShrinkable(*obj5));
     216             : 
     217             :   // Create several objects to complete the tracking.
     218          40 :   for (int i = 3; i < Map::kGenerousAllocationCount; i++) {
     219          40 :     CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     220             :     CompileRun("new A(3);");
     221             :   }
     222          10 :   CHECK(!initial_map->IsInobjectSlackTrackingInProgress());
     223             : 
     224             :   // obj1 and obj2 stays shrinkable because we don't clear unused fields.
     225          10 :   CHECK(IsObjectShrinkable(*obj1));
     226          10 :   CHECK(IsObjectShrinkable(*obj3));
     227          10 :   CHECK(!IsObjectShrinkable(*obj5));
     228             : 
     229          10 :   CHECK_EQ(5, obj1->map()->GetInObjectProperties());
     230          10 :   CHECK_EQ(4, obj1->map()->unused_property_fields());
     231             : 
     232          10 :   CHECK_EQ(5, obj3->map()->GetInObjectProperties());
     233          10 :   CHECK_EQ(2, obj3->map()->unused_property_fields());
     234             : 
     235          10 :   CHECK_EQ(5, obj5->map()->GetInObjectProperties());
     236          10 :   CHECK_EQ(0, obj5->map()->unused_property_fields());
     237             : 
     238             :   // Since slack tracking is complete, the new objects should not be shrinkable.
     239          10 :   obj1 = CompileRunI<JSObject>("new A(1);");
     240          10 :   obj3 = CompileRunI<JSObject>("new A(3);");
     241          10 :   obj5 = CompileRunI<JSObject>("new A(5);");
     242             : 
     243          10 :   CHECK(!IsObjectShrinkable(*obj1));
     244          10 :   CHECK(!IsObjectShrinkable(*obj3));
     245          10 :   CHECK(!IsObjectShrinkable(*obj5));
     246          10 : }
     247             : 
     248             : 
     249       23723 : TEST(JSObjectComplexNoInlineNew) {
     250           5 :   FLAG_inline_new = false;
     251           5 :   TestJSObjectComplex();
     252           5 : }
     253             : 
     254             : 
     255       23728 : TEST(JSGeneratorObjectBasic) {
     256             :   // Avoid eventual completion of in-object slack tracking.
     257          10 :   FLAG_always_opt = false;
     258          10 :   CcTest::InitializeVM();
     259          10 :   v8::HandleScope scope(CcTest::isolate());
     260             :   const char* source =
     261             :       "function* A() {"
     262             :       "  var i = 0;"
     263             :       "  while(true) {"
     264             :       "    yield i++;"
     265             :       "  }"
     266             :       "};"
     267             :       "function CreateGenerator() {"
     268             :       "  var o = A();"
     269             :       "  o.a = 42;"
     270             :       "  o.d = 4.2;"
     271             :       "  o.o = o;"
     272             :       "  return o;"
     273             :       "}";
     274             :   CompileRun(source);
     275             : 
     276          10 :   Handle<JSFunction> func = GetGlobal<JSFunction>("A");
     277             : 
     278             :   // Zero instances were created so far.
     279          10 :   CHECK(!func->has_initial_map());
     280             : 
     281             :   v8::Local<v8::Script> new_A_script = v8_compile("CreateGenerator();");
     282             : 
     283             :   Handle<JSObject> obj = RunI<JSObject>(new_A_script);
     284             : 
     285          10 :   CHECK(func->has_initial_map());
     286             :   Handle<Map> initial_map(func->initial_map());
     287             : 
     288             :   // One instance created.
     289          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     290             :            initial_map->construction_counter());
     291          10 :   CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     292             : 
     293             :   // There must be at least some slack.
     294          10 :   CHECK_LT(5, obj->map()->GetInObjectProperties());
     295          10 :   CHECK_EQ(Smi::FromInt(42), GetFieldValue(*obj, 0));
     296          10 :   CHECK_EQ(4.2, GetDoubleFieldValue(*obj, 1));
     297          20 :   CHECK_EQ(*obj, GetFieldValue(*obj, 2));
     298          10 :   CHECK(IsObjectShrinkable(*obj));
     299             : 
     300             :   // Create several objects to complete the tracking.
     301          60 :   for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     302          60 :     CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     303             :     Handle<JSObject> tmp = RunI<JSObject>(new_A_script);
     304         120 :     CHECK_EQ(initial_map->IsInobjectSlackTrackingInProgress(),
     305             :              IsObjectShrinkable(*tmp));
     306             :   }
     307          10 :   CHECK(!initial_map->IsInobjectSlackTrackingInProgress());
     308          10 :   CHECK(!IsObjectShrinkable(*obj));
     309             : 
     310             :   // No slack left.
     311          10 :   CHECK_EQ(3, obj->map()->GetInObjectProperties());
     312          10 : }
     313             : 
     314             : 
     315       23723 : TEST(JSGeneratorObjectBasicNoInlineNew) {
     316           5 :   FLAG_inline_new = false;
     317           5 :   TestJSGeneratorObjectBasic();
     318           5 : }
     319             : 
     320             : 
     321       23728 : TEST(SubclassBasicNoBaseClassInstances) {
     322             :   // Avoid eventual completion of in-object slack tracking.
     323          10 :   FLAG_always_opt = false;
     324          10 :   CcTest::InitializeVM();
     325          10 :   v8::HandleScope scope(CcTest::isolate());
     326             : 
     327             :   // Check that base class' and subclass' slack tracking do not interfere with
     328             :   // each other.
     329             :   // In this test we never create base class instances.
     330             : 
     331             :   const char* source =
     332             :       "'use strict';"
     333             :       "class A {"
     334             :       "  constructor(...args) {"
     335             :       "    this.aa = 42;"
     336             :       "    this.ad = 4.2;"
     337             :       "    this.ao = this;"
     338             :       "  }"
     339             :       "};"
     340             :       "class B extends A {"
     341             :       "  constructor(...args) {"
     342             :       "    super(...args);"
     343             :       "    this.ba = 142;"
     344             :       "    this.bd = 14.2;"
     345             :       "    this.bo = this;"
     346             :       "  }"
     347             :       "};";
     348             :   CompileRun(source);
     349             : 
     350          10 :   Handle<JSFunction> a_func = GetLexical<JSFunction>("A");
     351          10 :   Handle<JSFunction> b_func = GetLexical<JSFunction>("B");
     352             : 
     353             :   // Zero instances were created so far.
     354          10 :   CHECK(!a_func->has_initial_map());
     355          10 :   CHECK(!b_func->has_initial_map());
     356             : 
     357             :   v8::Local<v8::Script> new_B_script = v8_compile("new B();");
     358             : 
     359             :   Handle<JSObject> obj = RunI<JSObject>(new_B_script);
     360             : 
     361          10 :   CHECK(a_func->has_initial_map());
     362             :   Handle<Map> a_initial_map(a_func->initial_map());
     363             : 
     364          10 :   CHECK(b_func->has_initial_map());
     365             :   Handle<Map> b_initial_map(b_func->initial_map());
     366             : 
     367             :   // Zero instances of A created.
     368          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart,
     369             :            a_initial_map->construction_counter());
     370          10 :   CHECK(a_initial_map->IsInobjectSlackTrackingInProgress());
     371             : 
     372             :   // One instance of B created.
     373          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     374             :            b_initial_map->construction_counter());
     375          10 :   CHECK(b_initial_map->IsInobjectSlackTrackingInProgress());
     376             : 
     377             :   // There must be at least some slack.
     378          10 :   CHECK_LT(10, obj->map()->GetInObjectProperties());
     379          10 :   CHECK_EQ(Smi::FromInt(42), GetFieldValue(*obj, 0));
     380          10 :   CHECK_EQ(4.2, GetDoubleFieldValue(*obj, 1));
     381          20 :   CHECK_EQ(*obj, GetFieldValue(*obj, 2));
     382          10 :   CHECK_EQ(Smi::FromInt(142), GetFieldValue(*obj, 3));
     383          10 :   CHECK_EQ(14.2, GetDoubleFieldValue(*obj, 4));
     384          20 :   CHECK_EQ(*obj, GetFieldValue(*obj, 5));
     385          10 :   CHECK(IsObjectShrinkable(*obj));
     386             : 
     387             :   // Create several subclass instances to complete the tracking.
     388          60 :   for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     389          60 :     CHECK(b_initial_map->IsInobjectSlackTrackingInProgress());
     390             :     Handle<JSObject> tmp = RunI<JSObject>(new_B_script);
     391         120 :     CHECK_EQ(b_initial_map->IsInobjectSlackTrackingInProgress(),
     392             :              IsObjectShrinkable(*tmp));
     393             :   }
     394          10 :   CHECK(!b_initial_map->IsInobjectSlackTrackingInProgress());
     395          10 :   CHECK(!IsObjectShrinkable(*obj));
     396             : 
     397             :   // Zero instances of A created.
     398          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart,
     399             :            a_initial_map->construction_counter());
     400          10 :   CHECK(a_initial_map->IsInobjectSlackTrackingInProgress());
     401             : 
     402             :   // No slack left.
     403          10 :   CHECK_EQ(6, obj->map()->GetInObjectProperties());
     404          10 : }
     405             : 
     406             : 
     407       23723 : TEST(SubclassBasicNoBaseClassInstancesNoInlineNew) {
     408           5 :   FLAG_inline_new = false;
     409           5 :   TestSubclassBasicNoBaseClassInstances();
     410           5 : }
     411             : 
     412             : 
     413       23728 : TEST(SubclassBasic) {
     414             :   // Avoid eventual completion of in-object slack tracking.
     415          10 :   FLAG_always_opt = false;
     416          10 :   CcTest::InitializeVM();
     417          10 :   v8::HandleScope scope(CcTest::isolate());
     418             : 
     419             :   // Check that base class' and subclass' slack tracking do not interfere with
     420             :   // each other.
     421             :   // In this test we first create enough base class instances to complete
     422             :   // the slack tracking and then proceed creating subclass instances.
     423             : 
     424             :   const char* source =
     425             :       "'use strict';"
     426             :       "class A {"
     427             :       "  constructor(...args) {"
     428             :       "    this.aa = 42;"
     429             :       "    this.ad = 4.2;"
     430             :       "    this.ao = this;"
     431             :       "  }"
     432             :       "};"
     433             :       "class B extends A {"
     434             :       "  constructor(...args) {"
     435             :       "    super(...args);"
     436             :       "    this.ba = 142;"
     437             :       "    this.bd = 14.2;"
     438             :       "    this.bo = this;"
     439             :       "  }"
     440             :       "};";
     441             :   CompileRun(source);
     442             : 
     443          10 :   Handle<JSFunction> a_func = GetLexical<JSFunction>("A");
     444          10 :   Handle<JSFunction> b_func = GetLexical<JSFunction>("B");
     445             : 
     446             :   // Zero instances were created so far.
     447          10 :   CHECK(!a_func->has_initial_map());
     448          10 :   CHECK(!b_func->has_initial_map());
     449             : 
     450             :   v8::Local<v8::Script> new_A_script = v8_compile("new A();");
     451             :   v8::Local<v8::Script> new_B_script = v8_compile("new B();");
     452             : 
     453             :   Handle<JSObject> a_obj = RunI<JSObject>(new_A_script);
     454             :   Handle<JSObject> b_obj = RunI<JSObject>(new_B_script);
     455             : 
     456          10 :   CHECK(a_func->has_initial_map());
     457             :   Handle<Map> a_initial_map(a_func->initial_map());
     458             : 
     459          10 :   CHECK(b_func->has_initial_map());
     460             :   Handle<Map> b_initial_map(b_func->initial_map());
     461             : 
     462             :   // One instance of a base class created.
     463          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     464             :            a_initial_map->construction_counter());
     465          10 :   CHECK(a_initial_map->IsInobjectSlackTrackingInProgress());
     466             : 
     467             :   // One instance of a subclass created.
     468          10 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     469             :            b_initial_map->construction_counter());
     470          10 :   CHECK(b_initial_map->IsInobjectSlackTrackingInProgress());
     471             : 
     472             :   // Create several base class instances to complete the tracking.
     473          60 :   for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     474          60 :     CHECK(a_initial_map->IsInobjectSlackTrackingInProgress());
     475             :     Handle<JSObject> tmp = RunI<JSObject>(new_A_script);
     476         120 :     CHECK_EQ(a_initial_map->IsInobjectSlackTrackingInProgress(),
     477             :              IsObjectShrinkable(*tmp));
     478             :   }
     479          10 :   CHECK(!a_initial_map->IsInobjectSlackTrackingInProgress());
     480          10 :   CHECK(!IsObjectShrinkable(*a_obj));
     481             : 
     482             :   // No slack left.
     483          10 :   CHECK_EQ(3, a_obj->map()->GetInObjectProperties());
     484             : 
     485             :   // There must be at least some slack.
     486          10 :   CHECK_LT(10, b_obj->map()->GetInObjectProperties());
     487          10 :   CHECK_EQ(Smi::FromInt(42), GetFieldValue(*b_obj, 0));
     488          10 :   CHECK_EQ(4.2, GetDoubleFieldValue(*b_obj, 1));
     489          20 :   CHECK_EQ(*b_obj, GetFieldValue(*b_obj, 2));
     490          10 :   CHECK_EQ(Smi::FromInt(142), GetFieldValue(*b_obj, 3));
     491          10 :   CHECK_EQ(14.2, GetDoubleFieldValue(*b_obj, 4));
     492          20 :   CHECK_EQ(*b_obj, GetFieldValue(*b_obj, 5));
     493          10 :   CHECK(IsObjectShrinkable(*b_obj));
     494             : 
     495             :   // Create several subclass instances to complete the tracking.
     496          60 :   for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     497          60 :     CHECK(b_initial_map->IsInobjectSlackTrackingInProgress());
     498             :     Handle<JSObject> tmp = RunI<JSObject>(new_B_script);
     499         120 :     CHECK_EQ(b_initial_map->IsInobjectSlackTrackingInProgress(),
     500             :              IsObjectShrinkable(*tmp));
     501             :   }
     502          10 :   CHECK(!b_initial_map->IsInobjectSlackTrackingInProgress());
     503          10 :   CHECK(!IsObjectShrinkable(*b_obj));
     504             : 
     505             :   // No slack left.
     506          10 :   CHECK_EQ(6, b_obj->map()->GetInObjectProperties());
     507          10 : }
     508             : 
     509             : 
     510       23723 : TEST(SubclassBasicNoInlineNew) {
     511           5 :   FLAG_inline_new = false;
     512           5 :   TestSubclassBasic();
     513           5 : }
     514             : 
     515             : 
     516             : // Creates class hierarchy of length matching the |hierarchy_desc| length and
     517             : // with the number of fields at i'th level equal to |hierarchy_desc[i]|.
     518         575 : static void CreateClassHierarchy(const std::vector<int>& hierarchy_desc) {
     519          25 :   std::ostringstream os;
     520          25 :   os << "'use strict';\n\n";
     521             : 
     522          25 :   int n = static_cast<int>(hierarchy_desc.size());
     523         550 :   for (int cur_class = 0; cur_class < n; cur_class++) {
     524         525 :     os << "class A" << cur_class;
     525         525 :     if (cur_class > 0) {
     526         500 :       os << " extends A" << (cur_class - 1);
     527             :     }
     528             :     os << " {\n"
     529         525 :           "  constructor(...args) {\n";
     530         525 :     if (cur_class > 0) {
     531         500 :       os << "    super(...args);\n";
     532             :     }
     533        1050 :     int fields_count = hierarchy_desc[cur_class];
     534       11825 :     for (int k = 0; k < fields_count; k++) {
     535       11300 :       os << "    this.f" << cur_class << "_" << k << " = " << k << ";\n";
     536             :     }
     537             :     os << "  }\n"
     538         525 :           "};\n\n";
     539             :   }
     540          25 :   CompileRun(os.str().c_str());
     541          25 : }
     542             : 
     543             : 
     544         525 : static std::string GetClassName(int class_index) {
     545         525 :   std::ostringstream os;
     546         525 :   os << "A" << class_index;
     547         525 :   return os.str();
     548             : }
     549             : 
     550             : 
     551         525 : static v8::Local<v8::Script> GetNewObjectScript(const std::string& class_name) {
     552         525 :   std::ostringstream os;
     553        1050 :   os << "new " << class_name << "();";
     554         525 :   return v8_compile(os.str().c_str());
     555             : }
     556             : 
     557             : 
     558             : // Test that in-object slack tracking works as expected for first |n| classes
     559             : // in the hierarchy.
     560             : // This test works only for if the total property count is less than maximum
     561             : // in-object properties count.
     562         540 : static void TestClassHierarchy(const std::vector<int>& hierarchy_desc, int n) {
     563             :   int fields_count = 0;
     564         540 :   for (int cur_class = 0; cur_class < n; cur_class++) {
     565         515 :     std::string class_name = GetClassName(cur_class);
     566        1030 :     int fields_count_at_current_level = hierarchy_desc[cur_class];
     567         515 :     fields_count += fields_count_at_current_level;
     568             : 
     569             :     // This test is not suitable for in-object properties count overflow case.
     570         515 :     CHECK_LT(fields_count, kMaxInobjectProperties);
     571             : 
     572             :     // Create |class_name| objects and check slack tracking.
     573         515 :     v8::Local<v8::Script> new_script = GetNewObjectScript(class_name);
     574             : 
     575             :     Handle<JSFunction> func = GetLexical<JSFunction>(class_name);
     576             : 
     577             :     Handle<JSObject> obj = RunI<JSObject>(new_script);
     578             : 
     579         515 :     CHECK(func->has_initial_map());
     580             :     Handle<Map> initial_map(func->initial_map());
     581             : 
     582             :     // If the object is slow-mode already, bail out.
     583         515 :     if (obj->map()->is_dictionary_map()) continue;
     584             : 
     585             :     // There must be at least some slack.
     586         515 :     CHECK_LT(fields_count, obj->map()->GetInObjectProperties());
     587             : 
     588             :     // One instance was created.
     589         515 :     CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     590             :              initial_map->construction_counter());
     591         515 :     CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     592             : 
     593             :     // Create several instances to complete the tracking.
     594        2575 :     for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     595        3090 :       CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     596             :       Handle<JSObject> tmp = RunI<JSObject>(new_script);
     597        6180 :       CHECK_EQ(initial_map->IsInobjectSlackTrackingInProgress(),
     598             :                IsObjectShrinkable(*tmp));
     599        3090 :       if (!initial_map->IsInobjectSlackTrackingInProgress()) {
     600             :         // Turbofan can force completion of in-object slack tracking.
     601             :         break;
     602             :       }
     603        2575 :       CHECK_EQ(Map::kSlackTrackingCounterStart - i - 1,
     604             :                initial_map->construction_counter());
     605             :     }
     606         515 :     CHECK(!initial_map->IsInobjectSlackTrackingInProgress());
     607         515 :     CHECK(!IsObjectShrinkable(*obj));
     608             : 
     609             :     // No slack left.
     610         515 :     CHECK_EQ(fields_count, obj->map()->GetInObjectProperties());
     611             :   }
     612          25 : }
     613             : 
     614             : 
     615          30 : static void TestSubclassChain(const std::vector<int>& hierarchy_desc) {
     616             :   // Avoid eventual completion of in-object slack tracking.
     617          15 :   FLAG_always_opt = false;
     618          15 :   CcTest::InitializeVM();
     619          15 :   v8::HandleScope scope(CcTest::isolate());
     620             : 
     621          15 :   CreateClassHierarchy(hierarchy_desc);
     622          15 :   TestClassHierarchy(hierarchy_desc, static_cast<int>(hierarchy_desc.size()));
     623          15 : }
     624             : 
     625             : 
     626       23723 : TEST(LongSubclassChain1) {
     627             :   std::vector<int> hierarchy_desc;
     628          40 :   for (int i = 0; i < 7; i++) {
     629          70 :     hierarchy_desc.push_back(i * 10);
     630             :   }
     631           5 :   TestSubclassChain(hierarchy_desc);
     632           5 : }
     633             : 
     634             : 
     635       23723 : TEST(LongSubclassChain2) {
     636             :   std::vector<int> hierarchy_desc;
     637          10 :   hierarchy_desc.push_back(10);
     638         215 :   for (int i = 0; i < 42; i++) {
     639         420 :     hierarchy_desc.push_back(0);
     640             :   }
     641          10 :   hierarchy_desc.push_back(230);
     642           5 :   TestSubclassChain(hierarchy_desc);
     643           5 : }
     644             : 
     645             : 
     646       23723 : TEST(LongSubclassChain3) {
     647             :   std::vector<int> hierarchy_desc;
     648         215 :   for (int i = 0; i < 42; i++) {
     649         420 :     hierarchy_desc.push_back(5);
     650             :   }
     651           5 :   TestSubclassChain(hierarchy_desc);
     652           5 : }
     653             : 
     654             : 
     655       23723 : TEST(InobjectPropetiesCountOverflowInSubclass) {
     656             :   // Avoid eventual completion of in-object slack tracking.
     657           5 :   FLAG_always_opt = false;
     658           5 :   CcTest::InitializeVM();
     659           5 :   v8::HandleScope scope(CcTest::isolate());
     660             : 
     661             :   std::vector<int> hierarchy_desc;
     662             :   const int kNoOverflowCount = 5;
     663          30 :   for (int i = 0; i < kNoOverflowCount; i++) {
     664          50 :     hierarchy_desc.push_back(50);
     665             :   }
     666             :   // In this class we are going to have properties in the backing store.
     667          10 :   hierarchy_desc.push_back(100);
     668             : 
     669           5 :   CreateClassHierarchy(hierarchy_desc);
     670             : 
     671             :   // For the last class in the hierarchy we need different checks.
     672             :   {
     673             :     int cur_class = kNoOverflowCount;
     674           5 :     std::string class_name = GetClassName(cur_class);
     675             : 
     676             :     // Create |class_name| objects and check slack tracking.
     677           5 :     v8::Local<v8::Script> new_script = GetNewObjectScript(class_name);
     678             : 
     679             :     Handle<JSFunction> func = GetLexical<JSFunction>(class_name);
     680             : 
     681             :     Handle<JSObject> obj = RunI<JSObject>(new_script);
     682             : 
     683           5 :     CHECK(func->has_initial_map());
     684             :     Handle<Map> initial_map(func->initial_map());
     685             : 
     686             :     // There must be no slack left.
     687           5 :     CHECK_EQ(JSObject::kMaxInstanceSize, obj->map()->instance_size());
     688           5 :     CHECK_EQ(kMaxInobjectProperties, obj->map()->GetInObjectProperties());
     689             : 
     690             :     // One instance was created.
     691           5 :     CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     692             :              initial_map->construction_counter());
     693           5 :     CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     694             : 
     695             :     // Create several instances to complete the tracking.
     696          30 :     for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     697          30 :       CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     698             :       Handle<JSObject> tmp = RunI<JSObject>(new_script);
     699          30 :       CHECK(!IsObjectShrinkable(*tmp));
     700             :     }
     701           5 :     CHECK(!initial_map->IsInobjectSlackTrackingInProgress());
     702           5 :     CHECK(!IsObjectShrinkable(*obj));
     703             : 
     704             :     // No slack left.
     705           5 :     CHECK_EQ(kMaxInobjectProperties, obj->map()->GetInObjectProperties());
     706             :   }
     707             : 
     708             :   // The other classes in the hierarchy are not affected.
     709          10 :   TestClassHierarchy(hierarchy_desc, kNoOverflowCount);
     710           5 : }
     711             : 
     712          35 : static void CheckExpectedProperties(int expected, std::ostringstream& os) {
     713             :   Handle<HeapObject> obj = Handle<HeapObject>::cast(
     714          35 :       v8::Utils::OpenHandle(*CompileRun(os.str().c_str())));
     715          35 :   CHECK_EQ(expected, obj->map()->GetInObjectProperties());
     716          35 : }
     717             : 
     718       23723 : TEST(ObjectLiteralPropertyBackingStoreSize) {
     719           5 :   v8::HandleScope scope(CcTest::isolate());
     720          10 :   LocalContext env;
     721             : 
     722          10 :   std::ostringstream os;
     723             : 
     724             :   // An index key does not require space in the property backing store.
     725             :   os << "(function() {\n"
     726             :         "  function f() {\n"
     727             :         "    var o = {\n"
     728             :         "      '-1': 42,\n"  // Allocate for non-index key.
     729             :         "      1: 42,\n"     // Do not allocate for index key.
     730             :         "      '2': 42\n"    // Do not allocate for index key.
     731             :         "    };\n"
     732             :         "    return o;\n"
     733             :         "  }\n"
     734             :         "\n"
     735             :         "  return f();\n"
     736           5 :         "} )();";
     737           5 :   CheckExpectedProperties(1, os);
     738             : 
     739             :   // Avoid over-/under-allocation for computed property names.
     740             :   os << "(function() {\n"
     741             :         "  'use strict';\n"
     742             :         "  function f(x) {\n"
     743             :         "    var o = {\n"
     744             :         "      1: 42,\n"    // Do not allocate for index key.
     745             :         "      '2': 42,\n"  // Do not allocate for index key.
     746             :         "      [x]: 42,\n"  // Allocate for property with computed name.
     747             :         "      3: 42,\n"    // Do not allocate for index key.
     748             :         "      '4': 42\n"   // Do not allocate for index key.
     749             :         "    };\n"
     750             :         "    return o;\n"
     751             :         "  }\n"
     752             :         "\n"
     753             :         "  var x = 'hello'\n"
     754             :         "\n"
     755             :         "  return f(x);\n"
     756           5 :         "} )();";
     757           5 :   CheckExpectedProperties(1, os);
     758             : 
     759             :   // Conversion to index key.
     760             :   os << "(function() {\n"
     761             :         "  function f(x) {\n"
     762             :         "    var o = {\n"
     763             :         "      1: 42,\n"       // Do not allocate for index key.
     764             :         "      '2': 42,\n"     // Do not allocate for index key.
     765             :         "      [x]: 42,\n"     // Allocate for property with computed name.
     766             :         "      3: 42,\n"       // Do not allocate for index key.
     767             :         "      get 12() {}\n"  // Do not allocate for index key.
     768             :         "    };\n"
     769             :         "    return o;\n"
     770             :         "  }\n"
     771             :         "\n"
     772             :         "  var x = 'hello'\n"
     773             :         "\n"
     774             :         "  return f(x);\n"
     775           5 :         "} )();";
     776           5 :   CheckExpectedProperties(1, os);
     777             : 
     778             :   os << "(function() {\n"
     779             :         "  function f() {\n"
     780             :         "    var o = {};\n"
     781             :         "    return o;\n"
     782             :         "  }\n"
     783             :         "\n"
     784             :         "  return f();\n"
     785           5 :         "} )();";
     786             :   // Empty objects have slack for 4 properties.
     787           5 :   CheckExpectedProperties(4, os);
     788             : 
     789             :   os << "(function() {\n"
     790             :         "  function f(x) {\n"
     791             :         "    var o = {\n"
     792             :         "      a: 42,\n"    // Allocate for constant property.
     793             :         "      [x]: 42,\n"  // Allocate for property with computed name.
     794             :         "      b: 42\n"     // Allocate for constant property.
     795             :         "    };\n"
     796             :         "    return o;\n"
     797             :         "  }\n"
     798             :         "\n"
     799             :         "  var x = 'hello'\n"
     800             :         "\n"
     801             :         "  return f(x);\n"
     802           5 :         "} )();";
     803           5 :   CheckExpectedProperties(3, os);
     804             : 
     805             :   os << "(function() {\n"
     806             :         "  function f(x) {\n"
     807             :         "    var o = {\n"
     808             :         "      a: 42,\n"          // Allocate for constant property.
     809             :         "      __proto__: 42,\n"  // Do not allocate for __proto__.
     810             :         "      [x]: 42\n"         // Allocate for property with computed name.
     811             :         "    };\n"
     812             :         "    return o;\n"
     813             :         "  }\n"
     814             :         "\n"
     815             :         "  var x = 'hello'\n"
     816             :         "\n"
     817             :         "  return f(x);\n"
     818           5 :         "} )();";
     819             :   // __proto__ is not allocated in the backing store.
     820           5 :   CheckExpectedProperties(2, os);
     821             : 
     822             :   os << "(function() {\n"
     823             :         "  function f(x) {\n"
     824             :         "    var o = {\n"
     825             :         "      a: 42,\n"         // Allocate for constant property.
     826             :         "      [x]: 42,\n"       // Allocate for property with computed name.
     827             :         "      __proto__: 42\n"  // Do not allocate for __proto__.
     828             :         "    };\n"
     829             :         "    return o;\n"
     830             :         "  }\n"
     831             :         "\n"
     832             :         "  var x = 'hello'\n"
     833             :         "\n"
     834             :         "  return f(x);\n"
     835           5 :         "} )();";
     836          10 :   CheckExpectedProperties(2, os);
     837           5 : }
     838             : 
     839       23723 : TEST(SlowModeSubclass) {
     840             :   // Avoid eventual completion of in-object slack tracking.
     841           5 :   FLAG_always_opt = false;
     842           5 :   CcTest::InitializeVM();
     843           5 :   v8::HandleScope scope(CcTest::isolate());
     844             : 
     845             :   std::vector<int> hierarchy_desc;
     846             :   const int kNoOverflowCount = 5;
     847          30 :   for (int i = 0; i < kNoOverflowCount; i++) {
     848          50 :     hierarchy_desc.push_back(50);
     849             :   }
     850             :   // This class should go dictionary mode.
     851          10 :   hierarchy_desc.push_back(1000);
     852             : 
     853           5 :   CreateClassHierarchy(hierarchy_desc);
     854             : 
     855             :   // For the last class in the hierarchy we need different checks.
     856             :   {
     857             :     int cur_class = kNoOverflowCount;
     858           5 :     std::string class_name = GetClassName(cur_class);
     859             : 
     860             :     // Create |class_name| objects and check slack tracking.
     861           5 :     v8::Local<v8::Script> new_script = GetNewObjectScript(class_name);
     862             : 
     863             :     Handle<JSFunction> func = GetLexical<JSFunction>(class_name);
     864             : 
     865             :     Handle<JSObject> obj = RunI<JSObject>(new_script);
     866             : 
     867           5 :     CHECK(func->has_initial_map());
     868             :     Handle<Map> initial_map(func->initial_map());
     869             : 
     870             :     // Object should go dictionary mode.
     871           5 :     CHECK_EQ(JSObject::kHeaderSize, obj->map()->instance_size());
     872           5 :     CHECK(obj->map()->is_dictionary_map());
     873             : 
     874             :     // One instance was created.
     875           5 :     CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     876             :              initial_map->construction_counter());
     877           5 :     CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     878             : 
     879             :     // Create several instances to complete the tracking.
     880          30 :     for (int i = 1; i < Map::kGenerousAllocationCount; i++) {
     881          30 :       CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     882             :       Handle<JSObject> tmp = RunI<JSObject>(new_script);
     883          30 :       CHECK(!IsObjectShrinkable(*tmp));
     884             :     }
     885           5 :     CHECK(!initial_map->IsInobjectSlackTrackingInProgress());
     886           5 :     CHECK(!IsObjectShrinkable(*obj));
     887             : 
     888             :     // Object should stay in dictionary mode.
     889           5 :     CHECK_EQ(JSObject::kHeaderSize, obj->map()->instance_size());
     890           5 :     CHECK(obj->map()->is_dictionary_map());
     891             :   }
     892             : 
     893             :   // The other classes in the hierarchy are not affected.
     894          10 :   TestClassHierarchy(hierarchy_desc, kNoOverflowCount);
     895           5 : }
     896             : 
     897             : 
     898         370 : static void TestSubclassBuiltin(const char* subclass_name,
     899             :                                 InstanceType instance_type,
     900             :                                 const char* builtin_name,
     901             :                                 const char* ctor_arguments = "",
     902             :                                 int builtin_properties_count = 0) {
     903             :   {
     904         370 :     std::ostringstream os;
     905             :     os << "'use strict';\n"
     906         370 :           "class "
     907         370 :        << subclass_name << " extends " << builtin_name
     908             :        << " {\n"
     909             :           "  constructor(...args) {\n"
     910             :           "    super(...args);\n"
     911             :           "    this.a = 42;\n"
     912             :           "    this.d = 4.2;\n"
     913             :           "    this.o = this;\n"
     914             :           "  }\n"
     915         370 :           "};\n";
     916         370 :     CompileRun(os.str().c_str());
     917             :   }
     918             : 
     919         370 :   Handle<JSFunction> func = GetLexical<JSFunction>(subclass_name);
     920             : 
     921             :   // Zero instances were created so far.
     922         370 :   CHECK(!func->has_initial_map());
     923             : 
     924             :   v8::Local<v8::Script> new_script;
     925             :   {
     926         370 :     std::ostringstream os;
     927         370 :     os << "new " << subclass_name << "(" << ctor_arguments << ");";
     928         370 :     new_script = v8_compile(os.str().c_str());
     929             :   }
     930             : 
     931             :   RunI<JSObject>(new_script);
     932             : 
     933         370 :   CHECK(func->has_initial_map());
     934             :   Handle<Map> initial_map(func->initial_map());
     935             : 
     936         370 :   CHECK_EQ(instance_type, initial_map->instance_type());
     937             : 
     938             :   // One instance of a subclass created.
     939         370 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 1,
     940             :            initial_map->construction_counter());
     941         370 :   CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     942             : 
     943             :   // Create two instances in order to ensure that |obj|.o is a data field
     944             :   // in case of Function subclassing.
     945             :   Handle<JSObject> obj = RunI<JSObject>(new_script);
     946             : 
     947             :   // Two instances of a subclass created.
     948         370 :   CHECK_EQ(Map::kSlackTrackingCounterStart - 2,
     949             :            initial_map->construction_counter());
     950         370 :   CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     951             : 
     952             :   // There must be at least some slack.
     953         370 :   CHECK_LT(builtin_properties_count + 5, obj->map()->GetInObjectProperties());
     954         370 :   CHECK_EQ(Smi::FromInt(42), GetFieldValue(*obj, builtin_properties_count + 0));
     955         740 :   CHECK_EQ(4.2, GetDoubleFieldValue(*obj, builtin_properties_count + 1));
     956        1110 :   CHECK_EQ(*obj, GetFieldValue(*obj, builtin_properties_count + 2));
     957         370 :   CHECK(IsObjectShrinkable(*obj));
     958             : 
     959             :   // Create several subclass instances to complete the tracking.
     960        1850 :   for (int i = 2; i < Map::kGenerousAllocationCount; i++) {
     961        1850 :     CHECK(initial_map->IsInobjectSlackTrackingInProgress());
     962             :     Handle<JSObject> tmp = RunI<JSObject>(new_script);
     963        3700 :     CHECK_EQ(initial_map->IsInobjectSlackTrackingInProgress(),
     964             :              IsObjectShrinkable(*tmp));
     965             :   }
     966         370 :   CHECK(!initial_map->IsInobjectSlackTrackingInProgress());
     967         370 :   CHECK(!IsObjectShrinkable(*obj));
     968             : 
     969             :   // No slack left.
     970         370 :   CHECK_EQ(builtin_properties_count + 3, obj->map()->GetInObjectProperties());
     971             : 
     972         370 :   CHECK_EQ(instance_type, obj->map()->instance_type());
     973         370 : }
     974             : 
     975             : 
     976       23728 : TEST(SubclassObjectBuiltin) {
     977             :   // Avoid eventual completion of in-object slack tracking.
     978          10 :   FLAG_always_opt = false;
     979          10 :   CcTest::InitializeVM();
     980          10 :   v8::HandleScope scope(CcTest::isolate());
     981             : 
     982          10 :   TestSubclassBuiltin("A1", JS_OBJECT_TYPE, "Object", "true");
     983          10 :   TestSubclassBuiltin("A2", JS_OBJECT_TYPE, "Object", "42");
     984          10 :   TestSubclassBuiltin("A3", JS_OBJECT_TYPE, "Object", "'some string'");
     985          10 : }
     986             : 
     987             : 
     988       23723 : TEST(SubclassObjectBuiltinNoInlineNew) {
     989           5 :   FLAG_inline_new = false;
     990           5 :   TestSubclassObjectBuiltin();
     991           5 : }
     992             : 
     993             : 
     994       23728 : TEST(SubclassFunctionBuiltin) {
     995             :   // Avoid eventual completion of in-object slack tracking.
     996          10 :   FLAG_always_opt = false;
     997          10 :   CcTest::InitializeVM();
     998          10 :   v8::HandleScope scope(CcTest::isolate());
     999             : 
    1000          10 :   TestSubclassBuiltin("A1", JS_FUNCTION_TYPE, "Function", "'return 153;'");
    1001          10 :   TestSubclassBuiltin("A2", JS_FUNCTION_TYPE, "Function", "'this.a = 44;'");
    1002          10 : }
    1003             : 
    1004             : 
    1005       23723 : TEST(SubclassFunctionBuiltinNoInlineNew) {
    1006           5 :   FLAG_inline_new = false;
    1007           5 :   TestSubclassFunctionBuiltin();
    1008           5 : }
    1009             : 
    1010             : 
    1011       23728 : TEST(SubclassBooleanBuiltin) {
    1012             :   // Avoid eventual completion of in-object slack tracking.
    1013          10 :   FLAG_always_opt = false;
    1014          10 :   CcTest::InitializeVM();
    1015          10 :   v8::HandleScope scope(CcTest::isolate());
    1016             : 
    1017          10 :   TestSubclassBuiltin("A1", JS_VALUE_TYPE, "Boolean", "true");
    1018          10 :   TestSubclassBuiltin("A2", JS_VALUE_TYPE, "Boolean", "false");
    1019          10 : }
    1020             : 
    1021             : 
    1022       23723 : TEST(SubclassBooleanBuiltinNoInlineNew) {
    1023           5 :   FLAG_inline_new = false;
    1024           5 :   TestSubclassBooleanBuiltin();
    1025           5 : }
    1026             : 
    1027             : 
    1028       23728 : TEST(SubclassErrorBuiltin) {
    1029             :   // Avoid eventual completion of in-object slack tracking.
    1030          10 :   FLAG_always_opt = false;
    1031          10 :   CcTest::InitializeVM();
    1032          10 :   v8::HandleScope scope(CcTest::isolate());
    1033             : 
    1034             :   const int first_field = 2;
    1035          10 :   TestSubclassBuiltin("A1", JS_ERROR_TYPE, "Error", "'err'", first_field);
    1036          10 :   TestSubclassBuiltin("A2", JS_ERROR_TYPE, "EvalError", "'err'", first_field);
    1037          10 :   TestSubclassBuiltin("A3", JS_ERROR_TYPE, "RangeError", "'err'", first_field);
    1038             :   TestSubclassBuiltin("A4", JS_ERROR_TYPE, "ReferenceError", "'err'",
    1039          10 :                       first_field);
    1040          10 :   TestSubclassBuiltin("A5", JS_ERROR_TYPE, "SyntaxError", "'err'", first_field);
    1041          10 :   TestSubclassBuiltin("A6", JS_ERROR_TYPE, "TypeError", "'err'", first_field);
    1042          10 :   TestSubclassBuiltin("A7", JS_ERROR_TYPE, "URIError", "'err'", first_field);
    1043          10 : }
    1044             : 
    1045             : 
    1046       23723 : TEST(SubclassErrorBuiltinNoInlineNew) {
    1047           5 :   FLAG_inline_new = false;
    1048           5 :   TestSubclassErrorBuiltin();
    1049           5 : }
    1050             : 
    1051             : 
    1052       23728 : TEST(SubclassNumberBuiltin) {
    1053             :   // Avoid eventual completion of in-object slack tracking.
    1054          10 :   FLAG_always_opt = false;
    1055          10 :   CcTest::InitializeVM();
    1056          10 :   v8::HandleScope scope(CcTest::isolate());
    1057             : 
    1058          10 :   TestSubclassBuiltin("A1", JS_VALUE_TYPE, "Number", "42");
    1059          10 :   TestSubclassBuiltin("A2", JS_VALUE_TYPE, "Number", "4.2");
    1060          10 : }
    1061             : 
    1062             : 
    1063       23723 : TEST(SubclassNumberBuiltinNoInlineNew) {
    1064           5 :   FLAG_inline_new = false;
    1065           5 :   TestSubclassNumberBuiltin();
    1066           5 : }
    1067             : 
    1068             : 
    1069       23728 : TEST(SubclassDateBuiltin) {
    1070             :   // Avoid eventual completion of in-object slack tracking.
    1071          10 :   FLAG_always_opt = false;
    1072          10 :   CcTest::InitializeVM();
    1073          10 :   v8::HandleScope scope(CcTest::isolate());
    1074             : 
    1075          10 :   TestSubclassBuiltin("A1", JS_DATE_TYPE, "Date", "123456789");
    1076          10 : }
    1077             : 
    1078             : 
    1079       23723 : TEST(SubclassDateBuiltinNoInlineNew) {
    1080           5 :   FLAG_inline_new = false;
    1081           5 :   TestSubclassDateBuiltin();
    1082           5 : }
    1083             : 
    1084             : 
    1085       23728 : TEST(SubclassStringBuiltin) {
    1086             :   // Avoid eventual completion of in-object slack tracking.
    1087          10 :   FLAG_always_opt = false;
    1088          10 :   CcTest::InitializeVM();
    1089          10 :   v8::HandleScope scope(CcTest::isolate());
    1090             : 
    1091          10 :   TestSubclassBuiltin("A1", JS_VALUE_TYPE, "String", "'some string'");
    1092          10 :   TestSubclassBuiltin("A2", JS_VALUE_TYPE, "String", "");
    1093          10 : }
    1094             : 
    1095             : 
    1096       23723 : TEST(SubclassStringBuiltinNoInlineNew) {
    1097           5 :   FLAG_inline_new = false;
    1098           5 :   TestSubclassStringBuiltin();
    1099           5 : }
    1100             : 
    1101             : 
    1102       23728 : TEST(SubclassRegExpBuiltin) {
    1103             :   // Avoid eventual completion of in-object slack tracking.
    1104          10 :   FLAG_always_opt = false;
    1105          10 :   CcTest::InitializeVM();
    1106          10 :   v8::HandleScope scope(CcTest::isolate());
    1107             : 
    1108             :   const int first_field = 1;
    1109             :   TestSubclassBuiltin("A1", JS_REGEXP_TYPE, "RegExp", "'o(..)h', 'g'",
    1110          10 :                       first_field);
    1111          10 : }
    1112             : 
    1113             : 
    1114       23723 : TEST(SubclassRegExpBuiltinNoInlineNew) {
    1115           5 :   FLAG_inline_new = false;
    1116           5 :   TestSubclassRegExpBuiltin();
    1117           5 : }
    1118             : 
    1119             : 
    1120       23728 : TEST(SubclassArrayBuiltin) {
    1121             :   // Avoid eventual completion of in-object slack tracking.
    1122          10 :   FLAG_always_opt = false;
    1123          10 :   CcTest::InitializeVM();
    1124          10 :   v8::HandleScope scope(CcTest::isolate());
    1125             : 
    1126          10 :   TestSubclassBuiltin("A1", JS_ARRAY_TYPE, "Array", "42");
    1127          10 : }
    1128             : 
    1129             : 
    1130       23723 : TEST(SubclassArrayBuiltinNoInlineNew) {
    1131           5 :   FLAG_inline_new = false;
    1132           5 :   TestSubclassArrayBuiltin();
    1133           5 : }
    1134             : 
    1135             : 
    1136       23728 : TEST(SubclassTypedArrayBuiltin) {
    1137             :   // Avoid eventual completion of in-object slack tracking.
    1138          10 :   FLAG_always_opt = false;
    1139          10 :   CcTest::InitializeVM();
    1140          10 :   v8::HandleScope scope(CcTest::isolate());
    1141             : 
    1142             : #define TYPED_ARRAY_TEST(Type, type, TYPE, elementType, size) \
    1143             :   TestSubclassBuiltin("A" #Type, JS_TYPED_ARRAY_TYPE, #Type "Array", "42");
    1144             : 
    1145          10 :   TYPED_ARRAYS(TYPED_ARRAY_TEST)
    1146             : 
    1147             : #undef TYPED_ARRAY_TEST
    1148          10 : }
    1149             : 
    1150             : 
    1151       23723 : TEST(SubclassTypedArrayBuiltinNoInlineNew) {
    1152           5 :   FLAG_inline_new = false;
    1153           5 :   TestSubclassTypedArrayBuiltin();
    1154           5 : }
    1155             : 
    1156             : 
    1157       23728 : TEST(SubclassCollectionBuiltin) {
    1158             :   // Avoid eventual completion of in-object slack tracking.
    1159          10 :   FLAG_always_opt = false;
    1160          10 :   CcTest::InitializeVM();
    1161          10 :   v8::HandleScope scope(CcTest::isolate());
    1162             : 
    1163          10 :   TestSubclassBuiltin("A1", JS_SET_TYPE, "Set", "");
    1164          10 :   TestSubclassBuiltin("A2", JS_MAP_TYPE, "Map", "");
    1165          10 :   TestSubclassBuiltin("A3", JS_WEAK_SET_TYPE, "WeakSet", "");
    1166          10 :   TestSubclassBuiltin("A4", JS_WEAK_MAP_TYPE, "WeakMap", "");
    1167          10 : }
    1168             : 
    1169             : 
    1170       23723 : TEST(SubclassCollectionBuiltinNoInlineNew) {
    1171           5 :   FLAG_inline_new = false;
    1172           5 :   TestSubclassCollectionBuiltin();
    1173           5 : }
    1174             : 
    1175             : 
    1176       23728 : TEST(SubclassArrayBufferBuiltin) {
    1177             :   // Avoid eventual completion of in-object slack tracking.
    1178          10 :   FLAG_always_opt = false;
    1179          10 :   CcTest::InitializeVM();
    1180          10 :   v8::HandleScope scope(CcTest::isolate());
    1181             : 
    1182          10 :   TestSubclassBuiltin("A1", JS_ARRAY_BUFFER_TYPE, "ArrayBuffer", "42");
    1183             :   TestSubclassBuiltin("A2", JS_DATA_VIEW_TYPE, "DataView",
    1184          10 :                       "new ArrayBuffer(42)");
    1185          10 : }
    1186             : 
    1187             : 
    1188       23723 : TEST(SubclassArrayBufferBuiltinNoInlineNew) {
    1189           5 :   FLAG_inline_new = false;
    1190           5 :   TestSubclassArrayBufferBuiltin();
    1191           5 : }
    1192             : 
    1193             : 
    1194       23728 : TEST(SubclassPromiseBuiltin) {
    1195             :   // Avoid eventual completion of in-object slack tracking.
    1196          10 :   FLAG_always_opt = false;
    1197          10 :   CcTest::InitializeVM();
    1198          10 :   v8::HandleScope scope(CcTest::isolate());
    1199             : 
    1200             :   TestSubclassBuiltin("A1", JS_PROMISE_TYPE, "Promise",
    1201          10 :                       "function(resolve, reject) { resolve('ok'); }");
    1202          10 : }
    1203             : 
    1204             : 
    1205       23723 : TEST(SubclassPromiseBuiltinNoInlineNew) {
    1206           5 :   FLAG_inline_new = false;
    1207           5 :   TestSubclassPromiseBuiltin();
    1208           5 : }
    1209             : 
    1210             : }  // namespace test_inobject_slack_tracking
    1211             : }  // namespace internal
    1212       71154 : }  // namespace v8

Generated by: LCOV version 1.10