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

Generated by: LCOV version 1.10