[runtime] Store constructor function index on primitive maps.
authorbmeurer <bmeurer@chromium.org>
Tue, 11 Aug 2015 19:36:04 +0000 (12:36 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 11 Aug 2015 19:36:14 +0000 (19:36 +0000)
This way we can greatly simplify the different variants of ToObject in
our codebase and make them more uniform and robust.  Adding a new
primitive doesn't require finding and changing all those places again,
but it is sufficient to setup the constructor function index when
allocating the map.

We use the inobject properties field of Map, which is invalid primitive
maps anyway.

R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/1276533003

Cr-Commit-Position: refs/heads/master@{#30119}

29 files changed:
src/arm/builtins-arm.cc
src/arm64/builtins-arm64.cc
src/bootstrapper.cc
src/factory.cc
src/field-index-inl.h
src/heap/heap.cc
src/heap/objects-visiting-inl.h
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/builtins-ia32.cc
src/ic/handler-compiler.cc
src/ic/ic-inl.h
src/layout-descriptor-inl.h
src/layout-descriptor.cc
src/mips/builtins-mips.cc
src/mips64/builtins-mips64.cc
src/objects-debug.cc
src/objects-inl.h
src/objects-printer.cc
src/objects.cc
src/objects.h
src/ppc/builtins-ppc.cc
src/runtime/runtime-collections.cc
src/runtime/runtime-object.cc
src/x64/builtins-x64.cc
src/x87/builtins-x87.cc
test/cctest/test-heap.cc
test/cctest/test-unboxed-doubles.cc

index 9a68c8d..441f57e 100644 (file)
@@ -442,7 +442,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
 
         // Allocate object with a slack.
         __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
-        __ Ubfx(r0, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
+        __ Ubfx(r0, r0, Map::kInObjectPropertiesOrConstructorFunctionIndexByte *
+                            kBitsPerByte,
                 kBitsPerByte);
         __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset));
         __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte,
index c147a19..59b55a9 100644 (file)
@@ -436,8 +436,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
               Map::kUnusedPropertyFieldsByte * kBitsPerByte, kBitsPerByte);
       __ Ldr(inst_sizes_or_attrs,
              FieldMemOperand(init_map, Map::kInstanceSizesOffset));
-      __ Ubfx(inobject_props, inst_sizes_or_attrs,
-              Map::kInObjectPropertiesByte * kBitsPerByte, kBitsPerByte);
+      __ Ubfx(
+          inobject_props, inst_sizes_or_attrs,
+          Map::kInObjectPropertiesOrConstructorFunctionIndexByte * kBitsPerByte,
+          kBitsPerByte);
       __ Sub(prealloc_fields, inobject_props, unused_props);
 
       // Calculate number of property fields in the object.
index 36d322b..bca9b98 100644 (file)
@@ -533,7 +533,7 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
     int instance_size = JSObject::kHeaderSize + kPointerSize * unused;
     Handle<Map> object_function_map =
         factory->NewMap(JS_OBJECT_TYPE, instance_size);
-    object_function_map->set_inobject_properties(unused);
+    object_function_map->SetInObjectProperties(unused);
     JSFunction::SetInitialMap(object_fun, object_function_map,
                               isolate->factory()->null_value());
     object_function_map->set_unused_property_fields(unused);
@@ -1172,7 +1172,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     DCHECK(regexp_fun->has_initial_map());
     Handle<Map> initial_map(regexp_fun->initial_map());
 
-    DCHECK_EQ(0, initial_map->inobject_properties());
+    DCHECK_EQ(0, initial_map->GetInObjectProperties());
 
     PropertyAttributes final =
         static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
@@ -1217,7 +1217,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     }
 
     static const int num_fields = JSRegExp::kInObjectFieldCount;
-    initial_map->set_inobject_properties(num_fields);
+    initial_map->SetInObjectProperties(num_fields);
     initial_map->set_unused_property_fields(0);
     initial_map->set_instance_size(initial_map->instance_size() +
                                    num_fields * kPointerSize);
@@ -1313,7 +1313,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     DCHECK_EQ(JSGeneratorObject::kResultSize,
               iterator_result_map->instance_size());
     DCHECK_EQ(JSGeneratorObject::kResultPropertyCount,
-              iterator_result_map->inobject_properties());
+              iterator_result_map->GetInObjectProperties());
     Map::EnsureDescriptorSlack(iterator_result_map,
                                JSGeneratorObject::kResultPropertyCount);
 
@@ -1368,15 +1368,15 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     // @@iterator method is added later.
 
     map->set_function_with_prototype(true);
-    map->set_inobject_properties(2);
+    map->SetInObjectProperties(2);
     native_context()->set_sloppy_arguments_map(*map);
 
     DCHECK(!function->has_initial_map());
     JSFunction::SetInitialMap(function, map,
                               isolate->initial_object_prototype());
 
-    DCHECK(map->inobject_properties() > Heap::kArgumentsCalleeIndex);
-    DCHECK(map->inobject_properties() > Heap::kArgumentsLengthIndex);
+    DCHECK(map->GetInObjectProperties() > Heap::kArgumentsCalleeIndex);
+    DCHECK(map->GetInObjectProperties() > Heap::kArgumentsLengthIndex);
     DCHECK(!map->is_dictionary_map());
     DCHECK(IsFastObjectElementsKind(map->elements_kind()));
   }
@@ -1385,12 +1385,12 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     Handle<Map> map = isolate->sloppy_arguments_map();
     map = Map::Copy(map, "FastAliasedArguments");
     map->set_elements_kind(FAST_SLOPPY_ARGUMENTS_ELEMENTS);
-    DCHECK_EQ(2, map->inobject_properties());
+    DCHECK_EQ(2, map->GetInObjectProperties());
     native_context()->set_fast_aliased_arguments_map(*map);
 
     map = Map::Copy(map, "SlowAliasedArguments");
     map->set_elements_kind(SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
-    DCHECK_EQ(2, map->inobject_properties());
+    DCHECK_EQ(2, map->GetInObjectProperties());
     native_context()->set_slow_aliased_arguments_map(*map);
   }
 
@@ -1437,7 +1437,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     DCHECK_EQ(native_context()->object_function()->prototype(),
               *isolate->initial_object_prototype());
     Map::SetPrototype(map, isolate->initial_object_prototype());
