[turbofan] Serialize more Map fields.

... as well as ScopeInfo::ContextLength.

Bug: v8:7790
Change-Id: I3ca8b6f252d96b21d0990f8fc08e076eeeea4176
Reviewed-on: https://chromium-review.googlesource.com/1226973
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55939}
This commit is contained in:
Georg Neis 2018-09-14 15:12:59 +02:00 committed by Commit Bot
parent 0c789aa57f
commit ec55c1ff3d
7 changed files with 128 additions and 51 deletions

View File

@ -129,10 +129,10 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
JSFunctionRef constructor =
target_type.AsHeapConstant()->Ref().AsJSFunction();
if (!constructor.IsConstructor()) return NoChange();
if (!constructor.map().is_constructor()) return NoChange();
JSFunctionRef original_constructor =
new_target_type.AsHeapConstant()->Ref().AsJSFunction();
if (!original_constructor.IsConstructor()) return NoChange();
if (!original_constructor.map().is_constructor()) return NoChange();
// Check if we can inline the allocation.
if (!IsAllocationInlineable(constructor, original_constructor)) {
@ -711,8 +711,8 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
new_target_type.AsHeapConstant()->Ref().IsJSFunction()) {
JSFunctionRef original_constructor =
new_target_type.AsHeapConstant()->Ref().AsJSFunction();
DCHECK(constructor.IsConstructor());
DCHECK(original_constructor.IsConstructor());
DCHECK(constructor.map().is_constructor());
DCHECK(original_constructor.map().is_constructor());
// Check if we can inline the allocation.
if (IsAllocationInlineable(constructor, original_constructor)) {
@ -1721,7 +1721,7 @@ Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
builder.Store(AccessBuilder::ForJSObjectElements(), elements);
if (boilerplate_map.IsJSArrayMap()) {
if (boilerplate.IsJSArray()) {
JSArrayRef boilerplate_array = boilerplate.AsJSArray();
builder.Store(
AccessBuilder::ForJSArrayLength(boilerplate_array.GetElementsKind()),

View File

@ -464,13 +464,23 @@ struct PropertyDescriptor {
class MapData : public HeapObjectData {
public:
MapData(JSHeapBroker* broker, Handle<Map> object, HeapObjectType type);
InstanceType instance_type() const { return instance_type_; }
int instance_size() const { return instance_size_; }
byte bit_field() const { return bit_field_; }
byte bit_field2() const { return bit_field2_; }
uint32_t bit_field3() const { return bit_field3_; }
MapData(JSHeapBroker* broker, Handle<Map> object, HeapObjectType type);
bool can_be_deprecated() const { return can_be_deprecated_; }
bool can_transition() const { return can_transition_; }
int in_object_properties_start_in_words() const {
CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
return in_object_properties_start_in_words_;
}
int in_object_properties() const {
CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
return in_object_properties_;
}
// Extra information.
@ -487,6 +497,12 @@ class MapData : public HeapObjectData {
return descriptors_;
}
void SerializeConstructorOrBackpointer();
ObjectData* constructor_or_backpointer() const {
CHECK(serialized_constructor_or_backpointer_);
return constructor_or_backpointer_;
}
void SerializePrototype();
ObjectData* prototype() const {
CHECK(serialized_prototype_);
@ -499,6 +515,10 @@ class MapData : public HeapObjectData {
byte const bit_field_;
byte const bit_field2_;
uint32_t const bit_field3_;
bool const can_be_deprecated_;
bool const can_transition_;
int const in_object_properties_start_in_words_;
int const in_object_properties_;
bool serialized_elements_kind_generalizations_ = false;
ZoneVector<MapData*> elements_kind_generalizations_;
@ -506,6 +526,9 @@ class MapData : public HeapObjectData {
bool serialized_descriptors_ = false;
ZoneVector<PropertyDescriptor> descriptors_;
bool serialized_constructor_or_backpointer_ = false;
ObjectData* constructor_or_backpointer_ = nullptr;
bool serialized_prototype_ = false;
ObjectData* prototype_ = nullptr;
};
@ -558,6 +581,15 @@ MapData::MapData(JSHeapBroker* broker, Handle<Map> object, HeapObjectType type)
bit_field_(object->bit_field()),
bit_field2_(object->bit_field2()),
bit_field3_(object->bit_field3()),
can_be_deprecated_(object->NumberOfOwnDescriptors() > 0
? object->CanBeDeprecated()
: false),
can_transition_(object->CanTransition()),
in_object_properties_start_in_words_(
object->IsJSObjectMap() ? object->GetInObjectPropertiesStartInWords()
: 0),
in_object_properties_(
object->IsJSObjectMap() ? object->GetInObjectProperties() : 0),
elements_kind_generalizations_(broker->zone()),
descriptors_(broker->zone()) {}
@ -599,6 +631,7 @@ void JSFunctionData::Serialize() {
if (initial_map_->instance_type() == JS_ARRAY_TYPE) {
initial_map_->SerializeElementsKindGeneralizations();
}
initial_map_->SerializeConstructorOrBackpointer();
// TODO(neis): This is currently only needed for native_context's
// object_function, as used by GetObjectCreateMap. If no further use sites
// show up, we should move this into NativeContextData::Serialize.
@ -796,10 +829,19 @@ void JSArrayData::Serialize() {
class ScopeInfoData : public HeapObjectData {
public:
ScopeInfoData(JSHeapBroker* broker, Handle<ScopeInfo> object,
HeapObjectType type)
: HeapObjectData(broker, object, type) {}
HeapObjectType type);
int context_length() const { return context_length_; }
private:
int const context_length_;
};
ScopeInfoData::ScopeInfoData(JSHeapBroker* broker, Handle<ScopeInfo> object,
HeapObjectType type)
: HeapObjectData(broker, object, type),
context_length_(object->ContextLength()) {}
class SharedFunctionInfoData : public HeapObjectData {
public:
int builtin_id() const { return builtin_id_; }
@ -878,7 +920,6 @@ void ModuleData::Serialize() {
Handle<Module> module = Handle<Module>::cast(object());
// TODO(neis): We could be smarter and only serialize the cells we care about.
// TODO(neis): Define a helper for serializing a FixedArray into a ZoneVector.
DCHECK(imports_.empty());
@ -962,6 +1003,16 @@ void JSObjectData::SerializeElements() {
elements_ = broker()->GetOrCreateData(elements_object)->AsFixedArrayBase();
}
void MapData::SerializeConstructorOrBackpointer() {
if (serialized_constructor_or_backpointer_) return;
serialized_constructor_or_backpointer_ = true;
Handle<Map> map = Handle<Map>::cast(object());
DCHECK_NULL(constructor_or_backpointer_);
constructor_or_backpointer_ =
broker()->GetOrCreateData(map->constructor_or_backpointer());
}
void MapData::SerializePrototype() {
if (serialized_prototype_) return;
serialized_prototype_ = true;
@ -1201,6 +1252,7 @@ void JSHeapBroker::SerializeStandardObjects() {
GetOrCreateData(f->false_string());
GetOrCreateData(f->false_value());
GetOrCreateData(f->fixed_array_map());
GetOrCreateData(f->fixed_cow_array_map());
GetOrCreateData(f->fixed_double_array_map());
GetOrCreateData(f->function_context_map());
GetOrCreateData(f->function_string());
@ -1426,6 +1478,7 @@ int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
return data()->AsJSFunction()->initial_map_instance_size_with_min_slack();
}
// Not needed for TypedLowering.
base::Optional<ScriptContextTableRef::LookupResult>
ScriptContextTableRef::lookup(const NameRef& name) const {
AllowHandleAllocation handle_allocation;
@ -1465,12 +1518,11 @@ double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference handle_dereference;
return object<JSObject>()->RawFastDoublePropertyAt(index);
} else {
JSObjectData* object_data = data()->AsJSObject();
CHECK(map().IsUnboxedDoubleField(index));
CHECK(index.is_inobject());
return object_data->GetInobjectField(index.property_index()).AsDouble();
}
JSObjectData* object_data = data()->AsJSObject();
CHECK(map().IsUnboxedDoubleField(index));
CHECK(index.is_inobject());
return object_data->GetInobjectField(index.property_index()).AsDouble();
}
ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const {
@ -1480,26 +1532,23 @@ ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const {
return ObjectRef(broker(),
handle(object<JSObject>()->RawFastPropertyAt(index),
broker()->isolate()));
} else {
JSObjectData* object_data = data()->AsJSObject();
CHECK(!map().IsUnboxedDoubleField(index));
CHECK(index.is_inobject());
return ObjectRef(
object_data->GetInobjectField(index.property_index()).AsObject());
}
JSObjectData* object_data = data()->AsJSObject();
CHECK(!map().IsUnboxedDoubleField(index));
CHECK(index.is_inobject());
return ObjectRef(
object_data->GetInobjectField(index.property_index()).AsObject());
}
bool AllocationSiteRef::IsFastLiteral() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHeapAllocation
allow_heap_allocation; // This is needed for TryMigrateInstance.
AllowHeapAllocation allow_heap_allocation; // For TryMigrateInstance.
AllowHandleAllocation allow_handle_allocation;
AllowHandleDereference allow_handle_dereference;
return IsInlinableFastLiteral(
handle(object<AllocationSite>()->boilerplate(), broker()->isolate()));
} else {
return data()->AsAllocationSite()->IsFastLiteral();
}
return data()->AsAllocationSite()->IsFastLiteral();
}
void JSObjectRef::EnsureElementsTenured() {
@ -1519,9 +1568,9 @@ void JSObjectRef::EnsureElementsTenured() {
Handle<FixedArray>::cast(object_elements));
object<JSObject>()->set_elements(*object_elements);
}
} else {
CHECK(data()->AsJSObject()->cow_or_empty_elements_tenured());
return;
}
CHECK(data()->AsJSObject()->cow_or_empty_elements_tenured());
}
FieldIndex MapRef::GetFieldIndexFor(int descriptor_index) const {
@ -1558,9 +1607,9 @@ NameRef MapRef::GetPropertyKey(int descriptor_index) const {
}
bool MapRef::IsFixedCowArrayMap() const {
AllowHandleDereference allow_handle_dereference;
return *object<Map>() ==
ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map();
Handle<Map> fixed_cow_array_map =
ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map_handle();
return equals(MapRef(broker(), fixed_cow_array_map));
}
MapRef MapRef::FindFieldOwner(int descriptor_index) const {
@ -1727,24 +1776,18 @@ BIMODAL_ACCESSOR(JSFunction, JSGlobalProxy, global_proxy)
BIMODAL_ACCESSOR(JSFunction, Map, initial_map)
BIMODAL_ACCESSOR(JSFunction, Object, prototype)
BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
HANDLE_ACCESSOR_C(JSFunction, bool, IsConstructor)
BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors,
Map::NumberOfOwnDescriptorsBits)
BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit)
BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit)
BIMODAL_ACCESSOR_C(Map, int, instance_size)
BIMODAL_ACCESSOR(Map, Object, prototype)
HANDLE_ACCESSOR_C(Map, bool, CanBeDeprecated)
HANDLE_ACCESSOR_C(Map, bool, CanTransition)
HANDLE_ACCESSOR_C(Map, bool, IsInobjectSlackTrackingInProgress)
HANDLE_ACCESSOR_C(Map, bool, IsJSArrayMap)
HANDLE_ACCESSOR_C(Map, bool, is_stable)
HANDLE_ACCESSOR_C(Map, InstanceType, instance_type)
HANDLE_ACCESSOR_C(Map, int, GetInObjectProperties)
HANDLE_ACCESSOR_C(Map, int, GetInObjectPropertiesStartInWords)
HANDLE_ACCESSOR_C(Map, int, NumberOfOwnDescriptors)
HANDLE_ACCESSOR(Map, Object, constructor_or_backpointer)
BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
BIMODAL_ACCESSOR(Map, Object, constructor_or_backpointer)
#define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
BIMODAL_ACCESSOR(NativeContext, type, name)
@ -1754,8 +1797,6 @@ BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
HANDLE_ACCESSOR(PropertyCell, Object, value)
HANDLE_ACCESSOR_C(PropertyCell, PropertyDetails, property_details)
HANDLE_ACCESSOR_C(ScopeInfo, int, ContextLength)
BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
#define DEF_SFI_ACCESSOR(type, name) \
@ -1767,6 +1808,43 @@ BIMODAL_ACCESSOR_C(String, int, length)
// TODO(neis): Provide StringShape() on StringRef.
bool MapRef::IsInobjectSlackTrackingInProgress() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, IsInobjectSlackTrackingInProgress);
return Map::ConstructionCounterBits::decode(data()->AsMap()->bit_field3()) !=
Map::kNoSlackTracking;
}
bool MapRef::is_stable() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, is_stable);
return !Map::IsUnstableBit::decode(data()->AsMap()->bit_field3());
}
bool MapRef::CanBeDeprecated() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanBeDeprecated);
CHECK_GT(NumberOfOwnDescriptors(), 0);
return data()->AsMap()->can_be_deprecated();
}
bool MapRef::CanTransition() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, CanTransition);
return data()->AsMap()->can_transition();
}
int MapRef::GetInObjectPropertiesStartInWords() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectPropertiesStartInWords);
return data()->AsMap()->in_object_properties_start_in_words();
}
int MapRef::GetInObjectProperties() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetInObjectProperties);
return data()->AsMap()->in_object_properties();
}
int ScopeInfoRef::ContextLength() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(ScopeInfo, ContextLength);
return data()->AsScopeInfo()->context_length();
}
MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const {
DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX);
DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);

