summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/js-heap-broker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/js-heap-broker.cc')
-rw-r--r--deps/v8/src/compiler/js-heap-broker.cc502
1 files changed, 345 insertions, 157 deletions
diff --git a/deps/v8/src/compiler/js-heap-broker.cc b/deps/v8/src/compiler/js-heap-broker.cc
index 05048f7f4b..9a725eb4e9 100644
--- a/deps/v8/src/compiler/js-heap-broker.cc
+++ b/deps/v8/src/compiler/js-heap-broker.cc
@@ -16,6 +16,7 @@
#include "src/compiler/bytecode-analysis.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/per-isolate-compiler-cache.h"
+#include "src/execution/protectors-inl.h"
#include "src/init/bootstrapper.h"
#include "src/objects/allocation-site-inl.h"
#include "src/objects/api-callbacks.h"
@@ -86,6 +87,11 @@ class ObjectData : public ZoneObject {
ObjectDataKind kind() const { return kind_; }
bool is_smi() const { return kind_ == kSmi; }
+#ifdef DEBUG
+ enum class Usage{kUnused, kOnlyIdentityUsed, kDataUsed};
+ mutable Usage used_status = Usage::kUnused;
+#endif // DEBUG
+
private:
Handle<Object> const object_;
ObjectDataKind const kind_;
@@ -420,7 +426,7 @@ class JSTypedArrayData : public JSObjectData {
bool is_on_heap() const { return is_on_heap_; }
size_t length() const { return length_; }
- void* external_pointer() const { return external_pointer_; }
+ void* data_ptr() const { return data_ptr_; }
void Serialize(JSHeapBroker* broker);
bool serialized() const { return serialized_; }
@@ -430,7 +436,7 @@ class JSTypedArrayData : public JSObjectData {
private:
bool const is_on_heap_;
size_t const length_;
- void* const external_pointer_;
+ void* const data_ptr_;
bool serialized_ = false;
HeapObjectData* buffer_ = nullptr;
@@ -441,7 +447,7 @@ JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
: JSObjectData(broker, storage, object),
is_on_heap_(object->is_on_heap()),
length_(object->length()),
- external_pointer_(object->external_pointer()) {}
+ data_ptr_(object->DataPtr()) {}
void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
if (serialized_) return;
@@ -833,8 +839,7 @@ bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth,
// Check the in-object properties.
Handle<DescriptorArray> descriptors(boilerplate->map().instance_descriptors(),
isolate);
- int limit = boilerplate->map().NumberOfOwnDescriptors();
- for (int i = 0; i < limit; i++) {
+ for (InternalIndex i : boilerplate->map().IterateOwnDescriptors()) {
PropertyDetails details = descriptors->GetDetails(i);
if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind());
@@ -962,9 +967,6 @@ class MapData : public HeapObjectData {
bool supports_fast_array_resize() const {
return supports_fast_array_resize_;
}
- bool IsMapOfTargetGlobalProxy() const {
- return is_map_of_target_global_proxy_;
- }
bool is_abandoned_prototype_map() const {
return is_abandoned_prototype_map_;
}
@@ -979,9 +981,10 @@ class MapData : public HeapObjectData {
// Serialize a single (or all) own slot(s) of the descriptor array and recurse
// on field owner(s).
- void SerializeOwnDescriptor(JSHeapBroker* broker, int descriptor_index);
+ void SerializeOwnDescriptor(JSHeapBroker* broker,
+ InternalIndex descriptor_index);
void SerializeOwnDescriptors(JSHeapBroker* broker);
- ObjectData* GetStrongValue(int descriptor_index) const;
+ ObjectData* GetStrongValue(InternalIndex descriptor_index) const;
DescriptorArrayData* instance_descriptors() const {
return instance_descriptors_;
}
@@ -1027,7 +1030,6 @@ class MapData : public HeapObjectData {
int const unused_property_fields_;
bool const supports_fast_array_iteration_;
bool const supports_fast_array_resize_;
- bool const is_map_of_target_global_proxy_;
bool const is_abandoned_prototype_map_;
bool serialized_elements_kind_generalizations_ = false;
@@ -1109,8 +1111,9 @@ bool IsReadOnlyLengthDescriptor(Isolate* isolate, Handle<Map> jsarray_map) {
DCHECK(!jsarray_map->is_dictionary_map());
Handle<Name> length_string = isolate->factory()->length_string();
DescriptorArray descriptors = jsarray_map->instance_descriptors();
- int number = descriptors.Search(*length_string, *jsarray_map);
- DCHECK_NE(DescriptorArray::kNotFound, number);
+ // TODO(jkummerow): We could skip the search and hardcode number == 0.
+ InternalIndex number = descriptors.Search(*length_string, *jsarray_map);
+ DCHECK(number.is_found());
return descriptors.GetDetails(number).IsReadOnly();
}
@@ -1120,7 +1123,7 @@ bool SupportsFastArrayIteration(Isolate* isolate, Handle<Map> map) {
map->prototype().IsJSArray() &&
isolate->IsAnyInitialArrayPrototype(
handle(JSArray::cast(map->prototype()), isolate)) &&
- isolate->IsNoElementsProtectorIntact();
+ Protectors::IsNoElementsIntact(isolate);
}
bool SupportsFastArrayResize(Isolate* isolate, Handle<Map> map) {
@@ -1154,8 +1157,6 @@ MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
SupportsFastArrayIteration(broker->isolate(), object)),
supports_fast_array_resize_(
SupportsFastArrayResize(broker->isolate(), object)),
- is_map_of_target_global_proxy_(
- object->IsMapOfGlobalProxy(broker->target_native_context().object())),
is_abandoned_prototype_map_(object->is_abandoned_prototype_map()),
elements_kind_generalizations_(broker->zone()) {}
@@ -1268,7 +1269,6 @@ class FeedbackVectorData : public HeapObjectData {
double invocation_count() const { return invocation_count_; }
void Serialize(JSHeapBroker* broker);
- const ZoneVector<ObjectData*>& feedback() { return feedback_; }
FeedbackCellData* GetClosureFeedbackCell(JSHeapBroker* broker,
int index) const;
@@ -1276,7 +1276,6 @@ class FeedbackVectorData : public HeapObjectData {
double const invocation_count_;
bool serialized_ = false;
- ZoneVector<ObjectData*> feedback_;
ZoneVector<ObjectData*> closure_feedback_cell_array_;
};
@@ -1285,7 +1284,6 @@ FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker,
Handle<FeedbackVector> object)
: HeapObjectData(broker, storage, object),
invocation_count_(object->invocation_count()),
- feedback_(broker->zone()),
closure_feedback_cell_array_(broker->zone()) {}
FeedbackCellData* FeedbackVectorData::GetClosureFeedbackCell(
@@ -1309,26 +1307,6 @@ void FeedbackVectorData::Serialize(JSHeapBroker* broker) {
TraceScope tracer(broker, this, "FeedbackVectorData::Serialize");
Handle<FeedbackVector> vector = Handle<FeedbackVector>::cast(object());
- DCHECK(feedback_.empty());
- feedback_.reserve(vector->length());
- for (int i = 0; i < vector->length(); ++i) {
- MaybeObject value = vector->get(i);
- ObjectData* slot_value =
- value->IsObject() ? broker->GetOrCreateData(value->cast<Object>())
- : nullptr;
- feedback_.push_back(slot_value);
- if (slot_value == nullptr) continue;
-
- if (slot_value->IsAllocationSite() &&
- slot_value->AsAllocationSite()->IsFastLiteral()) {
- slot_value->AsAllocationSite()->SerializeBoilerplate(broker);
- } else if (slot_value->IsJSRegExp()) {
- slot_value->AsJSRegExp()->SerializeAsRegExpBoilerplate(broker);
- }
- }
- DCHECK_EQ(vector->length(), feedback_.size());
- TRACE(broker, "Copied " << feedback_.size() << " slots");
-
DCHECK(closure_feedback_cell_array_.empty());
int length = vector->closure_feedback_cell_array().length();
closure_feedback_cell_array_.reserve(length);
@@ -1496,10 +1474,6 @@ class BytecodeArrayData : public FixedArrayBaseData {
return *(Handle<Smi>::cast(constant_pool_[index]->object()));
}
- bool IsSerializedForCompilation() const {
- return is_serialized_for_compilation_;
- }
-
void SerializeForCompilation(JSHeapBroker* broker) {
if (is_serialized_for_compilation_) return;
@@ -1843,23 +1817,15 @@ class JSGlobalObjectData : public JSObjectData {
public:
JSGlobalObjectData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSGlobalObject> object);
-};
-
-JSGlobalObjectData::JSGlobalObjectData(JSHeapBroker* broker,
- ObjectData** storage,
- Handle<JSGlobalObject> object)
- : JSObjectData(broker, storage, object) {}
-
-class JSGlobalProxyData : public JSObjectData {
- public:
- JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
- Handle<JSGlobalProxy> object);
+ bool IsDetached() const { return is_detached_; }
PropertyCellData* GetPropertyCell(
JSHeapBroker* broker, NameData* name,
SerializationPolicy policy = SerializationPolicy::kAssumeSerialized);
private:
+ bool const is_detached_;
+
// Properties that either
// (1) are known to exist as property cells on the global object, or
// (2) are known not to (possibly they don't exist at all).
@@ -1867,9 +1833,22 @@ class JSGlobalProxyData : public JSObjectData {
ZoneVector<std::pair<NameData*, PropertyCellData*>> properties_;
};
+JSGlobalObjectData::JSGlobalObjectData(JSHeapBroker* broker,
+ ObjectData** storage,
+ Handle<JSGlobalObject> object)
+ : JSObjectData(broker, storage, object),
+ is_detached_(object->IsDetached()),
+ properties_(broker->zone()) {}
+
+class JSGlobalProxyData : public JSObjectData {
+ public:
+ JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
+ Handle<JSGlobalProxy> object);
+};
+
JSGlobalProxyData::JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSGlobalProxy> object)
- : JSObjectData(broker, storage, object), properties_(broker->zone()) {}
+ : JSObjectData(broker, storage, object) {}
namespace {
base::Optional<PropertyCellRef> GetPropertyCellFromHeap(JSHeapBroker* broker,
@@ -1888,7 +1867,7 @@ base::Optional<PropertyCellRef> GetPropertyCellFromHeap(JSHeapBroker* broker,
}
} // namespace
-PropertyCellData* JSGlobalProxyData::GetPropertyCell(
+PropertyCellData* JSGlobalObjectData::GetPropertyCell(
JSHeapBroker* broker, NameData* name, SerializationPolicy policy) {
CHECK_NOT_NULL(name);
for (auto const& p : properties_) {
@@ -1911,6 +1890,13 @@ PropertyCellData* JSGlobalProxyData::GetPropertyCell(
return result;
}
+class TemplateObjectDescriptionData : public HeapObjectData {
+ public:
+ TemplateObjectDescriptionData(JSHeapBroker* broker, ObjectData** storage,
+ Handle<TemplateObjectDescription> object)
+ : HeapObjectData(broker, storage, object) {}
+};
+
class CodeData : public HeapObjectData {
public:
CodeData(JSHeapBroker* broker, ObjectData** storage, Handle<Code> object)
@@ -2001,20 +1987,20 @@ void MapData::SerializeOwnDescriptors(JSHeapBroker* broker) {
Handle<Map> map = Handle<Map>::cast(object());
int const number_of_own = map->NumberOfOwnDescriptors();
- for (int i = 0; i < number_of_own; ++i) {
+ for (InternalIndex i : InternalIndex::Range(number_of_own)) {
SerializeOwnDescriptor(broker, i);
}
}
-ObjectData* MapData::GetStrongValue(int descriptor_index) const {
- auto data = instance_descriptors_->contents().find(descriptor_index);
+ObjectData* MapData::GetStrongValue(InternalIndex descriptor_index) const {
+ auto data = instance_descriptors_->contents().find(descriptor_index.as_int());
if (data == instance_descriptors_->contents().end()) return nullptr;
return data->second.value;
}
void MapData::SerializeOwnDescriptor(JSHeapBroker* broker,
- int descriptor_index) {
+ InternalIndex descriptor_index) {
TraceScope tracer(broker, this, "MapData::SerializeOwnDescriptor");
Handle<Map> map = Handle<Map>::cast(object());
@@ -2025,8 +2011,8 @@ void MapData::SerializeOwnDescriptor(JSHeapBroker* broker,
ZoneMap<int, PropertyDescriptor>& contents =
instance_descriptors()->contents();
- CHECK_LT(descriptor_index, map->NumberOfOwnDescriptors());
- if (contents.find(descriptor_index) != contents.end()) return;
+ CHECK_LT(descriptor_index.as_int(), map->NumberOfOwnDescriptors());
+ if (contents.find(descriptor_index.as_int()) != contents.end()) return;
Isolate* const isolate = broker->isolate();
auto descriptors =
@@ -2051,14 +2037,14 @@ void MapData::SerializeOwnDescriptor(JSHeapBroker* broker,
broker->GetOrCreateData(descriptors->GetFieldType(descriptor_index));
d.is_unboxed_double_field = map->IsUnboxedDoubleField(d.field_index);
}
- contents[descriptor_index] = d;
+ contents[descriptor_index.as_int()] = d;
if (d.details.location() == kField) {
// Recurse on the owner map.
d.field_owner->SerializeOwnDescriptor(broker, descriptor_index);
}
- TRACE(broker, "Copied descriptor " << descriptor_index << " into "
+ TRACE(broker, "Copied descriptor " << descriptor_index.as_int() << " into "
<< instance_descriptors_ << " ("
<< contents.size() << " total)");
}
@@ -2146,8 +2132,7 @@ void JSObjectData::SerializeRecursiveAsBoilerplate(JSHeapBroker* broker,
// Check the in-object properties.
Handle<DescriptorArray> descriptors(boilerplate->map().instance_descriptors(),
isolate);
- int const limit = boilerplate->map().NumberOfOwnDescriptors();
- for (int i = 0; i < limit; i++) {
+ for (InternalIndex i : boilerplate->map().IterateOwnDescriptors()) {
PropertyDetails details = descriptors->GetDetails(i);
if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind());
@@ -2210,6 +2195,12 @@ void JSRegExpData::SerializeAsRegExpBoilerplate(JSHeapBroker* broker) {
}
bool ObjectRef::equals(const ObjectRef& other) const {
+#ifdef DEBUG
+ if (broker()->mode() == JSHeapBroker::kSerialized &&
+ data_->used_status == ObjectData::Usage::kUnused) {
+ data_->used_status = ObjectData::Usage::kOnlyIdentityUsed;
+ }
+#endif // DEBUG
return data_ == other.data_;
}
@@ -2269,7 +2260,7 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone,
TRACE(this, "Constructing heap broker");
}
-std::ostream& JSHeapBroker::Trace() {
+std::ostream& JSHeapBroker::Trace() const {
return trace_out_ << "[" << this << "] "
<< std::string(trace_indentation_ * 2, ' ');
}
@@ -2280,10 +2271,92 @@ void JSHeapBroker::StopSerializing() {
mode_ = kSerialized;
}
+#ifdef DEBUG
+void JSHeapBroker::PrintRefsAnalysis() const {
+ // Usage counts
+ size_t used_total = 0, unused_total = 0, identity_used_total = 0;
+ for (RefsMap::Entry* ref = refs_->Start(); ref != nullptr;
+ ref = refs_->Next(ref)) {
+ switch (ref->value->used_status) {
+ case ObjectData::Usage::kUnused:
+ ++unused_total;
+ break;
+ case ObjectData::Usage::kOnlyIdentityUsed:
+ ++identity_used_total;
+ break;
+ case ObjectData::Usage::kDataUsed:
+ ++used_total;
+ break;
+ }
+ }
+
+ // Ref types analysis
+ TRACE_BROKER_MEMORY(
+ this, "Refs: " << refs_->occupancy() << "; data used: " << used_total
+ << "; only identity used: " << identity_used_total
+ << "; unused: " << unused_total);
+ size_t used_smis = 0, unused_smis = 0, identity_used_smis = 0;
+ size_t used[LAST_TYPE + 1] = {0};
+ size_t unused[LAST_TYPE + 1] = {0};
+ size_t identity_used[LAST_TYPE + 1] = {0};
+ for (RefsMap::Entry* ref = refs_->Start(); ref != nullptr;
+ ref = refs_->Next(ref)) {
+ if (ref->value->is_smi()) {
+ switch (ref->value->used_status) {
+ case ObjectData::Usage::kUnused:
+ ++unused_smis;
+ break;
+ case ObjectData::Usage::kOnlyIdentityUsed:
+ ++identity_used_smis;
+ break;
+ case ObjectData::Usage::kDataUsed:
+ ++used_smis;
+ break;
+ }
+ } else {
+ InstanceType instance_type =
+ static_cast<const HeapObjectData*>(ref->value)
+ ->map()
+ ->instance_type();
+ CHECK_LE(FIRST_TYPE, instance_type);
+ CHECK_LE(instance_type, LAST_TYPE);
+ switch (ref->value->used_status) {
+ case ObjectData::Usage::kUnused:
+ ++unused[instance_type];
+ break;
+ case ObjectData::Usage::kOnlyIdentityUsed:
+ ++identity_used[instance_type];
+ break;
+ case ObjectData::Usage::kDataUsed:
+ ++used[instance_type];
+ break;
+ }
+ }
+ }
+
+ TRACE_BROKER_MEMORY(
+ this, "Smis: " << used_smis + identity_used_smis + unused_smis
+ << "; data used: " << used_smis << "; only identity used: "
+ << identity_used_smis << "; unused: " << unused_smis);
+ for (uint16_t i = FIRST_TYPE; i <= LAST_TYPE; ++i) {
+ size_t total = used[i] + identity_used[i] + unused[i];
+ if (total == 0) continue;
+ TRACE_BROKER_MEMORY(
+ this, InstanceType(i) << ": " << total << "; data used: " << used[i]
+ << "; only identity used: " << identity_used[i]
+ << "; unused: " << unused[i]);
+ }
+}
+#endif // DEBUG
+
void JSHeapBroker::Retire() {
CHECK_EQ(mode_, kSerialized);
TRACE(this, "Retiring");
mode_ = kRetired;
+
+#ifdef DEBUG
+ PrintRefsAnalysis();
+#endif // DEBUG
}
bool JSHeapBroker::SerializingAllowed() const { return mode() == kSerializing; }
@@ -2473,6 +2546,7 @@ void JSHeapBroker::InitializeAndStartSerializing(
GetOrCreateData(f->empty_fixed_array());
GetOrCreateData(f->empty_string());
GetOrCreateData(f->eval_context_map());
+ GetOrCreateData(f->exec_string());
GetOrCreateData(f->false_string());
GetOrCreateData(f->false_value());
GetOrCreateData(f->fixed_array_map());
@@ -2480,11 +2554,13 @@ void JSHeapBroker::InitializeAndStartSerializing(
GetOrCreateData(f->fixed_double_array_map());
GetOrCreateData(f->function_context_map());
GetOrCreateData(f->function_string());
+ GetOrCreateData(f->has_instance_symbol());
GetOrCreateData(f->heap_number_map());
GetOrCreateData(f->length_string());
GetOrCreateData(f->many_closures_cell_map());
GetOrCreateData(f->minus_zero_value());
GetOrCreateData(f->name_dictionary_map());
+ GetOrCreateData(f->name_string());
GetOrCreateData(f->NaN_string());
GetOrCreateData(f->null_map());
GetOrCreateData(f->null_string());
@@ -2495,6 +2571,7 @@ void JSHeapBroker::InitializeAndStartSerializing(
GetOrCreateData(f->optimized_out());
GetOrCreateData(f->optimized_out_map());
GetOrCreateData(f->property_array_map());
+ GetOrCreateData(f->prototype_string());
GetOrCreateData(f->ReflectHas_string());
GetOrCreateData(f->ReflectGet_string());
GetOrCreateData(f->sloppy_arguments_elements_map());
@@ -2505,6 +2582,7 @@ void JSHeapBroker::InitializeAndStartSerializing(
GetOrCreateData(f->termination_exception_map());
GetOrCreateData(f->the_hole_map());
GetOrCreateData(f->the_hole_value());
+ GetOrCreateData(f->then_string());
GetOrCreateData(f->true_string());
GetOrCreateData(f->true_value());
GetOrCreateData(f->undefined_map());
@@ -2517,7 +2595,9 @@ void JSHeapBroker::InitializeAndStartSerializing(
GetOrCreateData(f->array_buffer_detaching_protector())
->AsPropertyCell()
->Serialize(this);
- GetOrCreateData(f->array_constructor_protector())->AsCell()->Serialize(this);
+ GetOrCreateData(f->array_constructor_protector())
+ ->AsPropertyCell()
+ ->Serialize(this);
GetOrCreateData(f->array_iterator_protector())
->AsPropertyCell()
->Serialize(this);
@@ -2537,7 +2617,9 @@ void JSHeapBroker::InitializeAndStartSerializing(
GetOrCreateData(f->promise_then_protector())
->AsPropertyCell()
->Serialize(this);
- GetOrCreateData(f->string_length_protector())->AsCell()->Serialize(this);
+ GetOrCreateData(f->string_length_protector())
+ ->AsPropertyCell()
+ ->Serialize(this);
// - CEntry stub
GetOrCreateData(
CodeFactory::CEntry(isolate(), 1, kDontSaveFPRegs, kArgvOnStack, true));
@@ -2719,16 +2801,6 @@ bool MapRef::supports_fast_array_resize() const {
return data()->AsMap()->supports_fast_array_resize();
}
-bool MapRef::IsMapOfTargetGlobalProxy() const {
- if (broker()->mode() == JSHeapBroker::kDisabled) {
- AllowHandleDereference allow_handle_dereference;
- AllowHandleAllocation handle_allocation;
- return object()->IsMapOfGlobalProxy(
- broker()->target_native_context().object());
- }
- return data()->AsMap()->IsMapOfTargetGlobalProxy();
-}
-
int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
@@ -2785,18 +2857,6 @@ OddballType MapRef::oddball_type() const {
return OddballType::kOther;
}
-ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const {
- if (broker()->mode() == JSHeapBroker::kDisabled) {
- AllowHandleAllocation handle_allocation;
- AllowHandleDereference handle_dereference;
- Handle<Object> value(object()->Get(slot)->cast<Object>(),
- broker()->isolate());
- return ObjectRef(broker(), value);
- }
- int i = FeedbackVector::GetIndex(slot);
- return ObjectRef(broker(), data()->AsFeedbackVector()->feedback().at(i));
-}
-
FeedbackCellRef FeedbackVectorRef::GetClosureFeedbackCell(int index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
@@ -2854,6 +2914,11 @@ bool AllocationSiteRef::IsFastLiteral() const {
return data()->AsAllocationSite()->IsFastLiteral();
}
+void AllocationSiteRef::SerializeBoilerplate() {
+ CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
+ data()->AsAllocationSite()->SerializeBoilerplate(broker());
+}
+
void JSObjectRef::SerializeElements() {
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsJSObject()->SerializeElements(broker());
@@ -2880,13 +2945,13 @@ void JSObjectRef::EnsureElementsTenured() {
CHECK(data()->AsJSObject()->cow_or_empty_elements_tenured());
}
-FieldIndex MapRef::GetFieldIndexFor(int descriptor_index) const {
+FieldIndex MapRef::GetFieldIndexFor(InternalIndex descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
return FieldIndex::ForDescriptor(*object(), descriptor_index);
}
DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
- return descriptors->contents().at(descriptor_index).field_index;
+ return descriptors->contents().at(descriptor_index.as_int()).field_index;
}
int MapRef::GetInObjectPropertyOffset(int i) const {
@@ -2897,16 +2962,17 @@ int MapRef::GetInObjectPropertyOffset(int i) const {
return (GetInObjectPropertiesStartInWords() + i) * kTaggedSize;
}
-PropertyDetails MapRef::GetPropertyDetails(int descriptor_index) const {
+PropertyDetails MapRef::GetPropertyDetails(
+ InternalIndex descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
return object()->instance_descriptors().GetDetails(descriptor_index);
}
DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
- return descriptors->contents().at(descriptor_index).details;
+ return descriptors->contents().at(descriptor_index.as_int()).details;
}
-NameRef MapRef::GetPropertyKey(int descriptor_index) const {
+NameRef MapRef::GetPropertyKey(InternalIndex descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
@@ -2916,7 +2982,8 @@ NameRef MapRef::GetPropertyKey(int descriptor_index) const {
broker()->isolate()));
}
DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
- return NameRef(broker(), descriptors->contents().at(descriptor_index).key);
+ return NameRef(broker(),
+ descriptors->contents().at(descriptor_index.as_int()).key);
}
bool MapRef::IsFixedCowArrayMap() const {
@@ -2926,10 +2993,10 @@ bool MapRef::IsFixedCowArrayMap() const {
}
bool MapRef::IsPrimitiveMap() const {
- return instance_type() <= LAST_PRIMITIVE_TYPE;
+ return instance_type() <= LAST_PRIMITIVE_HEAP_OBJECT_TYPE;
}
-MapRef MapRef::FindFieldOwner(int descriptor_index) const {
+MapRef MapRef::FindFieldOwner(InternalIndex descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
@@ -2939,11 +3006,12 @@ MapRef MapRef::FindFieldOwner(int descriptor_index) const {
return MapRef(broker(), owner);
}
DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
- return MapRef(broker(),
- descriptors->contents().at(descriptor_index).field_owner);
+ return MapRef(
+ broker(),
+ descriptors->contents().at(descriptor_index.as_int()).field_owner);
}
-ObjectRef MapRef::GetFieldType(int descriptor_index) const {
+ObjectRef MapRef::GetFieldType(InternalIndex descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
@@ -2953,18 +3021,21 @@ ObjectRef MapRef::GetFieldType(int descriptor_index) const {
return ObjectRef(broker(), field_type);
}
DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
- return ObjectRef(broker(),
- descriptors->contents().at(descriptor_index).field_type);
+ return ObjectRef(
+ broker(),
+ descriptors->contents().at(descriptor_index.as_int()).field_type);
}
-bool MapRef::IsUnboxedDoubleField(int descriptor_index) const {
+bool MapRef::IsUnboxedDoubleField(InternalIndex descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
return object()->IsUnboxedDoubleField(
FieldIndex::ForDescriptor(*object(), descriptor_index));
}
DescriptorArrayData* descriptors = data()->AsMap()->instance_descriptors();
- return descriptors->contents().at(descriptor_index).is_unboxed_double_field;
+ return descriptors->contents()
+ .at(descriptor_index.as_int())
+ .is_unboxed_double_field;
}
uint16_t StringRef::GetFirstChar() {
@@ -3074,11 +3145,6 @@ Smi BytecodeArrayRef::GetConstantAtIndexAsSmi(int index) const {
return data()->AsBytecodeArray()->GetConstantAtIndexAsSmi(index);
}
-bool BytecodeArrayRef::IsSerializedForCompilation() const {
- if (broker()->mode() == JSHeapBroker::kDisabled) return true;
- return data()->AsBytecodeArray()->IsSerializedForCompilation();
-}
-
void BytecodeArrayRef::SerializeForCompilation() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
data()->AsBytecodeArray()->SerializeForCompilation(broker());
@@ -3191,6 +3257,8 @@ BIMODAL_ACCESSOR(JSFunction, Object, prototype)
BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
BIMODAL_ACCESSOR(JSFunction, FeedbackVector, feedback_vector)
+BIMODAL_ACCESSOR_C(JSGlobalObject, bool, IsDetached)
+
BIMODAL_ACCESSOR_C(JSTypedArray, bool, is_on_heap)
BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length)
BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
@@ -3345,7 +3413,7 @@ BIMODAL_ACCESSOR_C(String, int, length)
BIMODAL_ACCESSOR(FeedbackCell, HeapObject, value)
-ObjectRef MapRef::GetStrongValue(int descriptor_index) const {
+ObjectRef MapRef::GetStrongValue(InternalIndex descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
return ObjectRef(broker(),
@@ -3376,12 +3444,12 @@ base::Optional<MapRef> MapRef::FindRootMap() const {
return base::nullopt;
}
-void* JSTypedArrayRef::external_pointer() const {
+void* JSTypedArrayRef::data_ptr() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
- return object()->external_pointer();
+ return object()->DataPtr();
}
- return data()->AsJSTypedArray()->external_pointer();
+ return data()->AsJSTypedArray()->data_ptr();
}
bool MapRef::IsInobjectSlackTrackingInProgress() const {
@@ -3774,12 +3842,37 @@ ObjectRef JSRegExpRef::source() const {
return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->source());
}
-Handle<Object> ObjectRef::object() const { return data_->object(); }
+void JSRegExpRef::SerializeAsRegExpBoilerplate() {
+ CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
+ JSObjectRef::data()->AsJSRegExp()->SerializeAsRegExpBoilerplate(broker());
+}
+Handle<Object> ObjectRef::object() const {
+#ifdef DEBUG
+ if (broker()->mode() == JSHeapBroker::kSerialized &&
+ data_->used_status == ObjectData::Usage::kUnused) {
+ data_->used_status = ObjectData::Usage::kOnlyIdentityUsed;
+ }
+#endif // DEBUG
+ return data_->object();
+}
+
+#ifdef DEBUG
#define DEF_OBJECT_GETTER(T) \
Handle<T> T##Ref::object() const { \
+ if (broker()->mode() == JSHeapBroker::kSerialized && \
+ data_->used_status == ObjectData::Usage::kUnused) { \
+ data_->used_status = ObjectData::Usage::kOnlyIdentityUsed; \
+ } \
return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
}
+#else
+#define DEF_OBJECT_GETTER(T) \
+ Handle<T> T##Ref::object() const { \
+ return Handle<T>(reinterpret_cast<Address*>(data_->object().address())); \
+ }
+#endif // DEBUG
+
HEAP_BROKER_OBJECT_LIST(DEF_OBJECT_GETTER)
#undef DEF_OBJECT_GETTER
@@ -3791,7 +3884,12 @@ ObjectData* ObjectRef::data() const {
CHECK_NE(data_->kind(), kSerializedHeapObject);
return data_;
case JSHeapBroker::kSerializing:
+ CHECK_NE(data_->kind(), kUnserializedHeapObject);
+ return data_;
case JSHeapBroker::kSerialized:
+#ifdef DEBUG
+ data_->used_status = ObjectData::Usage::kDataUsed;
+#endif // DEBUG
CHECK_NE(data_->kind(), kUnserializedHeapObject);
return data_;
case JSHeapBroker::kRetired:
@@ -3857,60 +3955,50 @@ bool JSFunctionRef::serialized() const {
return data()->AsJSFunction()->serialized();
}
-bool JSFunctionRef::IsSerializedForCompilation() const {
- if (broker()->mode() == JSHeapBroker::kDisabled) {
- return handle(object()->shared(), broker()->isolate())->HasBytecodeArray();
- }
-
- // We get a crash if we try to access the shared() getter without
- // checking for `serialized` first. Also it's possible to have a
- // JSFunctionRef without a feedback vector.
- return serialized() && has_feedback_vector() &&
- shared().IsSerializedForCompilation(feedback_vector());
-}
-
JSArrayRef SharedFunctionInfoRef::GetTemplateObject(
- ObjectRef description, FeedbackVectorRef vector, FeedbackSlot slot,
+ TemplateObjectDescriptionRef description, FeedbackSource const& source,
SerializationPolicy policy) {
- // Look in the feedback vector for the array. A Smi indicates that it's
- // not yet cached here.
- ObjectRef candidate = vector.get(slot);
- if (!candidate.IsSmi()) {
- return candidate.AsJSArray();
+ // First, see if we have processed feedback from the vector, respecting
+ // the serialization policy.
+ ProcessedFeedback const& feedback =
+ policy == SerializationPolicy::kSerializeIfNeeded
+ ? broker()->ProcessFeedbackForTemplateObject(source)
+ : broker()->GetFeedbackForTemplateObject(source);
+
+ if (!feedback.IsInsufficient()) {
+ return feedback.AsTemplateObject().value();
}
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
- Handle<TemplateObjectDescription> tod =
- Handle<TemplateObjectDescription>::cast(description.object());
Handle<JSArray> template_object =
TemplateObjectDescription::GetTemplateObject(
- broker()->isolate(), broker()->target_native_context().object(),
- tod, object(), slot.ToInt());
+ isolate(), broker()->target_native_context().object(),
+ description.object(), object(), source.slot.ToInt());
return JSArrayRef(broker(), template_object);
}
- JSArrayData* array = data()->AsSharedFunctionInfo()->GetTemplateObject(slot);
+ JSArrayData* array =
+ data()->AsSharedFunctionInfo()->GetTemplateObject(source.slot);
if (array != nullptr) return JSArrayRef(broker(), array);
CHECK_EQ(policy, SerializationPolicy::kSerializeIfNeeded);
CHECK(broker()->SerializingAllowed());
- Handle<TemplateObjectDescription> tod =
- Handle<TemplateObjectDescription>::cast(description.object());
Handle<JSArray> template_object =
TemplateObjectDescription::GetTemplateObject(
- broker()->isolate(), broker()->target_native_context().object(), tod,
- object(), slot.ToInt());
+ broker()->isolate(), broker()->target_native_context().object(),
+ description.object(), object(), source.slot.ToInt());
array = broker()->GetOrCreateData(template_object)->AsJSArray();
- data()->AsSharedFunctionInfo()->SetTemplateObject(slot, array);
+ data()->AsSharedFunctionInfo()->SetTemplateObject(source.slot, array);
return JSArrayRef(broker(), array);
}
void SharedFunctionInfoRef::SetSerializedForCompilation(
FeedbackVectorRef feedback) {
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
+ CHECK(HasBytecodeArray());
data()->AsSharedFunctionInfo()->SetSerializedForCompilation(broker(),
feedback);
}
@@ -3937,7 +4025,7 @@ SharedFunctionInfoRef::function_template_info() const {
bool SharedFunctionInfoRef::IsSerializedForCompilation(
FeedbackVectorRef feedback) const {
- if (broker()->mode() == JSHeapBroker::kDisabled) return true;
+ if (broker()->mode() == JSHeapBroker::kDisabled) return HasBytecodeArray();
return data()->AsSharedFunctionInfo()->IsSerializedForCompilation(feedback);
}
@@ -3953,19 +4041,19 @@ void MapRef::SerializeOwnDescriptors() {
data()->AsMap()->SerializeOwnDescriptors(broker());
}
-void MapRef::SerializeOwnDescriptor(int descriptor_index) {
+void MapRef::SerializeOwnDescriptor(InternalIndex descriptor_index) {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsMap()->SerializeOwnDescriptor(broker(), descriptor_index);
}
-bool MapRef::serialized_own_descriptor(int descriptor_index) const {
- CHECK_LT(descriptor_index, NumberOfOwnDescriptors());
+bool MapRef::serialized_own_descriptor(InternalIndex descriptor_index) const {
+ CHECK_LT(descriptor_index.as_int(), NumberOfOwnDescriptors());
if (broker()->mode() == JSHeapBroker::kDisabled) return true;
DescriptorArrayData* desc_array_data =
data()->AsMap()->instance_descriptors();
if (!desc_array_data) return false;
- return desc_array_data->contents().find(descriptor_index) !=
+ return desc_array_data->contents().find(descriptor_index.as_int()) !=
desc_array_data->contents().end();
}
@@ -4027,14 +4115,14 @@ void FunctionTemplateInfoRef::SerializeCallCode() {
data()->AsFunctionTemplateInfo()->SerializeCallCode(broker());
}
-base::Optional<PropertyCellRef> JSGlobalProxyRef::GetPropertyCell(
+base::Optional<PropertyCellRef> JSGlobalObjectRef::GetPropertyCell(
NameRef const& name, SerializationPolicy policy) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
return GetPropertyCellFromHeap(broker(), name.object());
}
PropertyCellData* property_cell_data =
- data()->AsJSGlobalProxy()->GetPropertyCell(broker(),
- name.data()->AsName(), policy);
+ data()->AsJSGlobalObject()->GetPropertyCell(
+ broker(), name.data()->AsName(), policy);
if (property_cell_data == nullptr) return base::nullopt;
return PropertyCellRef(broker(), property_cell_data);
}
@@ -4115,7 +4203,6 @@ GlobalAccessFeedback::GlobalAccessFeedback(PropertyCellRef cell,
GlobalAccessFeedback::GlobalAccessFeedback(FeedbackSlotKind slot_kind)
: ProcessedFeedback(kGlobalAccess, slot_kind),
- cell_or_context_(base::nullopt),
index_and_immutable_(0 /* doesn't matter */) {
DCHECK(IsGlobalICKind(slot_kind));
}
@@ -4265,6 +4352,7 @@ void JSHeapBroker::SetFeedback(FeedbackSource const& source,
}
bool JSHeapBroker::HasFeedback(FeedbackSource const& source) const {
+ DCHECK(source.IsValid());
return feedback_.find(source) != feedback_.end();
}
@@ -4315,7 +4403,6 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForPropertyAccess(
MapHandles maps;
nexus.ExtractMaps(&maps);
- DCHECK_NE(nexus.ic_state(), PREMONOMORPHIC);
if (!maps.empty()) {
maps = GetRelevantReceiverMaps(isolate(), maps);
if (maps.empty()) return *new (zone()) InsufficientFeedback(kind);
@@ -4424,6 +4511,47 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForInstanceOf(
return *new (zone()) InstanceOfFeedback(optional_constructor, nexus.kind());
}
+ProcessedFeedback const& JSHeapBroker::ReadFeedbackForArrayOrObjectLiteral(
+ FeedbackSource const& source) {
+ FeedbackNexus nexus(source.vector, source.slot);
+ HeapObject object;
+ if (nexus.IsUninitialized() || !nexus.GetFeedback()->GetHeapObject(&object)) {
+ return *new (zone()) InsufficientFeedback(nexus.kind());
+ }
+
+ AllocationSiteRef site(this, handle(object, isolate()));
+ if (site.IsFastLiteral()) {
+ site.SerializeBoilerplate();
+ }
+
+ return *new (zone()) LiteralFeedback(site, nexus.kind());
+}
+
+ProcessedFeedback const& JSHeapBroker::ReadFeedbackForRegExpLiteral(
+ FeedbackSource const& source) {
+ FeedbackNexus nexus(source.vector, source.slot);
+ HeapObject object;
+ if (nexus.IsUninitialized() || !nexus.GetFeedback()->GetHeapObject(&object)) {
+ return *new (zone()) InsufficientFeedback(nexus.kind());
+ }
+
+ JSRegExpRef regexp(this, handle(object, isolate()));
+ regexp.SerializeAsRegExpBoilerplate();
+ return *new (zone()) RegExpLiteralFeedback(regexp, nexus.kind());
+}
+
+ProcessedFeedback const& JSHeapBroker::ReadFeedbackForTemplateObject(
+ FeedbackSource const& source) {
+ FeedbackNexus nexus(source.vector, source.slot);
+ HeapObject object;
+ if (nexus.IsUninitialized() || !nexus.GetFeedback()->GetHeapObject(&object)) {
+ return *new (zone()) InsufficientFeedback(nexus.kind());
+ }
+
+ JSArrayRef array(this, handle(object, isolate()));
+ return *new (zone()) TemplateObjectFeedback(array, nexus.kind());
+}
+
ProcessedFeedback const& JSHeapBroker::ReadFeedbackForCall(
FeedbackSource const& source) {
FeedbackNexus nexus(source.vector, source.slot);
@@ -4495,6 +4623,50 @@ ProcessedFeedback const& JSHeapBroker::GetFeedbackForGlobalAccess(
: ProcessFeedbackForGlobalAccess(source);
}
+ProcessedFeedback const& JSHeapBroker::GetFeedbackForArrayOrObjectLiteral(
+ FeedbackSource const& source) {
+ return FLAG_concurrent_inlining
+ ? GetFeedback(source)
+ : ProcessFeedbackForArrayOrObjectLiteral(source);
+}
+
+ProcessedFeedback const& JSHeapBroker::GetFeedbackForRegExpLiteral(
+ FeedbackSource const& source) {
+ return FLAG_concurrent_inlining ? GetFeedback(source)
+ : ProcessFeedbackForRegExpLiteral(source);
+}
+
+ProcessedFeedback const& JSHeapBroker::GetFeedbackForTemplateObject(
+ FeedbackSource const& source) {
+ return FLAG_concurrent_inlining ? GetFeedback(source)
+ : ProcessFeedbackForTemplateObject(source);
+}
+
+ProcessedFeedback const& JSHeapBroker::ProcessFeedbackForArrayOrObjectLiteral(
+ FeedbackSource const& source) {
+ if (HasFeedback(source)) return GetFeedback(source);
+ ProcessedFeedback const& feedback =
+ ReadFeedbackForArrayOrObjectLiteral(source);
+ SetFeedback(source, &feedback);
+ return feedback;
+}
+
+ProcessedFeedback const& JSHeapBroker::ProcessFeedbackForRegExpLiteral(
+ FeedbackSource const& source) {
+ if (HasFeedback(source)) return GetFeedback(source);
+ ProcessedFeedback const& feedback = ReadFeedbackForRegExpLiteral(source);
+ SetFeedback(source, &feedback);
+ return feedback;
+}
+
+ProcessedFeedback const& JSHeapBroker::ProcessFeedbackForTemplateObject(
+ FeedbackSource const& source) {
+ if (HasFeedback(source)) return GetFeedback(source);
+ ProcessedFeedback const& feedback = ReadFeedbackForTemplateObject(source);
+ SetFeedback(source, &feedback);
+ return feedback;
+}
+
ProcessedFeedback const& JSHeapBroker::ProcessFeedbackForBinaryOperation(
FeedbackSource const& source) {
if (HasFeedback(source)) return GetFeedback(source);
@@ -4650,9 +4822,10 @@ void ElementAccessFeedback::AddGroup(TransitionGroup&& group) {
}
std::ostream& operator<<(std::ostream& os, const ObjectRef& ref) {
- if (ref.broker()->mode() == JSHeapBroker::kDisabled) {
- // If the broker is disabled we cannot be in a background thread so it's
- // safe to read the heap.
+ if (ref.broker()->mode() == JSHeapBroker::kDisabled ||
+ !FLAG_concurrent_recompilation) {
+ // We cannot be in a background thread so it's safe to read the heap.
+ AllowHandleDereference allow_handle_dereference;
return os << ref.data() << " {" << ref.object() << "}";
} else {
return os << ref.data();
@@ -4734,6 +4907,21 @@ NamedAccessFeedback const& ProcessedFeedback::AsNamedAccess() const {
return *static_cast<NamedAccessFeedback const*>(this);
}
+LiteralFeedback const& ProcessedFeedback::AsLiteral() const {
+ CHECK_EQ(kLiteral, kind());
+ return *static_cast<LiteralFeedback const*>(this);
+}
+
+RegExpLiteralFeedback const& ProcessedFeedback::AsRegExpLiteral() const {
+ CHECK_EQ(kRegExpLiteral, kind());
+ return *static_cast<RegExpLiteralFeedback const*>(this);
+}
+
+TemplateObjectFeedback const& ProcessedFeedback::AsTemplateObject() const {
+ CHECK_EQ(kTemplateObject, kind());
+ return *static_cast<TemplateObjectFeedback const*>(this);
+}
+
BytecodeAnalysis const& JSHeapBroker::GetBytecodeAnalysis(
Handle<BytecodeArray> bytecode_array, BailoutId osr_bailout_id,
bool analyze_liveness, SerializationPolicy policy) {