-    map->set_inobject_properties(1);
+    map->SetInObjectProperties(1);
 
     // Copy constructor from the sloppy arguments boilerplate.
     map->SetConstructor(
@@ -1445,7 +1445,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
 
     native_context()->set_strict_arguments_map(*map);
 
-    DCHECK(map->inobject_properties() > Heap::kArgumentsLengthIndex);
+    DCHECK(map->GetInObjectProperties() > Heap::kArgumentsLengthIndex);
     DCHECK(!map->is_dictionary_map());
     DCHECK(IsFastObjectElementsKind(map->elements_kind()));
   }
@@ -2496,7 +2496,7 @@ bool Genesis::InstallNatives(ContextType context_type) {
       initial_map->AppendDescriptor(&input_field);
     }
 
-    initial_map->set_inobject_properties(2);
+    initial_map->SetInObjectProperties(2);
     initial_map->set_unused_property_fields(0);
 
     native_context()->set_regexp_result_map(*initial_map);
index e5bdc29..11afad4 100644 (file)
@@ -1601,7 +1601,7 @@ Handle<GlobalObject> Factory::NewGlobalObject(Handle<JSFunction> constructor) {
   // Make sure we don't have a ton of pre-allocated slots in the
   // global objects. They will be unused once we normalize the object.
   DCHECK(map->unused_property_fields() == 0);
-  DCHECK(map->inobject_properties() == 0);
+  DCHECK(map->GetInObjectProperties() == 0);
 
   // Initial size of the backing store to avoid resize of the storage during
   // bootstrapping. The size differs between the JS global object ad the
index c151ab1..042e4fb 100644 (file)
@@ -16,7 +16,7 @@ inline FieldIndex FieldIndex::ForInObjectOffset(int offset, Map* map) {
   int index = offset / kPointerSize;
   DCHECK(map == NULL ||
          index < (map->GetInObjectPropertyOffset(0) / kPointerSize +
-                  map->inobject_properties()));
+                  map->GetInObjectProperties()));
   return FieldIndex(true, index, false, 0, 0, true);
 }
 
@@ -25,7 +25,7 @@ inline FieldIndex FieldIndex::ForPropertyIndex(Map* map,
                                                int property_index,
                                                bool is_double) {
   DCHECK(map->instance_type() >= FIRST_NONSTRING_TYPE);
-  int inobject_properties = map->inobject_properties();
+  int inobject_properties = map->GetInObjectProperties();
   bool is_inobject = property_index < inobject_properties;
   int first_inobject_offset;
   if (is_inobject) {
@@ -58,7 +58,7 @@ inline FieldIndex FieldIndex::ForLoadByFieldIndex(Map* map, int orig_index) {
     field_index += JSObject::kHeaderSize / kPointerSize;
   }
   FieldIndex result(is_inobject, field_index, is_double,
-                    map->inobject_properties(), first_inobject_offset);
+                    map->GetInObjectProperties(), first_inobject_offset);
   DCHECK(result.GetLoadByFieldIndex() == orig_index);
   return result;
 }
index d8b72be..5597553 100644 (file)
@@ -2654,7 +2654,8 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
         ->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
   }
   reinterpret_cast<Map*>(result)->clear_unused();
-  reinterpret_cast<Map*>(result)->set_inobject_properties(0);
+  reinterpret_cast<Map*>(result)
+      ->set_inobject_properties_or_constructor_function_index(0);
   reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
   reinterpret_cast<Map*>(result)->set_bit_field(0);
   reinterpret_cast<Map*>(result)->set_bit_field2(0);
@@ -2681,7 +2682,7 @@ AllocationResult Heap::AllocateMap(InstanceType instance_type,
   map->set_constructor_or_backpointer(null_value(), SKIP_WRITE_BARRIER);
   map->set_instance_size(instance_size);
   map->clear_unused();
-  map->set_inobject_properties(0);
+  map->set_inobject_properties_or_constructor_function_index(0);
   map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
   map->set_dependent_code(DependentCode::cast(empty_fixed_array()),
                           SKIP_WRITE_BARRIER);
@@ -2870,22 +2871,34 @@ bool Heap::CreateInitialMaps() {
 #define ALLOCATE_VARSIZE_MAP(instance_type, field_name) \
   ALLOCATE_MAP(instance_type, kVariableSizeSentinel, field_name)
 
+#define ALLOCATE_PRIMITIVE_MAP(instance_type, size, field_name, \
+                               constructor_function_index)      \
+  {                                                             \
+    ALLOCATE_MAP((instance_type), (size), field_name);          \
+    field_name##_map()->SetConstructorFunctionIndex(            \
+        (constructor_function_index));                          \
+  }
+
     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, fixed_cow_array)
     DCHECK(fixed_array_map() != fixed_cow_array_map());
 
     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info)
-    ALLOCATE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number)
+    ALLOCATE_PRIMITIVE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number,
+                           Context::NUMBER_FUNCTION_INDEX)
     ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize,
                  mutable_heap_number)
-    ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol)
+    ALLOCATE_PRIMITIVE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol,
+                           Context::SYMBOL_FUNCTION_INDEX)
 #define ALLOCATE_SIMD128_MAP(TYPE, Type, type, lane_count, lane_type) \
-  ALLOCATE_MAP(SIMD128_VALUE_TYPE, Type::kSize, type)
+  ALLOCATE_PRIMITIVE_MAP(SIMD128_VALUE_TYPE, Type::kSize, type,       \
+                         Context::TYPE##_FUNCTION_INDEX)
     SIMD128_TYPES(ALLOCATE_SIMD128_MAP)
 #undef ALLOCATE_SIMD128_MAP
     ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
 
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, the_hole);
-    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, boolean);
+    ALLOCATE_PRIMITIVE_MAP(ODDBALL_TYPE, Oddball::kSize, boolean,
+                           Context::BOOLEAN_FUNCTION_INDEX);
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, uninitialized);
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, arguments_marker);
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, no_interceptor_result_sentinel);
@@ -2898,9 +2911,10 @@ bool Heap::CreateInitialMaps() {
         AllocationResult allocation = AllocateMap(entry.type, entry.size);
         if (!allocation.To(&obj)) return false;
       }
+      Map* map = Map::cast(obj);
+      map->SetConstructorFunctionIndex(Context::STRING_FUNCTION_INDEX);
       // Mark cons string maps as unstable, because their objects can change
       // maps during GC.
-      Map* map = Map::cast(obj);
       if (StringShape(entry.type).IsCons()) map->mark_unstable();
       roots_[entry.index] = map;
     }