View File

@ -179,7 +179,6 @@ class JSFunctionRef : public JSObjectRef {
bool has_initial_map() const;
bool has_prototype() const;
bool IsConstructor() const;
bool PrototypeRequiresRuntimeLookup() const;
void Serialize();
@ -322,13 +321,13 @@ class MapRef : public HeapObjectRef {
int GetInObjectPropertyOffset(int index) const;
ElementsKind elements_kind() const;
bool is_stable() const;
bool is_constructor() const;
bool has_prototype_slot() const;
bool is_deprecated() const;
bool CanBeDeprecated() const;
bool CanTransition() const;
bool IsInobjectSlackTrackingInProgress() const;
bool is_dictionary_map() const;
bool IsJSArrayMap() const;
bool IsFixedCowArrayMap() const;
ObjectRef constructor_or_backpointer() const;

View File

@ -1509,7 +1509,7 @@ Reduction JSTypedLowering::ReduceJSConstructForwardVarargs(Node* node) {
target_type.AsHeapConstant()->Ref().IsJSFunction()) {
// Only optimize [[Construct]] here if {function} is a Constructor.
JSFunctionRef function = target_type.AsHeapConstant()->Ref().AsJSFunction();
if (!function.IsConstructor()) return NoChange();
if (!function.map().is_constructor()) return NoChange();
// Patch {node} to an indirect call via ConstructFunctionForwardVarargs.
Callable callable = CodeFactory::ConstructFunctionForwardVarargs(isolate());
node->RemoveInput(arity + 1);
@ -1545,7 +1545,7 @@ Reduction JSTypedLowering::ReduceJSConstruct(Node* node) {
SharedFunctionInfoRef shared = function.shared();
// Only optimize [[Construct]] here if {function} is a Constructor.
if (!function.IsConstructor()) return NoChange();
if (!function.map().is_constructor()) return NoChange();
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;

View File

@ -369,7 +369,6 @@ Handle<ScopeInfo> ScopeInfo::CreateForEmptyFunction(Isolate* isolate) {
// static
Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
ScopeType type) {
DCHECK(isolate->bootstrapper()->IsActive());
DCHECK(type == SCRIPT_SCOPE || type == FUNCTION_SCOPE);
const int parameter_count = 0;

View File

@ -177,7 +177,8 @@ class ScopeInfo : public FixedArray {
MaybeHandle<ScopeInfo> outer_scope);
static Handle<ScopeInfo> CreateForWithScope(
Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
static Handle<ScopeInfo> CreateForEmptyFunction(Isolate* isolate);
V8_EXPORT_PRIVATE static Handle<ScopeInfo> CreateForEmptyFunction(
Isolate* isolate);
static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);
// Serializes empty scope info.

View File

@ -176,7 +176,7 @@ TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
// JSCreateWithContext
TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
Handle<ScopeInfo> scope_info(factory()->NewScopeInfo(1));
Handle<ScopeInfo> scope_info = ScopeInfo::CreateForEmptyFunction(isolate());
Node* const object = Parameter(Type::Receiver());
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
@ -196,7 +196,7 @@ TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
// JSCreateCatchContext
TEST_F(JSCreateLoweringTest, JSCreateCatchContext) {
Handle<ScopeInfo> scope_info(factory()->NewScopeInfo(1));
Handle<ScopeInfo> scope_info = ScopeInfo::CreateForEmptyFunction(isolate());
Node* const exception = Parameter(Type::Receiver());
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();