[turbofan] Get rid of HeapObjectType-related heap reads.

This removes the last unconditional read accesses to the heap, but
required a significant refactoring.

- Remove HeapObjectRef::type().
- Change HeapObjectData::Is* testers to look at the instance type
  in HeapObjectData::map().

- Remove ObjectRef::oddball_type()
- Add MapRef::oddball_type()
- Add MapRef::is_undetectable().
- Add MapRef::is_callable().

- Remove JSHeapBroker::HeapObjectTypeFromMap()
- Remove Type::For(JSHeapBroker*, Handle<Map>)
- Add BitsetType::Lub(MapRef).
- Add Type::For(MapRef).
- Add Type::For(HeapObjectType).

- Add HeapObjectRef::GetHeapObjectType(). THIS IS TEMPORARY.

As the last item suggests, I couldn't actually remove the
HeapObjectType class yet. See the explanation in the code.

Bug: v8:7790
Change-Id: I508e4bd5337277b0050f2204392fc36f41032fe9
Reviewed-on: https://chromium-review.googlesource.com/1228033
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55994}
This commit is contained in:
Georg Neis 2018-09-18 11:43:24 +02:00 committed by Commit Bot
parent 7f5d299649
commit 253c2469f2
10 changed files with 254 additions and 236 deletions

View File

@ -409,7 +409,7 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
dependencies()->DependOnFieldType(map_ref, number);
// Remember the field map, and try to infer a useful type.
Handle<Map> map(descriptors_field_type->AsClass(), isolate());
field_type = Type::For(js_heap_broker(), map);
field_type = Type::For(MapRef(js_heap_broker(), map));
field_map = MaybeHandle<Map>(map);
}
}
@ -714,7 +714,7 @@ bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name,
dependencies()->DependOnFieldType(transition_map_ref, number);
// Remember the field map, and try to infer a useful type.
Handle<Map> map(descriptors_field_type->AsClass(), isolate());
field_type = Type::For(js_heap_broker(), map);
field_type = Type::For(MapRef(js_heap_broker(), map));
field_map = MaybeHandle<Map>(map);
}
}

View File