@@ -2909,7 +2923,9 @@ bool Heap::CreateInitialMaps() {
       AllocationResult allocation = AllocateMap(EXTERNAL_ONE_BYTE_STRING_TYPE,
                                                 ExternalOneByteString::kSize);
       if (!allocation.To(&obj)) return false;
-      set_native_source_string_map(Map::cast(obj));
+      Map* map = Map::cast(obj);
+      map->SetConstructorFunctionIndex(Context::STRING_FUNCTION_INDEX);
+      set_native_source_string_map(map);
     }
 
     ALLOCATE_VARSIZE_MAP(FIXED_DOUBLE_ARRAY_TYPE, fixed_double_array)
@@ -2963,6 +2979,7 @@ bool Heap::CreateInitialMaps() {
     ALLOCATE_MAP(JS_MESSAGE_OBJECT_TYPE, JSMessageObject::kSize, message_object)
     ALLOCATE_MAP(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize, external)
     external_map()->set_is_extensible(false);
+#undef ALLOCATE_PRIMITIVE_MAP
 #undef ALLOCATE_VARSIZE_MAP
 #undef ALLOCATE_MAP
   }
index 4838efb..4c3235e 100644 (file)
@@ -497,7 +497,7 @@ template <typename StaticVisitor>
 void StaticMarkingVisitor<StaticVisitor>::VisitJSRegExp(Map* map,
                                                         HeapObject* object) {
   int last_property_offset =
-      JSRegExp::kSize + kPointerSize * map->inobject_properties();
+      JSRegExp::kSize + kPointerSize * map->GetInObjectProperties();
   StaticVisitor::VisitPointers(
       map->GetHeap(), object,
       HeapObject::RawField(object, JSRegExp::kPropertiesOffset),
index 1819b32..807a651 100644 (file)
@@ -6106,10 +6106,10 @@ class HObjectAccess final {
                          Representation::Integer32());
   }
 
-  static HObjectAccess ForMapInObjectProperties() {
-    return HObjectAccess(kInobject,
-                         Map::kInObjectPropertiesOffset,
-                         Representation::UInteger8());
+  static HObjectAccess ForMapInObjectPropertiesOrConstructorFunctionIndex() {
+    return HObjectAccess(
+        kInobject, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
+        Representation::UInteger8());
   }
 
   static HObjectAccess ForMapInstanceType() {
index 34d8c3d..504c8b8 100644 (file)
@@ -2047,14 +2047,8 @@ HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
   receiver_is_smi.If<HIsSmiAndBranch>(receiver);
   receiver_is_smi.Then();
   {
-    // Load native context.
-    HValue* native_context = BuildGetNativeContext();
-
-    // Load global Number function.
-    HValue* constructor = Add<HLoadNamedField>(
-        native_context, nullptr,
-        HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
-    Push(constructor);
+    // Use global Number function.
+    Push(Add<HConstant>(Context::NUMBER_FUNCTION_INDEX));
   }
   receiver_is_smi.Else();
   {
@@ -2071,75 +2065,23 @@ HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
         Token::LT);
     receiver_is_not_spec_object.Then();
     {
-      // Load native context.
-      HValue* native_context = BuildGetNativeContext();
-
-      IfBuilder receiver_is_heap_number(this);
-      receiver_is_heap_number.If<HCompareNumericAndBranch>(
-          receiver_instance_type, Add<HConstant>(HEAP_NUMBER_TYPE), Token::EQ);
-      receiver_is_heap_number.Then();
-      {
-        // Load global Number function.
-        HValue* constructor = Add<HLoadNamedField>(
-            native_context, nullptr,
-            HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
-        Push(constructor);
-      }
-      receiver_is_heap_number.Else();
-      {
-        // Load boolean map (we cannot decide based on instance type, because
-        // it's ODDBALL_TYPE, which would also include null and undefined).
-        HValue* boolean_map = Add<HLoadRoot>(Heap::kBooleanMapRootIndex);
-
-        IfBuilder receiver_is_boolean(this);
-        receiver_is_boolean.If<HCompareObjectEqAndBranch>(receiver_map,
-                                                          boolean_map);
-        receiver_is_boolean.Then();
-        {
-          // Load global Boolean function.
-          HValue* constructor = Add<HLoadNamedField>(
-              native_context, nullptr,
-              HObjectAccess::ForContextSlot(Context::BOOLEAN_FUNCTION_INDEX));
-          Push(constructor);
-        }
-        receiver_is_boolean.Else();
-        {
-          IfBuilder receiver_is_string(this);
-          receiver_is_string.If<HCompareNumericAndBranch>(
-              receiver_instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE),
-              Token::LT);
-          receiver_is_string.Then();
-          {
-            // Load global String function.
-            HValue* constructor = Add<HLoadNamedField>(
-                native_context, nullptr,
-                HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX));
-            Push(constructor);
-          }
-          receiver_is_string.Else();
-          {
-            IfBuilder receiver_is_symbol(this);
-            receiver_is_symbol.If<HCompareNumericAndBranch>(
-                receiver_instance_type, Add<HConstant>(SYMBOL_TYPE), Token::EQ);
-            receiver_is_symbol.Then();
-            {
-              // Load global Symbol function.
-              HValue* constructor = Add<HLoadNamedField>(
-                  native_context, nullptr, HObjectAccess::ForContextSlot(
-                                               Context::SYMBOL_FUNCTION_INDEX));
-              Push(constructor);
-            }
-            // TODO(bmeurer): Don't inline this into crankshaft code, as it will
-            // deoptimize on all SIMD128 objects.
-            receiver_is_symbol.ElseDeopt(
-                Deoptimizer::kUndefinedOrNullInToObject);
-            receiver_is_symbol.JoinContinuation(&wrap);
-          }
-          receiver_is_string.JoinContinuation(&wrap);
-        }
-        receiver_is_boolean.JoinContinuation(&wrap);
-      }
-      receiver_is_heap_number.JoinContinuation(&wrap);
+      // Load the constructor function index from the {receiver} map.
+      HValue* constructor_function_index = Add<HLoadNamedField>(
+          receiver_map, nullptr,
+          HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());
+
+      // Check if {receiver} has a constructor (null and undefined have no
+      // constructors, so we deoptimize to the runtime to throw an exception).
+      IfBuilder constructor_function_index_is_invalid(this);
+      constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
+          constructor_function_index,
+          Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
+      constructor_function_index_is_invalid.ThenDeopt(
+          Deoptimizer::kUndefinedOrNullInToObject);
+      constructor_function_index_is_invalid.End();
+
+      // Use the global constructor function.
+      Push(constructor_function_index);
     }
     receiver_is_not_spec_object.JoinContinuation(&wrap);
   }
@@ -2149,8 +2091,15 @@ HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
   IfBuilder if_wrap(this, &wrap);
   if_wrap.Then();
   {
+    // Grab the constructor function index.
+    HValue* constructor_index = Pop();
+
+    // Load native context.
+    HValue* native_context = BuildGetNativeContext();
+
     // Determine the initial map for the global constructor.
-    HValue* constructor = Pop();
+    HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
+                                          nullptr, FAST_ELEMENTS);
     HValue* constructor_initial_map = Add<HLoadNamedField>(
         constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
     // Allocate and initialize a JSValue wrapper.
@@ -6443,7 +6392,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
     int descriptor = transition()->LastAdded();
     int index =
         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
-        map_->inobject_properties();
+        map_->GetInObjectProperties();
     PropertyDetails details =
         transition()->instance_descriptors()->GetDetails(descriptor);
     Representation representation = details.representation();
@@ -9963,9 +9912,9 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
 
 void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
     HValue* receiver, Handle<Map> initial_map) {
-  if (initial_map->inobject_properties() != 0) {
+  if (initial_map->GetInObjectProperties() != 0) {
     HConstant* undefined = graph()->GetConstantUndefined();
-    for (int i = 0; i < initial_map->inobject_properties(); i++) {
+    for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
       int property_offset = initial_map->GetInObjectPropertyOffset(i);
       Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
                                           initial_map, property_offset),
@@ -11778,7 +11727,7 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
     }
   }
 
-  int inobject_properties = boilerplate_object->map()->inobject_properties();
+  int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
   HInstruction* value_instruction =
       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
   for (int i = copied_fields; i < inobject_properties; i++) {
index bfb67aa..92576a3 100644 (file)
@@ -2637,7 +2637,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
              lookup_type_ == TRANSITION_TYPE);
       DCHECK(number_ < map->NumberOfOwnDescriptors());
       int field_index = map->instance_descriptors()->GetFieldIndex(number_);
-      return field_index - map->inobject_properties();
+      return field_index - map->GetInObjectProperties();
     }
 
     void LookupDescriptor(Map* map, Name* name) {
index d4cbf94..bbde80c 100644 (file)
@@ -224,7 +224,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
         __ j(less, &no_inobject_slack_tracking);
 
         // Allocate object with a slack.
-        __ movzx_b(esi, FieldOperand(eax, Map::kInObjectPropertiesOffset));
+        __ movzx_b(
+            esi,
+            FieldOperand(
+                eax, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
         __ movzx_b(eax, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
         __ sub(esi, eax);
         __ lea(esi,
index 74844d8..594fe19 100644 (file)
@@ -99,28 +99,11 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
                                                   Handle<Name> name,
                                                   Label* miss,
                                                   ReturnHolder return_what) {
-  PrototypeCheckType check_type = CHECK_ALL_MAPS;
-  int function_index = -1;
-  if (map()->instance_type() < FIRST_NONSTRING_TYPE) {
-    function_index = Context::STRING_FUNCTION_INDEX;
-  } else if (map()->instance_type() == SYMBOL_TYPE) {
-    function_index = Context::SYMBOL_FUNCTION_INDEX;
-  } else if (map()->instance_type() == HEAP_NUMBER_TYPE) {
-    function_index = Context::NUMBER_FUNCTION_INDEX;
-  } else if (*map() == isolate()->heap()->boolean_map()) {
-    function_index = Context::BOOLEAN_FUNCTION_INDEX;
-// clang-format off
-#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)           \
-  } else if (map().is_identical_to(isolate()->factory()->type##_map())) { \
-    function_index = Context::TYPE##_FUNCTION_INDEX;
-  SIMD128_TYPES(SIMD128_TYPE)
-#undef SIMD128_TYPE
-    // clang-format on
-  } else {
-    check_type = SKIP_RECEIVER;
-  }
-
-  if (check_type == CHECK_ALL_MAPS) {
+  PrototypeCheckType check_type = SKIP_RECEIVER;
+  int function_index = map()->IsPrimitiveMap()
+                           ? map()->GetConstructorFunctionIndex()
+                           : Map::kNoConstructorFunctionIndex;
+  if (function_index != Map::kNoConstructorFunctionIndex) {
     GenerateDirectLoadGlobalFunctionPrototype(masm(), function_index,
                                               scratch1(), miss);
     Object* function = isolate()->native_context()->get(function_index);
@@ -128,6 +111,7 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
     Handle<Map> map(JSObject::cast(prototype)->map());
     set_map(map);
     object_reg = scratch1();
+    check_type = CHECK_ALL_MAPS;
   }
 
   // Check that the maps starting from the prototype haven't changed.
index d6802b6..bce3c12 100644 (file)
@@ -127,25 +127,14 @@ void IC::UpdateTarget() { target_ = handle(raw_target(), isolate_); }
 
 
 JSFunction* IC::GetRootConstructor(Map* receiver_map, Context* native_context) {
-  Isolate* isolate = receiver_map->GetIsolate();
-  if (receiver_map == isolate->heap()->boolean_map()) {
-    return native_context->boolean_function();
+  DisallowHeapAllocation no_alloc;
+  if (receiver_map->IsPrimitiveMap()) {
+    int constructor_function_index =
+        receiver_map->GetConstructorFunctionIndex();
+    if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
+      return JSFunction::cast(native_context->get(constructor_function_index));
+    }
   }
-  if (receiver_map->instance_type() == HEAP_NUMBER_TYPE) {
-    return native_context->number_function();
-  }
-  if (receiver_map->instance_type() < FIRST_NONSTRING_TYPE) {
-    return native_context->string_function();
-  }
-  if (receiver_map->instance_type() == SYMBOL_TYPE) {
-    return native_context->symbol_function();
-  }
-#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
-  if (receiver_map == isolate->heap()->type##_map()) {        \
-    return native_context->type##_function();                 \
-  }
-  SIMD128_TYPES(SIMD128_TYPE)
-#undef SIMD128_TYPE
   return nullptr;
 }
 
index 7767132..cb3325b 100644 (file)
@@ -161,7 +161,7 @@ int LayoutDescriptor::GetSlowModeBackingStoreLength(int length) {
 
 int LayoutDescriptor::CalculateCapacity(Map* map, DescriptorArray* descriptors,
                                         int num_descriptors) {
-  int inobject_properties = map->inobject_properties();
+  int inobject_properties = map->GetInObjectProperties();
   if (inobject_properties == 0) return 0;
 
   DCHECK_LE(num_descriptors, descriptors->number_of_descriptors());
@@ -195,7 +195,7 @@ LayoutDescriptor* LayoutDescriptor::Initialize(
     LayoutDescriptor* layout_descriptor, Map* map, DescriptorArray* descriptors,
     int num_descriptors) {
   DisallowHeapAllocation no_allocation;
-  int inobject_properties = map->inobject_properties();
+  int inobject_properties = map->GetInObjectProperties();
 
   for (int i = 0; i < num_descriptors; i++) {
     PropertyDetails details = descriptors->GetDetails(i);
@@ -214,7 +214,7 @@ LayoutDescriptor* LayoutDescriptor::Initialize(
 }
 
 
-// InobjectPropertiesHelper is a helper class for querying whether inobject
+// LayoutDescriptorHelper is a helper class for querying whether inobject
 // property at offset is Double or not.
 LayoutDescriptorHelper::LayoutDescriptorHelper(Map* map)
     : all_fields_tagged_(true),
@@ -227,7 +227,7 @@ LayoutDescriptorHelper::LayoutDescriptorHelper(Map* map)
     return;
   }
 
-  int inobject_properties = map->inobject_properties();
+  int inobject_properties = map->GetInObjectProperties();
   DCHECK(inobject_properties > 0);
   header_size_ = map->instance_size() - (inobject_properties * kPointerSize);
   DCHECK(header_size_ >= 0);
index 25cece8..b961a7d 100644 (file)
@@ -46,7 +46,7 @@ Handle<LayoutDescriptor> LayoutDescriptor::ShareAppend(
   Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(),
                                              isolate);
 
-  if (!InobjectUnboxedField(map->inobject_properties(), details)) {
+  if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
     DCHECK(details.location() != kField ||
            layout_descriptor->IsTagged(details.field_index()));
     return layout_descriptor;
@@ -73,7 +73,7 @@ Handle<LayoutDescriptor> LayoutDescriptor::AppendIfFastOrUseFull(
   if (layout_descriptor->IsSlowLayout()) {
     return full_layout_descriptor;
   }
-  if (!InobjectUnboxedField(map->inobject_properties(), details)) {
+  if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
     DCHECK(details.location() != kField ||
            layout_descriptor->IsTagged(details.field_index()));
     return handle(layout_descriptor, map->GetIsolate());
index f4a4723..e27199a 100644 (file)
@@ -440,7 +440,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                   Operand(Map::kSlackTrackingCounterEnd));
 
         // Allocate object with a slack.
-        __ lbu(a0, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
+        __ lbu(
+            a0,
+            FieldMemOperand(
+                a2, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
         __ lbu(a2, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
         __ subu(a0, a0, a2);
         __ sll(at, a0, kPointerSizeLog2);
index b60d1a8..6d97e44 100644 (file)
@@ -439,7 +439,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                   Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
 
         // Allocate object with a slack.
-        __ lbu(a0, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
+        __ lbu(
+            a0,
+            FieldMemOperand(
+                a2, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
         __ lbu(a2, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
         __ dsubu(a0, a0, a2);
         __ dsll(at, a0, kPointerSizeLog2);
index 5a80d2a..c278bbc 100644 (file)
@@ -264,7 +264,7 @@ void JSObject::JSObjectVerify() {
   }
 
   if (HasFastProperties()) {
-    int actual_unused_property_fields = map()->inobject_properties() +
+    int actual_unused_property_fields = map()->GetInObjectProperties() +
                                         properties()->length() -
                                         map()->NextFreePropertyIndex();
     if (map()->unused_property_fields() != actual_unused_property_fields) {
index 62269ac..27c9695 100644 (file)
@@ -186,7 +186,9 @@ bool Object::IsString() const {
 
 
 bool Object::IsName() const {
-  return IsString() || IsSymbol();
+  STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
+  return Object::IsHeapObject() &&
+         HeapObject::cast(this)->map()->instance_type() <= LAST_NAME_TYPE;
 }
 
 
@@ -985,7 +987,7 @@ bool Object::IsOrderedHashMap() const {
 
 
 bool Object::IsPrimitive() const {
-  return IsOddball() || IsNumber() || IsString();
+  return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap();
 }
 
 
@@ -2117,7 +2119,7 @@ int JSObject::GetInternalFieldCount() {
   // Make sure to adjust for the number of in-object properties. These
   // properties do contribute to the size, but are not internal fields.
   return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
-         map()->inobject_properties();
+         map()->GetInObjectProperties();
 }
 
 
@@ -2274,7 +2276,7 @@ void JSObject::InitializeBody(Map* map,
   int offset = kHeaderSize;
   if (filler_value != pre_allocated_value) {
     int pre_allocated =
-        map->inobject_properties() - map->unused_property_fields();
+        map->GetInObjectProperties() - map->unused_property_fields();
     DCHECK(pre_allocated * kPointerSize + kHeaderSize <= size);
     for (int i = 0; i < pre_allocated; i++) {
       WRITE_FIELD(this, offset, pre_allocated_value);
@@ -2298,8 +2300,8 @@ bool Map::TooManyFastProperties(StoreFromKeyed store_mode) {
   if (unused_property_fields() != 0) return false;
   if (is_prototype_map()) return false;
   int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12;
-  int limit = Max(minimum, inobject_properties());
-  int external = NumberOfFields() - inobject_properties();
+  int limit = Max(minimum, GetInObjectProperties());
+  int external = NumberOfFields() - GetInObjectProperties();
   return external > limit;
 }
 
@@ -3986,14 +3988,46 @@ int Map::instance_size() {
 }
 
 
-int Map::inobject_properties() {
-  return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
+int Map::inobject_properties_or_constructor_function_index() {
+  return READ_BYTE_FIELD(this,
+                         kInObjectPropertiesOrConstructorFunctionIndexOffset);
+}
+
+
+void Map::set_inobject_properties_or_constructor_function_index(int value) {
+  DCHECK(0 <= value && value < 256);
+  WRITE_BYTE_FIELD(this, kInObjectPropertiesOrConstructorFunctionIndexOffset,
+                   static_cast<byte>(value));
+}
+
+
+int Map::GetInObjectProperties() {
+  DCHECK(IsJSObjectMap());
+  return inobject_properties_or_constructor_function_index();
+}
+
+
+void Map::SetInObjectProperties(int value) {
+  DCHECK(IsJSObjectMap());
+  set_inobject_properties_or_constructor_function_index(value);
+}
+
+
+int Map::GetConstructorFunctionIndex() {
+  DCHECK(IsPrimitiveMap());
+  return inobject_properties_or_constructor_function_index();
+}
+
+
+void Map::SetConstructorFunctionIndex(int value) {
+  DCHECK(IsPrimitiveMap());
+  set_inobject_properties_or_constructor_function_index(value);
 }
 
 
 int Map::GetInObjectPropertyOffset(int index) {
   // Adjust for the number of properties stored in the object.
-  index -= inobject_properties();
+  index -= GetInObjectProperties();
   DCHECK(index <= 0);
   return instance_size() + (index * kPointerSize);
 }
@@ -4061,12 +4095,6 @@ void Map::set_instance_size(int value) {
 }
 
 
-void Map::set_inobject_properties(int value) {
-  DCHECK(0 <= value && value < 256);
-  WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
-}
-
-
 void Map::clear_unused() { WRITE_BYTE_FIELD(this, kUnusedOffset, 0); }
 
 
index 54518a2..1f72ce3 100644 (file)
@@ -465,7 +465,9 @@ void Map::MapPrint(std::ostream& os) {  // NOLINT
   HeapObject::PrintHeader(os, "Map");
   os << " - type: " << TypeToString(instance_type()) << "\n";
   os << " - instance size: " << instance_size() << "\n";
-  os << " - inobject properties: " << inobject_properties() << "\n";
+  if (IsJSObjectMap()) {
+    os << " - inobject properties: " << GetInObjectProperties() << "\n";
+  }
   os << " - elements kind: " << ElementsKindToString(elements_kind()) << "\n";
   os << " - unused property fields: " << unused_property_fields() << "\n";
   if (is_deprecated()) os << " - deprecated_map\n";
index e45d0cd..69f3965 100644 (file)
@@ -72,34 +72,17 @@ MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
                                          Handle<Context> native_context) {
   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
   Handle<JSFunction> constructor;
-  if (object->IsNumber()) {
+  if (object->IsSmi()) {
     constructor = handle(native_context->number_function(), isolate);
-  } else if (object->IsBoolean()) {
-    constructor = handle(native_context->boolean_function(), isolate);
-  } else if (object->IsString()) {
-    constructor = handle(native_context->string_function(), isolate);
-  } else if (object->IsSymbol()) {
-    constructor = handle(native_context->symbol_function(), isolate);
-  } else if (object->IsSimd128Value()) {
-    if (object->IsFloat32x4()) {
-      constructor = handle(native_context->float32x4_function(), isolate);
-    } else if (object->IsInt32x4()) {
-      constructor = handle(native_context->int32x4_function(), isolate);
-    } else if (object->IsBool32x4()) {
-      constructor = handle(native_context->bool32x4_function(), isolate);
-    } else if (object->IsInt16x8()) {
-      constructor = handle(native_context->int16x8_function(), isolate);
-    } else if (object->IsBool16x8()) {
-      constructor = handle(native_context->bool16x8_function(), isolate);
-    } else if (object->IsInt8x16()) {
-      constructor = handle(native_context->int8x16_function(), isolate);
-    } else if (object->IsBool8x16()) {
-      constructor = handle(native_context->bool8x16_function(), isolate);
-    } else {
-      UNREACHABLE();
-    }
   } else {
-    return MaybeHandle<JSReceiver>();
+    int constructor_function_index =
+        Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
+    if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
+      return MaybeHandle<JSReceiver>();
+    }
+    constructor = handle(
+        JSFunction::cast(native_context->get(constructor_function_index)),
+        isolate);
   }
   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
   Handle<JSValue>::cast(result)->set_value(*object);
@@ -618,49 +601,23 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
 Map* Object::GetRootMap(Isolate* isolate) {
   DisallowHeapAllocation no_alloc;
   if (IsSmi()) {
-    Context* context = isolate->context()->native_context();
-    return context->number_function()->initial_map();
+    Context* native_context = isolate->context()->native_context();
+    return native_context->number_function()->initial_map();
   }
 
-  HeapObject* heap_object = HeapObject::cast(this);
-
   // The object is either a number, a string, a symbol, a boolean, a SIMD value,
   // a real JS object, or a Harmony proxy.
+  HeapObject* heap_object = HeapObject::cast(this);
   if (heap_object->IsJSReceiver()) {
     return heap_object->map();
   }
-  Context* context = isolate->context()->native_context();
-
-  if (heap_object->IsHeapNumber()) {
-    return context->number_function()->initial_map();
-  }
-  if (heap_object->IsString()) {
-    return context->string_function()->initial_map();
-  }
-  if (heap_object->IsSymbol()) {
-    return context->symbol_function()->initial_map();
-  }
-  if (heap_object->IsBoolean()) {
-    return context->boolean_function()->initial_map();
-  }
-  if (heap_object->IsSimd128Value()) {
-    if (heap_object->IsFloat32x4()) {
-      return context->float32x4_function()->initial_map();
-    } else if (heap_object->IsInt32x4()) {
-      return context->int32x4_function()->initial_map();
-    } else if (heap_object->IsBool32x4()) {
-      return context->bool32x4_function()->initial_map();
-    } else if (heap_object->IsInt16x8()) {
-      return context->int16x8_function()->initial_map();
-    } else if (heap_object->IsBool16x8()) {
-      return context->bool16x8_function()->initial_map();
-    } else if (heap_object->IsInt8x16()) {
-      return context->int8x16_function()->initial_map();
-    } else if (heap_object->IsBool8x16()) {
-      return context->bool8x16_function()->initial_map();
-    } else {
-      UNREACHABLE();
-    }
+  int constructor_function_index =
+      heap_object->map()->GetConstructorFunctionIndex();
+  if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
+    Context* native_context = isolate->context()->native_context();
+    JSFunction* constructor_function =
+        JSFunction::cast(native_context->get(constructor_function_index));
+    return constructor_function->initial_map();
   }
   return isolate->heap()->null_value()->map();
 }
@@ -1731,11 +1688,11 @@ bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
 
   // If no fields were added, and no inobject properties were removed, setting
   // the map is sufficient.
-  if (target_inobject == inobject_properties()) return false;
+  if (target_inobject == GetInObjectProperties()) return false;
   // In-object slack tracking may have reduced the object size of the new map.
   // In that case, succeed if all existing fields were inobject, and they still
   // fit within the new inobject size.
-  DCHECK(target_inobject < inobject_properties());
+  DCHECK(target_inobject < GetInObjectProperties());
   if (target_number_of_fields <= target_inobject) {
     DCHECK(target_number_of_fields + target_unused == target_inobject);
     return false;
@@ -1842,7 +1799,7 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
   Handle<Map> old_map(object->map());
   int old_number_of_fields;
   int number_of_fields = new_map->NumberOfFields();
-  int inobject = new_map->inobject_properties();
+  int inobject = new_map->GetInObjectProperties();
   int unused = new_map->unused_property_fields();
 
   // Nothing to do if no functions were converted to fields and no smis were
@@ -4049,7 +4006,8 @@ MaybeHandle<Object> JSProxy::CallTrap(Handle<JSProxy> proxy,
 
 
 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
-  DCHECK(object->map()->inobject_properties() == map->inobject_properties());
+  DCHECK(object->map()->GetInObjectProperties() ==
+         map->GetInObjectProperties());
   ElementsKind obj_kind = object->map()->elements_kind();
   ElementsKind map_kind = map->elements_kind();
   if (map_kind != obj_kind) {
@@ -4561,7 +4519,7 @@ void JSObject::MigrateFastToSlow(Handle<JSObject> object,
 
   // Ensure that in-object space of slow-mode object does not contain random
   // garbage.
-  int inobject_properties = new_map->inobject_properties();
+  int inobject_properties = new_map->GetInObjectProperties();
   for (int i = 0; i < inobject_properties; i++) {
     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
     object->RawFastPropertyAtPut(index, Smi::FromInt(0));
@@ -4618,7 +4576,7 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
 
   Handle<Map> old_map(object->map(), isolate);
 
-  int inobject_props = old_map->inobject_properties();
+  int inobject_props = old_map->GetInObjectProperties();
 
   // Allocate new map.
   Handle<Map> new_map = Map::CopyDropDescriptors(old_map);
@@ -6506,13 +6464,13 @@ Handle<Map> Map::CopyNormalized(Handle<Map> map,
                                 PropertyNormalizationMode mode) {
   int new_instance_size = map->instance_size();
   if (mode == CLEAR_INOBJECT_PROPERTIES) {
-    new_instance_size -= map->inobject_properties() * kPointerSize;
+    new_instance_size -= map->GetInObjectProperties() * kPointerSize;
   }
 
   Handle<Map> result = RawCopy(map, new_instance_size);
 
   if (mode != CLEAR_INOBJECT_PROPERTIES) {
-    result->set_inobject_properties(map->inobject_properties());
+    result->SetInObjectProperties(map->GetInObjectProperties());
   }
 
   result->set_dictionary_map(true);
@@ -6530,7 +6488,7 @@ Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
   Handle<Map> result = RawCopy(map, map->instance_size());
 
   // Please note instance_type and instance_size are set when allocated.
-  result->set_inobject_properties(map->inobject_properties());
+  result->SetInObjectProperties(map->GetInObjectProperties());
   result->set_unused_property_fields(map->unused_property_fields());
 
   result->ClearCodeCache(map->GetHeap());
@@ -6842,7 +6800,7 @@ Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
       JSObject::kHeaderSize + kPointerSize * inobject_properties;
 
   // Adjust the map with the extra inobject properties.
-  copy->set_inobject_properties(inobject_properties);
+  copy->SetInObjectProperties(inobject_properties);
   copy->set_unused_property_fields(inobject_properties);
   copy->set_instance_size(new_instance_size);
   copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
@@ -9236,10 +9194,10 @@ bool Map::EquivalentToForTransition(Map* other) {
 
 bool Map::EquivalentToForNormalization(Map* other,
                                        PropertyNormalizationMode mode) {
-  int properties = mode == CLEAR_INOBJECT_PROPERTIES
-      ? 0 : other->inobject_properties();
+  int properties =
+      mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
-         inobject_properties() == properties;
+         GetInObjectProperties() == properties;
 }
 
 
@@ -9497,7 +9455,7 @@ static void GetMinInobjectSlack(Map* map, void* data) {
 
 static void ShrinkInstanceSize(Map* map, void* data) {
   int slack = *reinterpret_cast<int*>(data);
-  map->set_inobject_properties(map->inobject_properties() - slack);
+  map->SetInObjectProperties(map->GetInObjectProperties() - slack);
   map->set_unused_property_fields(map->unused_property_fields() - slack);
   map->set_instance_size(map->instance_size() - slack * kPointerSize);
 
@@ -9979,7 +9937,7 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
   } else {
     prototype = isolate->factory()->NewFunctionPrototype(function);
   }
-  map->set_inobject_properties(in_object_properties);
+  map->SetInObjectProperties(in_object_properties);
   map->set_unused_property_fields(in_object_properties);
   DCHECK(map->has_fast_object_elements());
 
index 43e80c8..cfcc3ec 100644 (file)
@@ -612,8 +612,8 @@ static inline bool IsShortcutCandidate(int type) {
 
 enum InstanceType {
   // String types.
-  INTERNALIZED_STRING_TYPE =
-      kTwoByteStringTag | kSeqStringTag | kInternalizedTag,
+  INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kSeqStringTag |
+                             kInternalizedTag,  // FIRST_PRIMITIVE_TYPE
   ONE_BYTE_INTERNALIZED_STRING_TYPE =
       kOneByteStringTag | kSeqStringTag | kInternalizedTag,
   EXTERNAL_INTERNALIZED_STRING_TYPE =
@@ -660,16 +660,18 @@ enum InstanceType {
   // Non-string names
   SYMBOL_TYPE = kNotStringTag,  // FIRST_NONSTRING_TYPE, LAST_NAME_TYPE
 
+  // Other primitives (cannot contain non-map-word pointers to heap objects).
+  HEAP_NUMBER_TYPE,
+  SIMD128_VALUE_TYPE,
+  ODDBALL_TYPE,  // LAST_PRIMITIVE_TYPE
+
   // Objects allocated in their own spaces (never in new space).
   MAP_TYPE,
   CODE_TYPE,
-  ODDBALL_TYPE,
 
   // "Data", objects that cannot contain non-map-word pointers to heap
   // objects.
-  HEAP_NUMBER_TYPE,
   MUTABLE_HEAP_NUMBER_TYPE,
-  SIMD128_VALUE_TYPE,
   FOREIGN_TYPE,
   BYTE_ARRAY_TYPE,
   BYTECODE_ARRAY_TYPE,
@@ -753,6 +755,8 @@ enum InstanceType {
   FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE,
   LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE,
   FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
+  FIRST_PRIMITIVE_TYPE = FIRST_NAME_TYPE,
+  LAST_PRIMITIVE_TYPE = ODDBALL_TYPE,
   // Boundaries for testing for a fixed typed array.
   FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE,
   LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE,
@@ -5273,9 +5277,20 @@ class Map: public HeapObject {
   // Only to clear an unused byte, remove once byte is used.
   inline void clear_unused();
 
-  // Count of properties allocated in the object.
-  inline int inobject_properties();
-  inline void set_inobject_properties(int value);
+  // [inobject_properties_or_constructor_function_index]: Provides access
+  // to the inobject properties in case of JSObject maps, or the constructor
+  // function index in case of primitive maps.
+  inline int inobject_properties_or_constructor_function_index();
+  inline void set_inobject_properties_or_constructor_function_index(int value);
+  // Count of properties allocated in the object (JSObject only).
+  inline int GetInObjectProperties();
+  inline void SetInObjectProperties(int value);
+  // Index of the constructor function in the native context (primitives only),
+  // or the special sentinel value to indicate that there is no object wrapper
+  // for the primitive (i.e. in case of null or undefined).
+  static const int kNoConstructorFunctionIndex = 0;
+  inline int GetConstructorFunctionIndex();
+  inline void SetConstructorFunctionIndex(int value);
 
   // Instance type.
   inline InstanceType instance_type();
@@ -5766,7 +5781,12 @@ class Map: public HeapObject {
     return instance_type() >= FIRST_JS_OBJECT_TYPE;
   }
 
+  bool IsPrimitiveMap() {
+    STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
+    return instance_type() <= LAST_PRIMITIVE_TYPE;
+  }
   bool IsJSObjectMap() {
+    STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
     return instance_type() >= FIRST_JS_OBJECT_TYPE;
   }
   bool IsJSArrayMap() { return instance_type() == JS_ARRAY_TYPE; }
@@ -5847,9 +5867,9 @@ class Map: public HeapObject {
 
   // Byte offsets within kInstanceSizesOffset.
   static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
-  static const int kInObjectPropertiesByte = 1;
-  static const int kInObjectPropertiesOffset =
-      kInstanceSizesOffset + kInObjectPropertiesByte;
+  static const int kInObjectPropertiesOrConstructorFunctionIndexByte = 1;
+  static const int kInObjectPropertiesOrConstructorFunctionIndexOffset =
+      kInstanceSizesOffset + kInObjectPropertiesOrConstructorFunctionIndexByte;
   // Note there is one byte available for use here.
   static const int kUnusedByte = 2;
   static const int kUnusedOffset = kInstanceSizesOffset + kUnusedByte;
index 45a6c9e..0bc781e 100644 (file)
@@ -434,7 +434,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
         __ blt(&no_inobject_slack_tracking);
 
         // Allocate object with a slack.
-        __ lbz(r3, FieldMemOperand(r5, Map::kInObjectPropertiesOffset));
+        __ lbz(
+            r3,
+            FieldMemOperand(
+                r5, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
         __ lbz(r5, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset));
         __ sub(r3, r3, r5);
         if (FLAG_debug_code) {
index 1ba1e34..b8a97c7 100644 (file)
@@ -299,7 +299,7 @@ RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
 
 void Runtime::WeakCollectionInitialize(
     Isolate* isolate, Handle<JSWeakCollection> weak_collection) {
-  DCHECK(weak_collection->map()->inobject_properties() == 0);
+  DCHECK_EQ(0, weak_collection->map()->GetInObjectProperties());
   Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
   weak_collection->set_table(*table);
 }
index 7b937fe..d7fca52 100644 (file)
@@ -1193,7 +1193,7 @@ RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
   if (field_index.is_inobject()) {
     RUNTIME_ASSERT(field_index.property_index() <
-                   object->map()->inobject_properties());
+                   object->map()->GetInObjectProperties());
   } else {
     RUNTIME_ASSERT(field_index.outobject_array_index() <
                    object->properties()->length());
index 94aa42c..55961c7 100644 (file)
@@ -225,7 +225,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
         __ j(less, &no_inobject_slack_tracking);
 
         // Allocate object with a slack.
-        __ movzxbp(rsi, FieldOperand(rax, Map::kInObjectPropertiesOffset));
+        __ movzxbp(
+            rsi,
+            FieldOperand(
+                rax, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
         __ movzxbp(rax, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
         __ subp(rsi, rax);
         __ leap(rsi,
index 4fc08f5..5d10684 100644 (file)
@@ -224,7 +224,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
         __ j(less, &no_inobject_slack_tracking);
 
         // Allocate object with a slack.
-        __ movzx_b(esi, FieldOperand(eax, Map::kInObjectPropertiesOffset));
+        __ movzx_b(
+            esi,
+            FieldOperand(
+                eax, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
         __ movzx_b(eax, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
         __ sub(esi, eax);
         __ lea(esi,
index 06fcd97..1c09752 100644 (file)
@@ -1144,7 +1144,7 @@ TEST(Regression39128) {
   // Step 1: prepare a map for the object.  We add 1 inobject property to it.
   // Create a map with single inobject property.
   Handle<Map> my_map = Map::Create(CcTest::i_isolate(), 1);
-  int n_properties = my_map->inobject_properties();
+  int n_properties = my_map->GetInObjectProperties();
   CHECK_GT(n_properties, 0);
 
   int object_size = my_map->instance_size();
index 30c7ba8..3a629bd 100644 (file)
@@ -634,7 +634,7 @@ static Handle<LayoutDescriptor> TestLayoutDescriptorAppend(
       descriptors->Append(&f);
 
       int field_index = f.GetDetails().field_index();
-      bool is_inobject = field_index < map->inobject_properties();
+      bool is_inobject = field_index < map->GetInObjectProperties();
       for (int bit = 0; bit < field_width_in_words; bit++) {
         CHECK_EQ(is_inobject && (kind == PROP_DOUBLE),
                  !layout_descriptor->IsTagged(field_index + bit));
@@ -763,7 +763,7 @@ static Handle<LayoutDescriptor> TestLayoutDescriptorAppendIfFastOrUseFull(
         int field_index = details.field_index();
         int field_width_in_words = details.field_width_in_words();
 
-        bool is_inobject = field_index < map->inobject_properties();
+        bool is_inobject = field_index < map->GetInObjectProperties();
         for (int bit = 0; bit < field_width_in_words; bit++) {
           CHECK_EQ(is_inobject && details.representation().IsDouble(),
                    !layout_desc->IsTagged(field_index + bit));