From: bmeurer Date: Tue, 11 Aug 2015 19:36:04 +0000 (-0700) Subject: [runtime] Store constructor function index on primitive maps. X-Git-Tag: upstream/4.7.83~921 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6c743b2b39ae4333e9451f99f3edb3e17e7ad2a5;p=platform%2Fupstream%2Fv8.git [runtime] Store constructor function index on primitive maps. 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} --- diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc index 9a68c8dcb..441f57e41 100644 --- a/src/arm/builtins-arm.cc +++ b/src/arm/builtins-arm.cc @@ -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, diff --git a/src/arm64/builtins-arm64.cc b/src/arm64/builtins-arm64.cc index c147a196c..59b55a9f9 100644 --- a/src/arm64/builtins-arm64.cc +++ b/src/arm64/builtins-arm64.cc @@ -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. diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 36d322bb3..bca9b98d4 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -533,7 +533,7 @@ Handle Genesis::CreateEmptyFunction(Isolate* isolate) { int instance_size = JSObject::kHeaderSize + kPointerSize * unused; Handle 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 global_object, DCHECK(regexp_fun->has_initial_map()); Handle initial_map(regexp_fun->initial_map()); - DCHECK_EQ(0, initial_map->inobject_properties()); + DCHECK_EQ(0, initial_map->GetInObjectProperties()); PropertyAttributes final = static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY); @@ -1217,7 +1217,7 @@ void Genesis::InitializeGlobal(Handle 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 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 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 global_object, Handle 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 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 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); diff --git a/src/factory.cc b/src/factory.cc index e5bdc298f..11afad456 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -1601,7 +1601,7 @@ Handle Factory::NewGlobalObject(Handle 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 diff --git a/src/field-index-inl.h b/src/field-index-inl.h index c151ab107..042e4fbdd 100644 --- a/src/field-index-inl.h +++ b/src/field-index-inl.h @@ -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; } diff --git a/src/heap/heap.cc b/src/heap/heap.cc index d8b72bed5..5597553b7 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -2654,7 +2654,8 @@ AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, ->set_layout_descriptor(LayoutDescriptor::FastPointerLayout()); } reinterpret_cast(result)->clear_unused(); - reinterpret_cast(result)->set_inobject_properties(0); + reinterpret_cast(result) + ->set_inobject_properties_or_constructor_function_index(0); reinterpret_cast(result)->set_unused_property_fields(0); reinterpret_cast(result)->set_bit_field(0); reinterpret_cast(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 } diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h index 4838efb91..4c3235e7b 100644 --- a/src/heap/objects-visiting-inl.h +++ b/src/heap/objects-visiting-inl.h @@ -497,7 +497,7 @@ template void StaticMarkingVisitor::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), diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 1819b32d0..807a65102 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -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() { diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 34d8c3d3f..504c8b8ef 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -2047,14 +2047,8 @@ HValue* HGraphBuilder::BuildToObject(HValue* receiver) { receiver_is_smi.If(receiver); receiver_is_smi.Then(); { - // Load native context. - HValue* native_context = BuildGetNativeContext(); - - // Load global Number function. - HValue* constructor = Add( - native_context, nullptr, - HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX)); - Push(constructor); + // Use global Number function. + Push(Add(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( - receiver_instance_type, Add(HEAP_NUMBER_TYPE), Token::EQ); - receiver_is_heap_number.Then(); - { - // Load global Number function. - HValue* constructor = Add( - 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(Heap::kBooleanMapRootIndex); - - IfBuilder receiver_is_boolean(this); - receiver_is_boolean.If(receiver_map, - boolean_map); - receiver_is_boolean.Then(); - { - // Load global Boolean function. - HValue* constructor = Add( - native_context, nullptr, - HObjectAccess::ForContextSlot(Context::BOOLEAN_FUNCTION_INDEX)); - Push(constructor); - } - receiver_is_boolean.Else(); - { - IfBuilder receiver_is_string(this); - receiver_is_string.If( - receiver_instance_type, Add(FIRST_NONSTRING_TYPE), - Token::LT); - receiver_is_string.Then(); - { - // Load global String function. - HValue* constructor = Add( - native_context, nullptr, - HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX)); - Push(constructor); - } - receiver_is_string.Else(); - { - IfBuilder receiver_is_symbol(this); - receiver_is_symbol.If( - receiver_instance_type, Add(SYMBOL_TYPE), Token::EQ); - receiver_is_symbol.Then(); - { - // Load global Symbol function. - HValue* constructor = Add( - 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( + 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( + constructor_function_index, + Add(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(native_context, constructor_index, + nullptr, FAST_ELEMENTS); HValue* constructor_initial_map = Add( 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 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(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(isolate()->factory()->one_pointer_filler_map()); for (int i = copied_fields; i < inobject_properties; i++) { diff --git a/src/hydrogen.h b/src/hydrogen.h index bfb67aaed..92576a316 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -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) { diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc index d4cbf9486..bbde80cde 100644 --- a/src/ia32/builtins-ia32.cc +++ b/src/ia32/builtins-ia32.cc @@ -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, diff --git a/src/ic/handler-compiler.cc b/src/ic/handler-compiler.cc index 74844d869..594fe194f 100644 --- a/src/ic/handler-compiler.cc +++ b/src/ic/handler-compiler.cc @@ -99,28 +99,11 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, Handle 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(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. diff --git a/src/ic/ic-inl.h b/src/ic/ic-inl.h index d6802b67d..bce3c1206 100644 --- a/src/ic/ic-inl.h +++ b/src/ic/ic-inl.h @@ -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; } diff --git a/src/layout-descriptor-inl.h b/src/layout-descriptor-inl.h index 77671328b..cb3325b31 100644 --- a/src/layout-descriptor-inl.h +++ b/src/layout-descriptor-inl.h @@ -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); diff --git a/src/layout-descriptor.cc b/src/layout-descriptor.cc index 25cece822..b961a7de9 100644 --- a/src/layout-descriptor.cc +++ b/src/layout-descriptor.cc @@ -46,7 +46,7 @@ Handle LayoutDescriptor::ShareAppend( Handle 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::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()); diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc index f4a47238d..e27199a90 100644 --- a/src/mips/builtins-mips.cc +++ b/src/mips/builtins-mips.cc @@ -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); diff --git a/src/mips64/builtins-mips64.cc b/src/mips64/builtins-mips64.cc index b60d1a814..6d97e4405 100644 --- a/src/mips64/builtins-mips64.cc +++ b/src/mips64/builtins-mips64.cc @@ -439,7 +439,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, Operand(static_cast(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); diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 5a80d2a04..c278bbc5d 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -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) { diff --git a/src/objects-inl.h b/src/objects-inl.h index 62269acc4..27c969564 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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(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(value)); -} - - void Map::clear_unused() { WRITE_BYTE_FIELD(this, kUnusedOffset, 0); } diff --git a/src/objects-printer.cc b/src/objects-printer.cc index 54518a21f..1f72ce3c8 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -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"; diff --git a/src/objects.cc b/src/objects.cc index e45d0cda7..69f396517 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -72,34 +72,17 @@ MaybeHandle Object::ToObject(Isolate* isolate, Handle native_context) { if (object->IsJSReceiver()) return Handle::cast(object); Handle 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(); + int constructor_function_index = + Handle::cast(object)->map()->GetConstructorFunctionIndex(); + if (constructor_function_index == Map::kNoConstructorFunctionIndex) { + return MaybeHandle(); + } + constructor = handle( + JSFunction::cast(native_context->get(constructor_function_index)), + isolate); } Handle result = isolate->factory()->NewJSObject(constructor); Handle::cast(result)->set_value(*object); @@ -618,49 +601,23 @@ void JSObject::SetNormalizedProperty(Handle 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 object, Handle new_map) { Handle 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 JSProxy::CallTrap(Handle proxy, void JSObject::AllocateStorageForMap(Handle object, Handle 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 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 object, Handle old_map(object->map(), isolate); - int inobject_props = old_map->inobject_properties(); + int inobject_props = old_map->GetInObjectProperties(); // Allocate new map. Handle new_map = Map::CopyDropDescriptors(old_map); @@ -6506,13 +6464,13 @@ Handle Map::CopyNormalized(Handle 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 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::CopyDropDescriptors(Handle map) { Handle 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::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(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 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()); diff --git a/src/objects.h b/src/objects.h index 43e80c815..cfcc3ec42 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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; diff --git a/src/ppc/builtins-ppc.cc b/src/ppc/builtins-ppc.cc index 45a6c9ea6..0bc781e34 100644 --- a/src/ppc/builtins-ppc.cc +++ b/src/ppc/builtins-ppc.cc @@ -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) { diff --git a/src/runtime/runtime-collections.cc b/src/runtime/runtime-collections.cc index 1ba1e3435..b8a97c794 100644 --- a/src/runtime/runtime-collections.cc +++ b/src/runtime/runtime-collections.cc @@ -299,7 +299,7 @@ RUNTIME_FUNCTION(Runtime_MapIteratorNext) { void Runtime::WeakCollectionInitialize( Isolate* isolate, Handle weak_collection) { - DCHECK(weak_collection->map()->inobject_properties() == 0); + DCHECK_EQ(0, weak_collection->map()->GetInObjectProperties()); Handle table = ObjectHashTable::New(isolate, 0); weak_collection->set_table(*table); } diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index 7b937fe3d..d7fca5280 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -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()); diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc index 94aa42c51..55961c7ff 100644 --- a/src/x64/builtins-x64.cc +++ b/src/x64/builtins-x64.cc @@ -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, diff --git a/src/x87/builtins-x87.cc b/src/x87/builtins-x87.cc index 4fc08f5b9..5d10684a2 100644 --- a/src/x87/builtins-x87.cc +++ b/src/x87/builtins-x87.cc @@ -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, diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 06fcd97a7..1c09752b7 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -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 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(); diff --git a/test/cctest/test-unboxed-doubles.cc b/test/cctest/test-unboxed-doubles.cc index 30c7ba833..3a629bdca 100644 --- a/test/cctest/test-unboxed-doubles.cc +++ b/test/cctest/test-unboxed-doubles.cc @@ -634,7 +634,7 @@ static Handle 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 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));