@ -165,7 +165,7 @@ Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
// We must be conservative and check if the value in the slot is currently
// the hole or undefined. Only if it is neither of these, can we be sure
// that it won't change anymore.
OddballType oddball_type = maybe_value->oddball_type();
OddballType oddball_type = maybe_value->AsHeapObject().map().oddball_type();
if (oddball_type == OddballType::kUndefined ||
oddball_type == OddballType::kHole) {
maybe_value.reset();

View File

@ -1352,7 +1352,7 @@ base::Optional<MapRef> GetObjectCreateMap(JSHeapBroker* broker,
if (prototype.equals(standard_map.prototype())) {
return standard_map;
}
if (prototype.oddball_type() == OddballType::kNull) {
if (prototype.map().oddball_type() == OddballType::kNull) {
return broker->native_context().slow_object_with_null_prototype_map();
}
if (prototype.IsJSObject()) {
@ -1378,7 +1378,7 @@ Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
Node* properties = jsgraph()->EmptyFixedArrayConstant();
if (instance_map.is_dictionary_map()) {
DCHECK_EQ(prototype_const.type().oddball_type(), OddballType::kNull);
DCHECK_EQ(prototype_const.map().oddball_type(), OddballType::kNull);
// Allocate an empty NameDictionary as backing store for the properties.
Handle<Map> map = isolate()->factory()->name_dictionary_map();
int capacity =
@ -1689,7 +1689,11 @@ Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
value = effect = builder.Finish();
} else if (property_details.representation().IsSmi()) {
// Ensure that value is stored as smi.
value = boilerplate_value.oddball_type() == OddballType::kUninitialized
bool is_uninitialized =
boilerplate_value.IsHeapObject() &&
boilerplate_value.AsHeapObject().map().oddball_type() ==
OddballType::kUninitialized;
value = is_uninitialized
? jsgraph()->ZeroConstant()
: jsgraph()->Constant(boilerplate_value.AsSmi());
} else {
@ -1717,7 +1721,7 @@ Node* JSCreateLowering::AllocateFastLiteral(Node* effect, Node* control,
// Actually allocate and initialize the object.
AllocationBuilder builder(jsgraph(), effect, control);
builder.Allocate(boilerplate_map.instance_size(), pretenure,
Type::For(js_heap_broker(), boilerplate_map.object<Map>()));
Type::For(boilerplate_map));
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(), properties);
builder.Store(AccessBuilder::ForJSObjectElements(), elements);
@ -1805,8 +1809,7 @@ Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
AllocationBuilder builder(jsgraph(), effect, control);
builder.Allocate(size, pretenure,
Type::For(js_heap_broker(), boilerplate_map.object<Map>()));
builder.Allocate(size, pretenure, Type::For(boilerplate_map));
builder.Store(AccessBuilder::ForMap(), boilerplate_map);
builder.Store(AccessBuilder::ForJSObjectPropertiesOrHash(),
boilerplate.raw_properties_or_hash());

View File

@ -68,7 +68,8 @@ Node* JSGraph::Constant(Handle<Object> value) {
Node* JSGraph::Constant(const ObjectRef& ref) {
if (ref.IsSmi()) return Constant(ref.AsSmi());
OddballType oddball_type = ref.oddball_type();
OddballType oddball_type =
ref.AsHeapObject().GetHeapObjectType().oddball_type();
if (ref.IsHeapNumber()) {
return Constant(ref.AsHeapNumber().value());
} else if (oddball_type == OddballType::kUndefined) {

View File

@ -52,27 +52,22 @@ class ObjectData : public ZoneObject {
class HeapObjectData : public ObjectData {
public:
HeapObjectData(JSHeapBroker* broker, Handle<HeapObject> object,
HeapObjectType type);
HeapObjectData(JSHeapBroker* broker, Handle<HeapObject> object);
bool boolean_value() const { return boolean_value_; }
MapData* map() const { return map_; }
static HeapObjectData* Serialize(JSHeapBroker* broker,
Handle<HeapObject> object);
HeapObjectType type() const { return type_; }
bool boolean_value() const { return boolean_value_; }
MapData* map() const { return map_; }
private:
HeapObjectType const type_;
bool const boolean_value_;
MapData* const map_;
};
class PropertyCellData : public HeapObjectData {
public:
PropertyCellData(JSHeapBroker* broker, Handle<PropertyCell> object,
HeapObjectType type);
PropertyCellData(JSHeapBroker* broker, Handle<PropertyCell> object);
PropertyDetails property_details() const { return property_details_; }
@ -87,9 +82,8 @@ class PropertyCellData : public HeapObjectData {
};
PropertyCellData::PropertyCellData(JSHeapBroker* broker,
Handle<PropertyCell> object,
HeapObjectType type)
: HeapObjectData(broker, object, type),
Handle<PropertyCell> object)
: HeapObjectData(broker, object),
property_details_(object->property_details()) {}
void PropertyCellData::Serialize() {
@ -125,8 +119,7 @@ class JSObjectField {
class JSObjectData : public HeapObjectData {
public:
JSObjectData(JSHeapBroker* broker, Handle<JSObject> object,
HeapObjectType type);
JSObjectData(JSHeapBroker* broker, Handle<JSObject> object);
// Recursively serializes all reachable JSObjects.
void SerializeAsBoilerplate();
@ -183,8 +176,7 @@ void JSObjectData::SerializeObjectCreateMap() {
class JSFunctionData : public JSObjectData {
public:
JSFunctionData(JSHeapBroker* broker, Handle<JSFunction> object,
HeapObjectType type);
JSFunctionData(JSHeapBroker* broker, Handle<JSFunction> object);
bool has_initial_map() const { return has_initial_map_; }
bool has_prototype() const { return has_prototype_; }
@ -219,9 +211,8 @@ class JSFunctionData : public JSObjectData {
class JSRegExpData : public JSObjectData {
public:
JSRegExpData(JSHeapBroker* broker, Handle<JSRegExp> object,
HeapObjectType type)
: JSObjectData(broker, object, type) {}
JSRegExpData(JSHeapBroker* broker, Handle<JSRegExp> object)
: JSObjectData(broker, object) {}
void SerializeAsRegExpBoilerplate();
@ -243,9 +234,8 @@ class JSRegExpData : public JSObjectData {
class HeapNumberData : public HeapObjectData {
public:
HeapNumberData(JSHeapBroker* broker, Handle<HeapNumber> object,
HeapObjectType type)
: HeapObjectData(broker, object, type), value_(object->value()) {}
HeapNumberData(JSHeapBroker* broker, Handle<HeapNumber> object)
: HeapObjectData(broker, object), value_(object->value()) {}
double value() const { return value_; }
@ -255,9 +245,8 @@ class HeapNumberData : public HeapObjectData {
class MutableHeapNumberData : public HeapObjectData {
public:
MutableHeapNumberData(JSHeapBroker* broker, Handle<MutableHeapNumber> object,
HeapObjectType type)
: HeapObjectData(broker, object, type), value_(object->value()) {}
MutableHeapNumberData(JSHeapBroker* broker, Handle<MutableHeapNumber> object)
: HeapObjectData(broker, object), value_(object->value()) {}
double value() const { return value_; }
@ -267,8 +256,7 @@ class MutableHeapNumberData : public HeapObjectData {
class ContextData : public HeapObjectData {
public:
ContextData(JSHeapBroker* broker, Handle<Context> object,
HeapObjectType type);
ContextData(JSHeapBroker* broker, Handle<Context> object);
void Serialize();
ContextData* previous() const {
@ -281,9 +269,8 @@ class ContextData : public HeapObjectData {
ContextData* previous_ = nullptr;
};
ContextData::ContextData(JSHeapBroker* broker, Handle<Context> object,
HeapObjectType type)
: HeapObjectData(broker, object, type) {}
ContextData::ContextData(JSHeapBroker* broker, Handle<Context> object)
: HeapObjectData(broker, object) {}
void ContextData::Serialize() {
if (serialized_) return;
@ -311,8 +298,7 @@ class NativeContextData : public ContextData {
return function_maps_;
}
NativeContextData(JSHeapBroker* broker, Handle<NativeContext> object,
HeapObjectType type);
NativeContextData(JSHeapBroker* broker, Handle<NativeContext> object);
void Serialize();
private:
@ -325,13 +311,13 @@ class NativeContextData : public ContextData {
class NameData : public HeapObjectData {
public:
NameData(JSHeapBroker* broker, Handle<Name> object, HeapObjectType type)
: HeapObjectData(broker, object, type) {}
NameData(JSHeapBroker* broker, Handle<Name> object)
: HeapObjectData(broker, object) {}
};
class StringData : public NameData {
public:
StringData(JSHeapBroker* broker, Handle<String> object, HeapObjectType type);
StringData(JSHeapBroker* broker, Handle<String> object);
int length() const { return length_; }
uint16_t first_char() const { return first_char_; }
@ -349,9 +335,8 @@ class StringData : public NameData {
static constexpr int kMaxLengthForDoubleConversion = 23;
};
StringData::StringData(JSHeapBroker* broker, Handle<String> object,
HeapObjectType type)
: NameData(broker, object, type),
StringData::StringData(JSHeapBroker* broker, Handle<String> object)
: NameData(broker, object),
length_(object->length()),
first_char_(length_ > 0 ? object->Get(0) : 0),
is_external_string_(object->IsExternalString()),
@ -366,8 +351,8 @@ StringData::StringData(JSHeapBroker* broker, Handle<String> object,
class InternalizedStringData : public StringData {
public:
InternalizedStringData(JSHeapBroker* broker,
Handle<InternalizedString> object, HeapObjectType type)
: StringData(broker, object, type) {}
Handle<InternalizedString> object)
: StringData(broker, object) {}
};
namespace {
@ -458,8 +443,7 @@ bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) {
class AllocationSiteData : public HeapObjectData {
public:
AllocationSiteData(JSHeapBroker* broker, Handle<AllocationSite> object,
HeapObjectType type);
AllocationSiteData(JSHeapBroker* broker, Handle<AllocationSite> object);
void SerializeBoilerplate();
bool PointsToLiteral() const { return PointsToLiteral_; }
@ -487,8 +471,8 @@ class AllocationSiteData : public HeapObjectData {
class ScriptContextTableData : public HeapObjectData {
public:
ScriptContextTableData(JSHeapBroker* broker,
Handle<ScriptContextTable> object, HeapObjectType type)
: HeapObjectData(broker, object, type) {}
Handle<ScriptContextTable> object)
: HeapObjectData(broker, object) {}
};
struct PropertyDescriptor {
@ -502,7 +486,7 @@ struct PropertyDescriptor {
class MapData : public HeapObjectData {
public:
MapData(JSHeapBroker* broker, Handle<Map> object, HeapObjectType type);
MapData(JSHeapBroker* broker, Handle<Map> object);
InstanceType instance_type() const { return instance_type_; }
int instance_size() const { return instance_size_; }
@ -572,9 +556,8 @@ class MapData : public HeapObjectData {
};
AllocationSiteData::AllocationSiteData(JSHeapBroker* broker,
Handle<AllocationSite> object,
HeapObjectType type)
: HeapObjectData(broker, object, type),
Handle<AllocationSite> object)
: HeapObjectData(broker, object),
PointsToLiteral_(object->PointsToLiteral()),
GetPretenureMode_(object->GetPretenureMode()) {
if (PointsToLiteral_) {
@ -604,17 +587,20 @@ void AllocationSiteData::SerializeBoilerplate() {
}
}
HeapObjectData::HeapObjectData(JSHeapBroker* broker, Handle<HeapObject> object,
HeapObjectType type)
HeapObjectData::HeapObjectData(JSHeapBroker* broker, Handle<HeapObject> object)
: ObjectData(broker, object, false),
type_(type),
boolean_value_(object->BooleanValue(broker->isolate())),
map_(broker->GetOrCreateData(object->map())->AsMap()) {
// We have to use a raw cast below instead of AsMap() because of
// recursion. AsMap() would call IsMap(), which accesses the
// instance_type_ member. In the case of constructing the MapData for the
// meta map (whose map is itself), this member has not yet been
// initialized.
map_(static_cast<MapData*>(broker->GetOrCreateData(object->map()))) {
CHECK(broker->SerializingAllowed());
}
MapData::MapData(JSHeapBroker* broker, Handle<Map> object, HeapObjectType type)
: HeapObjectData(broker, object, type),
MapData::MapData(JSHeapBroker* broker, Handle<Map> object)
: HeapObjectData(broker, object),
instance_type_(object->instance_type()),
instance_size_(object->instance_size()),
bit_field_(object->bit_field()),
@ -632,9 +618,8 @@ MapData::MapData(JSHeapBroker* broker, Handle<Map> object, HeapObjectType type)
elements_kind_generalizations_(broker->zone()),
descriptors_(broker->zone()) {}
JSFunctionData::JSFunctionData(JSHeapBroker* broker, Handle<JSFunction> object,
HeapObjectType type)
: JSObjectData(broker, object, type),
JSFunctionData::JSFunctionData(JSHeapBroker* broker, Handle<JSFunction> object)
: JSObjectData(broker, object),
has_initial_map_(object->has_prototype_slot() &&
object->has_initial_map()),
has_prototype_(object->has_prototype_slot() && object->has_prototype()),
@ -702,8 +687,7 @@ class FeedbackVectorData : public HeapObjectData {
public:
const ZoneVector<ObjectData*>& feedback() { return feedback_; }
FeedbackVectorData(JSHeapBroker* broker, Handle<FeedbackVector> object,
HeapObjectType type);
FeedbackVectorData(JSHeapBroker* broker, Handle<FeedbackVector> object);
void SerializeSlots();
@ -713,9 +697,8 @@ class FeedbackVectorData : public HeapObjectData {
};
FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker,
Handle<FeedbackVector> object,
HeapObjectType type)
: HeapObjectData(broker, object, type), feedback_(broker->zone()) {}
Handle<FeedbackVector> object)
: HeapObjectData(broker, object), feedback_(broker->zone()) {}
void FeedbackVectorData::SerializeSlots() {
if (serialized_) return;
@ -744,9 +727,8 @@ void FeedbackVectorData::SerializeSlots() {
class FixedArrayBaseData : public HeapObjectData {
public:
FixedArrayBaseData(JSHeapBroker* broker, Handle<FixedArrayBase> object,
HeapObjectType type)
: HeapObjectData(broker, object, type), length_(object->length()) {}
FixedArrayBaseData(JSHeapBroker* broker, Handle<FixedArrayBase> object)
: HeapObjectData(broker, object), length_(object->length()) {}
int length() const { return length_; }
@ -754,14 +736,12 @@ class FixedArrayBaseData : public HeapObjectData {
int const length_;
};
JSObjectData::JSObjectData(JSHeapBroker* broker, Handle<JSObject> object,
HeapObjectType type)
: HeapObjectData(broker, object, type), inobject_fields_(broker->zone()) {}
JSObjectData::JSObjectData(JSHeapBroker* broker, Handle<JSObject> object)
: HeapObjectData(broker, object), inobject_fields_(broker->zone()) {}
class FixedArrayData : public FixedArrayBaseData {
public:
FixedArrayData(JSHeapBroker* broker, Handle<FixedArray> object,
HeapObjectType type);
FixedArrayData(JSHeapBroker* broker, Handle<FixedArray> object);
// Creates all elements of the fixed array.
void SerializeContents();
@ -788,14 +768,12 @@ void FixedArrayData::SerializeContents() {
}
}
FixedArrayData::FixedArrayData(JSHeapBroker* broker, Handle<FixedArray> object,
HeapObjectType type)
: FixedArrayBaseData(broker, object, type), contents_(broker->zone()) {}
FixedArrayData::FixedArrayData(JSHeapBroker* broker, Handle<FixedArray> object)
: FixedArrayBaseData(broker, object), contents_(broker->zone()) {}
class FixedDoubleArrayData : public FixedArrayBaseData {
public:
FixedDoubleArrayData(JSHeapBroker* broker, Handle<FixedDoubleArray> object,
HeapObjectType type);
FixedDoubleArrayData(JSHeapBroker* broker, Handle<FixedDoubleArray> object);
// Serializes all elements of the fixed array.
void SerializeContents();
@ -808,9 +786,8 @@ class FixedDoubleArrayData : public FixedArrayBaseData {
};
FixedDoubleArrayData::FixedDoubleArrayData(JSHeapBroker* broker,
Handle<FixedDoubleArray> object,
HeapObjectType type)
: FixedArrayBaseData(broker, object, type), contents_(broker->zone()) {}
Handle<FixedDoubleArray> object)
: FixedArrayBaseData(broker, object), contents_(broker->zone()) {}
void FixedDoubleArrayData::SerializeContents() {
if (serialized_contents_) return;
@ -830,9 +807,8 @@ class BytecodeArrayData : public FixedArrayBaseData {
public:
int register_count() const { return register_count_; }
BytecodeArrayData(JSHeapBroker* broker, Handle<BytecodeArray> object,
HeapObjectType type)
: FixedArrayBaseData(broker, object, type),
BytecodeArrayData(JSHeapBroker* broker, Handle<BytecodeArray> object)
: FixedArrayBaseData(broker, object),
register_count_(object->register_count()) {}
private:
@ -841,8 +817,7 @@ class BytecodeArrayData : public FixedArrayBaseData {
class JSArrayData : public JSObjectData {
public:
JSArrayData(JSHeapBroker* broker, Handle<JSArray> object,
HeapObjectType type);
JSArrayData(JSHeapBroker* broker, Handle<JSArray> object);
void Serialize();
ObjectData* length() const { return length_; }
@ -852,9 +827,8 @@ class JSArrayData : public JSObjectData {
ObjectData* length_ = nullptr;
};
JSArrayData::JSArrayData(JSHeapBroker* broker, Handle<JSArray> object,
HeapObjectType type)
: JSObjectData(broker, object, type) {}
JSArrayData::JSArrayData(JSHeapBroker* broker, Handle<JSArray> object)
: JSObjectData(broker, object) {}
void JSArrayData::Serialize() {
if (serialized_) return;
@ -867,8 +841,7 @@ void JSArrayData::Serialize() {
class ScopeInfoData : public HeapObjectData {
public:
ScopeInfoData(JSHeapBroker* broker, Handle<ScopeInfo> object,
HeapObjectType type);
ScopeInfoData(JSHeapBroker* broker, Handle<ScopeInfo> object);
int context_length() const { return context_length_; }
@ -876,9 +849,8 @@ class ScopeInfoData : public HeapObjectData {
int const context_length_;
};
ScopeInfoData::ScopeInfoData(JSHeapBroker* broker, Handle<ScopeInfo> object,
HeapObjectType type)
: HeapObjectData(broker, object, type),
ScopeInfoData::ScopeInfoData(JSHeapBroker* broker, Handle<ScopeInfo> object)
: HeapObjectData(broker, object),
context_length_(object->ContextLength()) {}
class SharedFunctionInfoData : public HeapObjectData {
@ -891,8 +863,8 @@ class SharedFunctionInfoData : public HeapObjectData {
#undef DECL_ACCESSOR
SharedFunctionInfoData(JSHeapBroker* broker,
Handle<SharedFunctionInfo> object, HeapObjectType type)
: HeapObjectData(broker, object, type),
Handle<SharedFunctionInfo> object)
: HeapObjectData(broker, object),
builtin_id_(object->HasBuiltinId() ? object->builtin_id()
: Builtins::kNoBuiltinId),
GetBytecodeArray_(
@ -918,7 +890,7 @@ class SharedFunctionInfoData : public HeapObjectData {
class ModuleData : public HeapObjectData {
public:
ModuleData(JSHeapBroker* broker, Handle<Module> object, HeapObjectType type);
ModuleData(JSHeapBroker* broker, Handle<Module> object);
void Serialize();
CellData* GetCell(int cell_index) const;
@ -929,9 +901,8 @@ class ModuleData : public HeapObjectData {
ZoneVector<CellData*> exports_;
};
ModuleData::ModuleData(JSHeapBroker* broker, Handle<Module> object,
HeapObjectType type)
: HeapObjectData(broker, object, type),
ModuleData::ModuleData(JSHeapBroker* broker, Handle<Module> object)
: HeapObjectData(broker, object),
imports_(broker->zone()),
exports_(broker->zone()) {}
@ -980,21 +951,20 @@ void ModuleData::Serialize() {
class CellData : public HeapObjectData {
public:
CellData(JSHeapBroker* broker, Handle<Cell> object, HeapObjectType type)
: HeapObjectData(broker, object, type) {}
CellData(JSHeapBroker* broker, Handle<Cell> object)
: HeapObjectData(broker, object) {}
};
class JSGlobalProxyData : public JSObjectData {
public:
JSGlobalProxyData(JSHeapBroker* broker, Handle<JSGlobalProxy> object,
HeapObjectType type)
: JSObjectData(broker, object, type) {}
JSGlobalProxyData(JSHeapBroker* broker, Handle<JSGlobalProxy> object)
: JSObjectData(broker, object) {}
};
class CodeData : public HeapObjectData {
public:
CodeData(JSHeapBroker* broker, Handle<Code> object, HeapObjectType type)
: HeapObjectData(broker, object, type) {}
CodeData(JSHeapBroker* broker, Handle<Code> object)
: HeapObjectData(broker, object) {}
};
#define DEFINE_IS_AND_AS(Name) \
@ -1005,7 +975,7 @@ class CodeData : public HeapObjectData {
} \
if (is_smi()) return false; \
InstanceType instance_type = \
static_cast<const HeapObjectData*>(this)->type().instance_type(); \
static_cast<const HeapObjectData*>(this)->map()->instance_type(); \
return InstanceTypeChecker::Is##Name(instance_type); \
} \
Name##Data* ObjectData::As##Name() { \
@ -1214,12 +1184,11 @@ HeapObjectData* HeapObjectData::Serialize(JSHeapBroker* broker,
Handle<HeapObject> object) {
CHECK(broker->SerializingAllowed());
Handle<Map> map(object->map(), broker->isolate());
HeapObjectType type = broker->HeapObjectTypeFromMap(map);
#define RETURN_CREATE_DATA_IF_MATCH(name) \
if (object->Is##name()) { \
return new (broker->zone()) \
name##Data(broker, Handle<name>::cast(object), type); \
#define RETURN_CREATE_DATA_IF_MATCH(name) \
if (object->Is##name()) { \
return new (broker->zone()) \
name##Data(broker, Handle<name>::cast(object)); \
}
HEAP_BROKER_OBJECT_LIST(RETURN_CREATE_DATA_IF_MATCH)
#undef RETURN_CREATE_DATA_IF_MATCH
@ -1392,36 +1361,6 @@ void JSHeapBroker::SerializeStandardObjects() {
Trace("Finished serializing standard objects.\n");
}
HeapObjectType JSHeapBroker::HeapObjectTypeFromMap(Map* map) const {
AllowHandleDereference allow_handle_dereference;
OddballType oddball_type = OddballType::kNone;
if (map->instance_type() == ODDBALL_TYPE) {
ReadOnlyRoots roots(isolate_);
if (map == roots.undefined_map()) {
oddball_type = OddballType::kUndefined;
} else if (map == roots.null_map()) {
oddball_type = OddballType::kNull;
} else if (map == roots.boolean_map()) {
oddball_type = OddballType::kBoolean;
} else if (map == roots.the_hole_map()) {
oddball_type = OddballType::kHole;
} else if (map == roots.uninitialized_map()) {
oddball_type = OddballType::kUninitialized;
} else {
oddball_type = OddballType::kOther;
DCHECK(map == roots.termination_exception_map() ||
map == roots.arguments_marker_map() ||
map == roots.optimized_out_map() ||
map == roots.stale_register_map());
}
}
HeapObjectType::Flags flags(0);
if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
if (map->is_callable()) flags |= HeapObjectType::kCallable;
return HeapObjectType(map->instance_type(), flags, oddball_type);
}
ObjectData* JSHeapBroker::GetData(Handle<Object> object) const {
auto it = refs_.find(object.address());
return it != refs_.end() ? it->second : nullptr;
@ -1473,14 +1412,6 @@ int ObjectRef::AsSmi() const {
return object<Smi>()->value();
}
HeapObjectType HeapObjectRef::type() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
return broker()->HeapObjectTypeFromMap(object<HeapObject>()->map());
}
return data()->AsHeapObject()->type();
}
NativeContextRef JSHeapBroker::native_context() {
AllowHandleAllocation handle_allocation;
return NativeContextRef(this, isolate()->native_context());
@ -1552,8 +1483,31 @@ ScriptContextTableRef::lookup(const NameRef& name) const {
return result;
}
OddballType ObjectRef::oddball_type() const {
return IsSmi() ? OddballType::kNone : AsHeapObject().type().oddball_type();
OddballType MapRef::oddball_type() const {
if (instance_type() != ODDBALL_TYPE) {
return OddballType::kNone;
}
Factory* f = broker()->isolate()->factory();
if (equals(MapRef(broker(), f->undefined_map()))) {
return OddballType::kUndefined;
}
if (equals(MapRef(broker(), f->null_map()))) {
return OddballType::kNull;
}
if (equals(MapRef(broker(), f->boolean_map()))) {
return OddballType::kBoolean;
}
if (equals(MapRef(broker(), f->the_hole_map()))) {
return OddballType::kHole;
}
if (equals(MapRef(broker(), f->uninitialized_map()))) {
return OddballType::kUninitialized;
}
DCHECK(equals(MapRef(broker(), f->termination_exception_map())) ||
equals(MapRef(broker(), f->arguments_marker_map())) ||
equals(MapRef(broker(), f->optimized_out_map())) ||
equals(MapRef(broker(), f->stale_register_map())));
return OddballType::kOther;
}
ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const {
@ -1817,7 +1771,9 @@ 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_callable, Map::IsCallableBit)
BIMODAL_ACCESSOR_B(Map, bit_field, is_constructor, Map::IsConstructorBit)
BIMODAL_ACCESSOR_B(Map, bit_field, is_undetectable, Map::IsUndetectableBit)
BIMODAL_ACCESSOR_C(Map, int, instance_size)
BIMODAL_ACCESSOR(Map, Object, prototype)
BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
@ -1925,7 +1881,7 @@ bool ObjectRef::BooleanValue() const {
}
double ObjectRef::OddballToNumber() const {
OddballType type = oddball_type();
OddballType type = AsHeapObject().map().oddball_type();
switch (type) {
case OddballType::kBoolean: {
@ -1990,6 +1946,49 @@ ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object) {
CHECK_NOT_NULL(data_);
}
namespace {
OddballType GetOddballType(Isolate* isolate, Map* map) {
if (map->instance_type() != ODDBALL_TYPE) {
return OddballType::kNone;
}
ReadOnlyRoots roots(isolate);
if (map == roots.undefined_map()) {
return OddballType::kUndefined;
}
if (map == roots.null_map()) {
return OddballType::kNull;
}
if (map == roots.boolean_map()) {
return OddballType::kBoolean;
}
if (map == roots.the_hole_map()) {
return OddballType::kHole;
}
if (map == roots.uninitialized_map()) {
return OddballType::kUninitialized;
}
DCHECK(map == roots.termination_exception_map() ||
map == roots.arguments_marker_map() ||
map == roots.optimized_out_map() || map == roots.stale_register_map());
return OddballType::kOther;
}
} // namespace
HeapObjectType HeapObjectRef::GetHeapObjectType() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference handle_dereference;
Map* map = Handle<HeapObject>::cast(object())->map();
HeapObjectType::Flags flags(0);
if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
if (map->is_callable()) flags |= HeapObjectType::kCallable;
return HeapObjectType(map->instance_type(), flags,
GetOddballType(broker()->isolate(), map));
}
HeapObjectType::Flags flags(0);
if (map().is_undetectable()) flags |= HeapObjectType::kUndetectable;
if (map().is_callable()) flags |= HeapObjectType::kCallable;
return HeapObjectType(map().instance_type(), flags, map().oddball_type());
}
base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
@ -2080,9 +2079,8 @@ Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
}
NativeContextData::NativeContextData(JSHeapBroker* broker,
Handle<NativeContext> object,
HeapObjectType type)
: ContextData(broker, object, type), function_maps_(broker->zone()) {}
Handle<NativeContext> object)
: ContextData(broker, object), function_maps_(broker->zone()) {}
void NativeContextData::Serialize() {
if (serialized_) return;

View File

@ -25,35 +25,6 @@ enum class OddballType : uint8_t {
kOther // Oddball, but none of the above.
};
// TODO(neis): Get rid of the HeapObjectType class.
class HeapObjectType {
public:
enum Flag : uint8_t { kUndetectable = 1 << 0, kCallable = 1 << 1 };
typedef base::Flags<Flag> Flags;
HeapObjectType(InstanceType instance_type, Flags flags,
OddballType oddball_type)
: instance_type_(instance_type),
oddball_type_(oddball_type),
flags_(flags) {
DCHECK_EQ(instance_type == ODDBALL_TYPE,
oddball_type != OddballType::kNone);
}
OddballType oddball_type() const { return oddball_type_; }
InstanceType instance_type() const { return instance_type_; }
Flags flags() const { return flags_; }
bool is_callable() const { return flags_ & kCallable; }
bool is_undetectable() const { return flags_ & kUndetectable; }
private:
InstanceType const instance_type_;
OddballType const oddball_type_;
Flags const flags_;
};
// This list is sorted such that subtypes appear before their supertypes.
// DO NOT VIOLATE THIS PROPERTY!
#define HEAP_BROKER_OBJECT_LIST(V) \
@ -114,8 +85,6 @@ class ObjectRef {
return Handle<T>::cast(object());
}
OddballType oddball_type() const;
bool IsSmi() const;
int AsSmi() const;
@ -140,12 +109,49 @@ class ObjectRef {
ObjectData* data_;
};
// Temporary class that carries information from a Map. We'd like to remove
// this class and use MapRef instead, but we can't as long as we support the
// kDisabled broker mode. That's because obtaining the MapRef via
// HeapObjectRef::map() requires a HandleScope when the broker is disabled.
// During OptimizeGraph we generally don't have a HandleScope, however. There
// are two places where we therefore use GetHeapObjectType() instead. Both that
// function and this class should eventually be removed.
class HeapObjectType {
public:
enum Flag : uint8_t { kUndetectable = 1 << 0, kCallable = 1 << 1 };
typedef base::Flags<Flag> Flags;
HeapObjectType(InstanceType instance_type, Flags flags,
OddballType oddball_type)
: instance_type_(instance_type),
oddball_type_(oddball_type),
flags_(flags) {
DCHECK_EQ(instance_type == ODDBALL_TYPE,
oddball_type != OddballType::kNone);
}
OddballType oddball_type() const { return oddball_type_; }
InstanceType instance_type() const { return instance_type_; }
Flags flags() const { return flags_; }
bool is_callable() const { return flags_ & kCallable; }
bool is_undetectable() const { return flags_ & kUndetectable; }
private:
InstanceType const instance_type_;
OddballType const oddball_type_;
Flags const flags_;
};
class HeapObjectRef : public ObjectRef {
public:
using ObjectRef::ObjectRef;
HeapObjectType type() const;
MapRef map() const;
// See the comment on the HeapObjectType class.
HeapObjectType GetHeapObjectType() const;
};
class PropertyCellRef : public HeapObjectRef {
@ -327,10 +333,14 @@ class MapRef : public HeapObjectRef {
bool IsInobjectSlackTrackingInProgress() const;
bool is_dictionary_map() const;
bool IsFixedCowArrayMap() const;
bool is_undetectable() const;
bool is_callable() const;
ObjectRef constructor_or_backpointer() const;
ObjectRef prototype() const;
OddballType oddball_type() const;
base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;
// Concerning the underlying instance_descriptors:
@ -456,11 +466,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
JSHeapBroker(Isolate* isolate, Zone* zone);
void SerializeStandardObjects();
HeapObjectType HeapObjectTypeFromMap(Handle<Map> map) const {
AllowHandleDereference handle_dereference;
return HeapObjectTypeFromMap(*map);
}
Isolate* isolate() const { return isolate_; }
Zone* zone() const { return zone_; }
@ -488,9 +493,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
friend class ObjectRef;
friend class ObjectData;
// TODO(neis): Remove eventually.
HeapObjectType HeapObjectTypeFromMap(Map* map) const;
void AddData(Handle<Object> object, ObjectData* data);
Isolate* const isolate_;

View File

@ -664,20 +664,19 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
property_cell_value_type = Type::Number();
representation = MachineRepresentation::kTaggedPointer;
} else {
Handle<Map> property_cell_value_map(
Handle<HeapObject>::cast(property_cell_value)->map(),
isolate());
property_cell_value_type =
Type::For(js_heap_broker(), property_cell_value_map);
MapRef property_cell_value_map(
js_heap_broker(),
handle(HeapObject::cast(*property_cell_value)->map(),
isolate()));
property_cell_value_type = Type::For(property_cell_value_map);
representation = MachineRepresentation::kTaggedPointer;
// We can only use the property cell value map for map check
// elimination if it's stable, i.e. the HeapObject wasn't
// mutated without the cell state being updated.
if (property_cell_value_map->is_stable()) {
dependencies()->DependOnStableMap(
MapRef(js_heap_broker(), property_cell_value_map));
map = property_cell_value_map;
if (property_cell_value_map.is_stable()) {
dependencies()->DependOnStableMap(property_cell_value_map);
map = property_cell_value_map.object<Map>();
}
}
}
@ -780,8 +779,8 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
native_context().script_context_table().lookup(name);
if (result) {
ObjectRef contents = result->context.get(result->index);
OddballType oddball_type = contents.oddball_type();
if (oddball_type == OddballType::kHole) {
if (contents.IsHeapObject() &&
contents.AsHeapObject().map().oddball_type() == OddballType::kHole) {
return NoChange();
}
Node* context = jsgraph()->Constant(result->context);
@ -809,8 +808,9 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
native_context().script_context_table().lookup(name);
if (result) {
ObjectRef contents = result->context.get(result->index);
OddballType oddball_type = contents.oddball_type();
if (oddball_type == OddballType::kHole || result->immutable) {
if ((contents.IsHeapObject() &&
contents.AsHeapObject().map().oddball_type() == OddballType::kHole) ||
result->immutable) {
return NoChange();
}
Node* context = jsgraph()->Constant(result->context);

View File

@ -952,8 +952,8 @@ Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
}
}
if (input_type.IsHeapConstant()) {
ObjectRef input_value = input_type.AsHeapConstant()->Ref();
if (input_value.oddball_type() != OddballType::kNone) {
HeapObjectRef input_value = input_type.AsHeapConstant()->Ref();
if (input_value.map().oddball_type() != OddballType::kNone) {
return Replace(jsgraph()->Constant(input_value.OddballToNumber()));
}
}

View File

@ -132,8 +132,11 @@ Type::bitset Type::BitsetLub() const {
UNREACHABLE();
}
Type::bitset BitsetType::Lub(HeapObjectType const& type) {
switch (type.instance_type()) {
// TODO(neis): Once the broker mode kDisabled is gone, change the input type to
// MapRef and get rid of the HeapObjectType class.
template <typename MapRefLike>
Type::bitset BitsetType::Lub(const MapRefLike& map) {
switch (map.instance_type()) {
case CONS_STRING_TYPE:
case CONS_ONE_BYTE_STRING_TYPE:
case THIN_STRING_TYPE:
@ -163,7 +166,7 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
case BIGINT_TYPE:
return kBigInt;
case ODDBALL_TYPE:
switch (type.oddball_type()) {
switch (map.oddball_type()) {
case OddballType::kNone:
break;
case OddballType::kHole:
@ -189,15 +192,15 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
case JS_GLOBAL_PROXY_TYPE:
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
if (type.is_undetectable()) {
if (map.is_undetectable()) {
// Currently we assume that every undetectable receiver is also
// callable, which is what we need to support document.all. We
// could add another Type bit to support other use cases in the
// future if necessary.
DCHECK(type.is_callable());
DCHECK(map.is_callable());
return kOtherUndetectable;
}
if (type.is_callable()) {
if (map.is_callable()) {
return kOtherCallable;
}
return kOtherObject;
@ -244,18 +247,18 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
case WASM_MEMORY_TYPE:
case WASM_MODULE_TYPE:
case WASM_TABLE_TYPE:
DCHECK(!type.is_callable());
DCHECK(!type.is_undetectable());
DCHECK(!map.is_callable());
DCHECK(!map.is_undetectable());
return kOtherObject;
case JS_BOUND_FUNCTION_TYPE:
DCHECK(!type.is_undetectable());
DCHECK(!map.is_undetectable());
return kBoundFunction;
case JS_FUNCTION_TYPE:
DCHECK(!type.is_undetectable());
DCHECK(!map.is_undetectable());
return kFunction;
case JS_PROXY_TYPE:
DCHECK(!type.is_undetectable());
if (type.is_callable()) return kCallableProxy;
DCHECK(!map.is_undetectable());
if (map.is_callable()) return kCallableProxy;
return kOtherProxy;
case MAP_TYPE:
case ALLOCATION_SITE_TYPE:
@ -352,6 +355,9 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
UNREACHABLE();
}
// Explicit instantiation.
template Type::bitset BitsetType::Lub<MapRef>(const MapRef& map);
Type::bitset BitsetType::Lub(double value) {
DisallowHeapAllocation no_allocation;
if (IsMinusZero(value)) return kMinusZero;

View File

@ -253,7 +253,10 @@ class V8_EXPORT_PRIVATE BitsetType {
static double Max(bitset);
static bitset Glb(double min, double max);
static bitset Lub(HeapObjectType const& type);
static bitset Lub(HeapObjectType const& type) {
return Lub<HeapObjectType>(type);
}
static bitset Lub(MapRef const& map) { return Lub<MapRef>(map); }
static bitset Lub(double value);
static bitset Lub(double min, double max);
static bitset ExpandInternals(bitset bits);
@ -275,6 +278,9 @@ class V8_EXPORT_PRIVATE BitsetType {
static const Boundary BoundariesArray[];
static inline const Boundary* Boundaries();
static inline size_t BoundariesSize();
template <typename MapRefLike>
static bitset Lub(MapRefLike const& map);
};
// -----------------------------------------------------------------------------
@ -379,8 +385,10 @@ class V8_EXPORT_PRIVATE Type {
static Type Union(Type type1, Type type2, Zone* zone);
static Type Intersect(Type type1, Type type2, Zone* zone);
static Type For(JSHeapBroker* js_heap_broker, Handle<i::Map> map) {
HeapObjectType type = js_heap_broker->HeapObjectTypeFromMap(map);
static Type For(HeapObjectType const& type) {
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
}
static Type For(MapRef const& type) {
return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
}
@ -547,7 +555,7 @@ class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
static HeapConstantType* New(const HeapObjectRef& heap_ref, Zone* zone) {
DCHECK(!heap_ref.IsHeapNumber());
DCHECK_IMPLIES(heap_ref.IsString(), heap_ref.IsInternalizedString());
BitsetType::bitset bitset = BitsetType::Lub(heap_ref.type());
BitsetType::bitset bitset = BitsetType::Lub(heap_ref.GetHeapObjectType());
return new (zone->New(sizeof(HeapConstantType)))
HeapConstantType(bitset, heap_ref);
}