diff options
Diffstat (limited to 'deps/v8/src/compiler/js-heap-broker.cc')
-rw-r--r-- | deps/v8/src/compiler/js-heap-broker.cc | 1410 |
1 files changed, 880 insertions, 530 deletions
diff --git a/deps/v8/src/compiler/js-heap-broker.cc b/deps/v8/src/compiler/js-heap-broker.cc index 26243871657..949dca377d7 100644 --- a/deps/v8/src/compiler/js-heap-broker.cc +++ b/deps/v8/src/compiler/js-heap-broker.cc @@ -4,41 +4,528 @@ #include "src/compiler/js-heap-broker.h" -#include "src/compiler/compilation-dependencies.h" +#include "src/compiler/graph-reducer.h" #include "src/objects-inl.h" +#include "src/objects/js-array-inl.h" #include "src/objects/js-regexp-inl.h" #include "src/objects/module-inl.h" +#include "src/utils.h" namespace v8 { namespace internal { namespace compiler { -MapRef HeapObjectRef::map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), - handle(object<HeapObject>()->map(), broker()->isolate())); +#define FORWARD_DECL(Name) class Name##Data; +HEAP_BROKER_OBJECT_LIST(FORWARD_DECL) +#undef FORWARD_DECL + +// TODO(neis): It would be nice to share the serialized data for read-only +// objects. + +class ObjectData : public ZoneObject { + public: + static ObjectData* Serialize(JSHeapBroker* broker, Handle<Object> object); + + ObjectData(JSHeapBroker* broker_, Handle<Object> object_, bool is_smi_) + : broker(broker_), object(object_), is_smi(is_smi_) { + broker->AddData(object, this); + } + +#define DECLARE_IS_AND_AS(Name) \ + bool Is##Name() const; \ + Name##Data* As##Name(); + HEAP_BROKER_OBJECT_LIST(DECLARE_IS_AND_AS) +#undef DECLARE_IS_AND_AS + + JSHeapBroker* const broker; + Handle<Object> const object; + bool const is_smi; +}; + +// TODO(neis): Perhaps add a boolean that indicates whether serialization of an +// object has completed. That could be used to add safety checks. + +#define GET_OR_CREATE(name) \ + broker->GetOrCreateData(handle(object_->name(), broker->isolate())) + +class HeapObjectData : public ObjectData { + public: + static HeapObjectData* Serialize(JSHeapBroker* broker, + Handle<HeapObject> object); + + HeapObjectType const type; + MapData* const map; + + HeapObjectData(JSHeapBroker* broker_, Handle<HeapObject> object_, + HeapObjectType type_) + : ObjectData(broker_, object_, false), + type(type_), + map(GET_OR_CREATE(map)->AsMap()) { + CHECK(broker_->SerializingAllowed()); + } +}; + +class PropertyCellData : public HeapObjectData { + public: + PropertyCellData(JSHeapBroker* broker_, Handle<PropertyCell> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class JSObjectData : public HeapObjectData { + public: + JSObjectData(JSHeapBroker* broker_, Handle<JSObject> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class JSFunctionData : public JSObjectData { + public: + JSGlobalProxyData* const global_proxy; + MapData* const initial_map; // Can be nullptr. + bool const has_prototype; + ObjectData* const prototype; // Can be nullptr. + bool const PrototypeRequiresRuntimeLookup; + SharedFunctionInfoData* const shared; + + JSFunctionData(JSHeapBroker* broker_, Handle<JSFunction> object_, + HeapObjectType type_); +}; + +class JSRegExpData : public JSObjectData { + public: + JSRegExpData(JSHeapBroker* broker_, Handle<JSRegExp> object_, + HeapObjectType type_) + : JSObjectData(broker_, object_, type_) {} +}; + +class HeapNumberData : public HeapObjectData { + public: + HeapNumberData(JSHeapBroker* broker_, Handle<HeapNumber> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class MutableHeapNumberData : public HeapObjectData { + public: + MutableHeapNumberData(JSHeapBroker* broker_, + Handle<MutableHeapNumber> object_, HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class ContextData : public HeapObjectData { + public: + ContextData(JSHeapBroker* broker_, Handle<Context> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class NativeContextData : public ContextData { + public: +#define DECL_MEMBER(type, name) type##Data* const name; + BROKER_NATIVE_CONTEXT_FIELDS(DECL_MEMBER) +#undef DECL_MEMBER + + NativeContextData(JSHeapBroker* broker_, Handle<NativeContext> object_, + HeapObjectType type_) + : ContextData(broker_, object_, type_) +#define INIT_MEMBER(type, name) , name(GET_OR_CREATE(name)->As##type()) + BROKER_NATIVE_CONTEXT_FIELDS(INIT_MEMBER) +#undef INIT_MEMBER + { + } +}; + +class NameData : public HeapObjectData { + public: + NameData(JSHeapBroker* broker, Handle<Name> object, HeapObjectType type) + : HeapObjectData(broker, object, type) {} +}; + +class StringData : public NameData { + public: + StringData(JSHeapBroker* broker, Handle<String> object, HeapObjectType type) + : NameData(broker, object, type), + length(object->length()), + first_char(length > 0 ? object->Get(0) : 0) { + int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY; + if (length <= kMaxLengthForDoubleConversion) { + to_number = StringToDouble( + broker->isolate(), broker->isolate()->unicode_cache(), object, flags); + } + } + + int const length; + uint16_t const first_char; + base::Optional<double> to_number; + + private: + static constexpr int kMaxLengthForDoubleConversion = 23; +}; + +class InternalizedStringData : public StringData { + public: + InternalizedStringData(JSHeapBroker* broker, + Handle<InternalizedString> object, HeapObjectType type) + : StringData(broker, object, type) {} +}; + +namespace { + +bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth, + int* max_properties) { + DCHECK_GE(max_depth, 0); + DCHECK_GE(*max_properties, 0); + + // Make sure the boilerplate map is not deprecated. + if (!JSObject::TryMigrateInstance(boilerplate)) return false; + + // Check for too deep nesting. + if (max_depth == 0) return false; + + // Check the elements. + Isolate* const isolate = boilerplate->GetIsolate(); + Handle<FixedArrayBase> elements(boilerplate->elements(), isolate); + if (elements->length() > 0 && + elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) { + if (boilerplate->HasSmiOrObjectElements()) { + Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); + int length = elements->length(); + for (int i = 0; i < length; i++) { + if ((*max_properties)-- == 0) return false; + Handle<Object> value(fast_elements->get(i), isolate); + if (value->IsJSObject()) { + Handle<JSObject> value_object = Handle<JSObject>::cast(value); + if (!IsFastLiteralHelper(value_object, max_depth - 1, + max_properties)) { + return false; + } + } + } + } else if (boilerplate->HasDoubleElements()) { + if (elements->Size() > kMaxRegularHeapObjectSize) return false; + } else { + return false; + } + } + + // TODO(turbofan): Do we want to support out-of-object properties? + if (!(boilerplate->HasFastProperties() && + boilerplate->property_array()->length() == 0)) { + return false; + } + + // 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++) { + PropertyDetails details = descriptors->GetDetails(i); + if (details.location() != kField) continue; + DCHECK_EQ(kData, details.kind()); + if ((*max_properties)-- == 0) return false; + FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i); + if (boilerplate->IsUnboxedDoubleField(field_index)) continue; + Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate); + if (value->IsJSObject()) { + Handle<JSObject> value_object = Handle<JSObject>::cast(value); + if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) { + return false; + } + } + } + return true; } -double HeapNumberRef::value() const { - AllowHandleDereference allow_handle_dereference; - return object<HeapNumber>()->value(); +// Maximum depth and total number of elements and properties for literal +// graphs to be considered for fast deep-copying. The limit is chosen to +// match the maximum number of inobject properties, to ensure that the +// performance of using object literals is not worse than using constructor +// functions, see crbug.com/v8/6211 for details. +const int kMaxFastLiteralDepth = 3; +const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties; + +// Determines whether the given array or object literal boilerplate satisfies +// all limits to be considered for fast deep-copying and computes the total +// size of all objects that are part of the graph. +bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) { + int max_properties = kMaxFastLiteralProperties; + return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth, + &max_properties); } -double MutableHeapNumberRef::value() const { - AllowHandleDereference allow_handle_dereference; - return object<MutableHeapNumber>()->value(); +} // namespace + +class AllocationSiteData : public HeapObjectData { + public: + AllocationSiteData(JSHeapBroker* broker, Handle<AllocationSite> object_, + HeapObjectType type_) + : HeapObjectData(broker, object_, type_), + PointsToLiteral(object_->PointsToLiteral()), + GetPretenureMode(object_->GetPretenureMode()), + nested_site(GET_OR_CREATE(nested_site)) { + if (PointsToLiteral) { + if (IsInlinableFastLiteral( + handle(object_->boilerplate(), broker->isolate()))) { + boilerplate = GET_OR_CREATE(boilerplate)->AsJSObject(); + } + } else { + GetElementsKind = object_->GetElementsKind(); + CanInlineCall = object_->CanInlineCall(); + } + } + + bool const PointsToLiteral; + PretenureFlag const GetPretenureMode; + ObjectData* const nested_site; + JSObjectData* boilerplate = nullptr; + + // These are only valid if PointsToLiteral is false. + ElementsKind GetElementsKind = NO_ELEMENTS; + bool CanInlineCall = false; +}; + +// Only used in JSNativeContextSpecialization. +class ScriptContextTableData : public HeapObjectData { + public: + ScriptContextTableData(JSHeapBroker* broker_, + Handle<ScriptContextTable> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class MapData : public HeapObjectData { + public: + InstanceType const instance_type; + int const instance_size; + byte const bit_field; + byte const bit_field2; + uint32_t const bit_field3; + + MapData(JSHeapBroker* broker_, Handle<Map> object_, HeapObjectType type_); + + // Extra information. + void SerializeElementsKindGeneralizations(); + const ZoneVector<MapData*>& elements_kind_generalizations() { + return elements_kind_generalizations_; + } + + private: + ZoneVector<MapData*> elements_kind_generalizations_; +}; + +MapData::MapData(JSHeapBroker* broker_, Handle<Map> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_), + instance_type(object_->instance_type()), + instance_size(object_->instance_size()), + bit_field(object_->bit_field()), + bit_field2(object_->bit_field2()), + bit_field3(object_->bit_field3()), + elements_kind_generalizations_(broker->zone()) {} + +JSFunctionData::JSFunctionData(JSHeapBroker* broker_, + Handle<JSFunction> object_, HeapObjectType type_) + : JSObjectData(broker_, object_, type_), + global_proxy(GET_OR_CREATE(global_proxy)->AsJSGlobalProxy()), + initial_map(object_->has_prototype_slot() && object_->has_initial_map() + ? GET_OR_CREATE(initial_map)->AsMap() + : nullptr), + has_prototype(object_->has_prototype_slot() && object_->has_prototype()), + prototype(has_prototype ? GET_OR_CREATE(prototype) : nullptr), + PrototypeRequiresRuntimeLookup(object_->PrototypeRequiresRuntimeLookup()), + shared(GET_OR_CREATE(shared)->AsSharedFunctionInfo()) { + if (initial_map != nullptr && initial_map->instance_type == JS_ARRAY_TYPE) { + initial_map->SerializeElementsKindGeneralizations(); + } } -bool ObjectRef::IsSmi() const { - AllowHandleDereference allow_handle_dereference; - return object_->IsSmi(); +void MapData::SerializeElementsKindGeneralizations() { + broker->Trace("Computing ElementsKind generalizations of %p.\n", *object); + DCHECK_EQ(instance_type, JS_ARRAY_TYPE); + MapRef self(this); + ElementsKind from_kind = self.elements_kind(); + for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) { + ElementsKind to_kind = static_cast<ElementsKind>(i); + if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { + Handle<Map> target = + Map::AsElementsKind(broker->isolate(), self.object<Map>(), to_kind); + elements_kind_generalizations_.push_back( + broker->GetOrCreateData(target)->AsMap()); + } + } } -int ObjectRef::AsSmi() const { return object<Smi>()->value(); } +class FeedbackVectorData : public HeapObjectData { + public: + const ZoneVector<ObjectData*>& feedback() { return feedback_; } + + FeedbackVectorData(JSHeapBroker* broker_, Handle<FeedbackVector> object_, + HeapObjectType type_); + + private: + ZoneVector<ObjectData*> feedback_; +}; + +FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker_, + Handle<FeedbackVector> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_), feedback_(broker_->zone()) { + feedback_.reserve(object_->length()); + for (int i = 0; i < object_->length(); ++i) { + MaybeObject* value = object_->get(i); + feedback_.push_back(value->IsObject() + ? broker->GetOrCreateData( + handle(value->ToObject(), broker->isolate())) + : nullptr); + } + DCHECK_EQ(object_->length(), feedback_.size()); +} + +class FixedArrayBaseData : public HeapObjectData { + public: + int const length; + + FixedArrayBaseData(JSHeapBroker* broker_, Handle<FixedArrayBase> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_), length(object_->length()) {} +}; + +class FixedArrayData : public FixedArrayBaseData { + public: + FixedArrayData(JSHeapBroker* broker_, Handle<FixedArray> object_, + HeapObjectType type_) + : FixedArrayBaseData(broker_, object_, type_) {} +}; + +class FixedDoubleArrayData : public FixedArrayBaseData { + public: + FixedDoubleArrayData(JSHeapBroker* broker_, Handle<FixedDoubleArray> object_, + HeapObjectType type_) + : FixedArrayBaseData(broker_, object_, type_) {} +}; + +class BytecodeArrayData : public FixedArrayBaseData { + public: + int const register_count; + + BytecodeArrayData(JSHeapBroker* broker_, Handle<BytecodeArray> object_, + HeapObjectType type_) + : FixedArrayBaseData(broker_, object_, type_), + register_count(object_->register_count()) {} +}; + +class JSArrayData : public JSObjectData { + public: + JSArrayData(JSHeapBroker* broker_, Handle<JSArray> object_, + HeapObjectType type_) + : JSObjectData(broker_, object_, type_) {} +}; + +class ScopeInfoData : public HeapObjectData { + public: + ScopeInfoData(JSHeapBroker* broker_, Handle<ScopeInfo> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class SharedFunctionInfoData : public HeapObjectData { + public: + int const builtin_id; + BytecodeArrayData* const GetBytecodeArray; // Can be nullptr. +#define DECL_MEMBER(type, name) type const name; + BROKER_SFI_FIELDS(DECL_MEMBER) +#undef DECL_MEMBER + + SharedFunctionInfoData(JSHeapBroker* broker_, + Handle<SharedFunctionInfo> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_), + builtin_id(object_->HasBuiltinId() ? object_->builtin_id() + : Builtins::kNoBuiltinId), + GetBytecodeArray( + object_->HasBytecodeArray() + ? GET_OR_CREATE(GetBytecodeArray)->AsBytecodeArray() + : nullptr) +#define INIT_MEMBER(type, name) , name(object_->name()) + BROKER_SFI_FIELDS(INIT_MEMBER) +#undef INIT_MEMBER + { + DCHECK_EQ(HasBuiltinId, builtin_id != Builtins::kNoBuiltinId); + DCHECK_EQ(HasBytecodeArray, GetBytecodeArray != nullptr); + } +}; + +class ModuleData : public HeapObjectData { + public: + ModuleData(JSHeapBroker* broker_, Handle<Module> object_, + HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class CellData : public HeapObjectData { + public: + CellData(JSHeapBroker* broker_, Handle<Cell> object_, HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +class JSGlobalProxyData : public JSObjectData { + public: + JSGlobalProxyData(JSHeapBroker* broker_, Handle<JSGlobalProxy> object_, + HeapObjectType type_) + : JSObjectData(broker_, object_, type_) {} +}; + +class CodeData : public HeapObjectData { + public: + CodeData(JSHeapBroker* broker_, Handle<Code> object_, HeapObjectType type_) + : HeapObjectData(broker_, object_, type_) {} +}; + +#define DEFINE_IS_AND_AS(Name) \ + bool ObjectData::Is##Name() const { \ + if (broker->mode() == JSHeapBroker::kDisabled) { \ + AllowHandleDereference allow_handle_dereference; \ + return object->Is##Name(); \ + } \ + if (is_smi) return false; \ + InstanceType instance_type = \ + static_cast<const HeapObjectData*>(this)->type.instance_type(); \ + return InstanceTypeChecker::Is##Name(instance_type); \ + } \ + Name##Data* ObjectData::As##Name() { \ + CHECK_NE(broker->mode(), JSHeapBroker::kDisabled); \ + CHECK(Is##Name()); \ + return static_cast<Name##Data*>(this); \ + } +HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS) +#undef DEFINE_IS_AND_AS + +ObjectData* ObjectData::Serialize(JSHeapBroker* broker, Handle<Object> object) { + CHECK(broker->SerializingAllowed()); + return object->IsSmi() ? new (broker->zone()) ObjectData(broker, object, true) + : HeapObjectData::Serialize( + broker, Handle<HeapObject>::cast(object)); +} + +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); \ + } + HEAP_BROKER_OBJECT_LIST(RETURN_CREATE_DATA_IF_MATCH) +#undef RETURN_CREATE_DATA_IF_MATCH + UNREACHABLE(); +} bool ObjectRef::equals(const ObjectRef& other) const { - return object<Object>().equals(other.object<Object>()); + return data_ == other.data_; } StringRef ObjectRef::TypeOf() const { @@ -48,6 +535,8 @@ StringRef ObjectRef::TypeOf() const { Object::TypeOf(broker()->isolate(), object<Object>())); } +Isolate* ObjectRef::isolate() const { return broker()->isolate(); } + base::Optional<ContextRef> ContextRef::previous() const { AllowHandleAllocation handle_allocation; AllowHandleDereference handle_dereference; @@ -63,7 +552,84 @@ ObjectRef ContextRef::get(int index) const { return ObjectRef(broker(), value); } -JSHeapBroker::JSHeapBroker(Isolate* isolate) : isolate_(isolate) {} +JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* zone) + : isolate_(isolate), + zone_(zone), + refs_(zone), + mode_(FLAG_concurrent_compiler_frontend ? kSerializing : kDisabled) { + Trace("%s", "Constructing heap broker.\n"); +} + +void JSHeapBroker::Trace(const char* format, ...) const { + if (FLAG_trace_heap_broker) { + PrintF("[%p] ", this); + va_list arguments; + va_start(arguments, format); + base::OS::VPrint(format, arguments); + va_end(arguments); + } +} + +bool JSHeapBroker::SerializingAllowed() const { + return mode() == kSerializing || + (!FLAG_strict_heap_broker && mode() == kSerialized); +} + +void JSHeapBroker::SerializeStandardObjects() { + Trace("Serializing standard objects.\n"); + + Builtins* const b = isolate()->builtins(); + Factory* const f = isolate()->factory(); + + // Stuff used by JSGraph: + GetOrCreateData(f->empty_fixed_array()); + + // Stuff used by JSCreateLowering: + GetOrCreateData(f->block_context_map()); + GetOrCreateData(f->catch_context_map()); + GetOrCreateData(f->eval_context_map()); + GetOrCreateData(f->fixed_array_map()); + GetOrCreateData(f->fixed_double_array_map()); + GetOrCreateData(f->function_context_map()); + GetOrCreateData(f->many_closures_cell_map()); + GetOrCreateData(f->mutable_heap_number_map()); + GetOrCreateData(f->name_dictionary_map()); + GetOrCreateData(f->one_pointer_filler_map()); + GetOrCreateData(f->sloppy_arguments_elements_map()); + GetOrCreateData(f->with_context_map()); + + // Stuff used by TypedOptimization: + // Strings produced by typeof: + GetOrCreateData(f->boolean_string()); + GetOrCreateData(f->number_string()); + GetOrCreateData(f->string_string()); + GetOrCreateData(f->bigint_string()); + GetOrCreateData(f->symbol_string()); + GetOrCreateData(f->undefined_string()); + GetOrCreateData(f->object_string()); + GetOrCreateData(f->function_string()); + + // Stuff used by JSTypedLowering: + GetOrCreateData(f->length_string()); + Builtins::Name builtins[] = { + Builtins::kArgumentsAdaptorTrampoline, + Builtins::kCallFunctionForwardVarargs, + Builtins::kStringAdd_CheckNone_NotTenured, + Builtins::kStringAdd_CheckNone_Tenured, + Builtins::kStringAdd_ConvertLeft_NotTenured, + Builtins::kStringAdd_ConvertRight_NotTenured, + }; + for (auto id : builtins) { + GetOrCreateData(b->builtin_handle(id)); + } + for (int32_t id = 0; id < Builtins::builtin_count; ++id) { + if (Builtins::KindOf(id) == Builtins::TFJ) { + GetOrCreateData(b->builtin_handle(id)); + } + } + + Trace("Finished serializing standard objects.\n"); +} HeapObjectType JSHeapBroker::HeapObjectTypeFromMap(Map* map) const { AllowHandleDereference allow_handle_dereference; @@ -95,28 +661,58 @@ HeapObjectType JSHeapBroker::HeapObjectTypeFromMap(Map* map) const { return HeapObjectType(map->instance_type(), flags, oddball_type); } -// static -base::Optional<int> JSHeapBroker::TryGetSmi(Handle<Object> object) { - AllowHandleDereference allow_handle_dereference; - if (!object->IsSmi()) return base::Optional<int>(); - return Smi::cast(*object)->value(); +ObjectData* JSHeapBroker::GetData(Handle<Object> object) const { + auto it = refs_.find(object.address()); + return it != refs_.end() ? it->second : nullptr; +} + +ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) { + CHECK(SerializingAllowed()); + ObjectData* data = GetData(object); + if (data == nullptr) { + // TODO(neis): Remove these Allow* once we serialize everything upfront. + AllowHandleAllocation handle_allocation; + AllowHandleDereference handle_dereference; + data = ObjectData::Serialize(this, object); + } + CHECK_NOT_NULL(data); + return data; } -#define DEFINE_IS_AND_AS(Name) \ - bool ObjectRef::Is##Name() const { \ - AllowHandleDereference allow_handle_dereference; \ - return object<Object>()->Is##Name(); \ - } \ - Name##Ref ObjectRef::As##Name() const { \ - DCHECK(Is##Name()); \ - return Name##Ref(broker(), object<HeapObject>()); \ +void JSHeapBroker::AddData(Handle<Object> object, ObjectData* data) { + Trace("Creating data %p for handle %" V8PRIuPTR " (", data, object.address()); + if (FLAG_trace_heap_broker) { + object->ShortPrint(); + PrintF(")\n"); + } + CHECK_NOT_NULL(isolate()->handle_scope_data()->canonical_scope); + CHECK(refs_.insert({object.address(), data}).second); +} + +#define DEFINE_IS_AND_AS(Name) \ + bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \ + Name##Ref ObjectRef::As##Name() const { \ + DCHECK(Is##Name()); \ + return Name##Ref(data()); \ } HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS) #undef DEFINE_IS_AND_AS +bool ObjectRef::IsSmi() const { return data()->is_smi; } + +int ObjectRef::AsSmi() const { + DCHECK(IsSmi()); + // Handle-dereference is always allowed for Handle<Smi>. + return object<Smi>()->value(); +} + HeapObjectType HeapObjectRef::type() const { - AllowHandleDereference allow_handle_dereference; - return broker()->HeapObjectTypeFromMap(object<HeapObject>()->map()); + if (broker()->mode() == JSHeapBroker::kDisabled) { + AllowHandleDereference allow_handle_dereference; + return broker()->HeapObjectTypeFromMap(object<HeapObject>()->map()); + } else { + return data()->AsHeapObject()->type; + } } base::Optional<MapRef> HeapObjectRef::TryGetObjectCreateMap() const { @@ -131,75 +727,31 @@ base::Optional<MapRef> HeapObjectRef::TryGetObjectCreateMap() const { } } -bool HeapObjectRef::IsSeqString() const { - AllowHandleDereference allow_handle_dereference; - return object<HeapObject>()->IsSeqString(); -} - -bool HeapObjectRef::IsExternalString() const { - AllowHandleDereference allow_handle_dereference; - return object<HeapObject>()->IsExternalString(); -} - -bool JSFunctionRef::HasBuiltinFunctionId() const { - AllowHandleDereference allow_handle_dereference; - return object<JSFunction>()->shared()->HasBuiltinFunctionId(); -} - -BuiltinFunctionId JSFunctionRef::GetBuiltinFunctionId() const { - AllowHandleDereference allow_handle_dereference; - return object<JSFunction>()->shared()->builtin_function_id(); -} - -bool JSFunctionRef::IsConstructor() const { - AllowHandleDereference allow_handle_dereference; - return object<JSFunction>()->IsConstructor(); -} - -void JSFunctionRef::EnsureHasInitialMap() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - AllowHeapAllocation heap_allocation; - // TODO(jarin) Eventually, we will prepare initial maps for resumable - // functions (i.e., generators). - DCHECK(IsResumableFunction(object<JSFunction>()->shared()->kind())); - JSFunction::EnsureHasInitialMap(object<JSFunction>()); -} - -SlackTrackingResult JSFunctionRef::FinishSlackTracking() const { - AllowHandleDereference allow_handle_dereference; - AllowHandleAllocation handle_allocation; - object<JSFunction>()->CompleteInobjectSlackTrackingIfActive(); - int instance_size = object<JSFunction>()->initial_map()->instance_size(); - int inobject_property_count = - object<JSFunction>()->initial_map()->GetInObjectProperties(); - return SlackTrackingResult(instance_size, inobject_property_count); -} - -bool JSFunctionRef::has_initial_map() const { - AllowHandleDereference allow_handle_dereference; - return object<JSFunction>()->has_initial_map(); +base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const { + if (broker()->mode() == JSHeapBroker::kDisabled) { + AllowHandleAllocation handle_allocation; + AllowHeapAllocation heap_allocation; + AllowHandleDereference allow_handle_dereference; + return MapRef(broker(), Map::AsElementsKind(broker()->isolate(), + object<Map>(), kind)); + } else { + if (kind == elements_kind()) return *this; + const ZoneVector<MapData*>& elements_kind_generalizations = + data()->AsMap()->elements_kind_generalizations(); + for (auto data : elements_kind_generalizations) { + MapRef map(data); + if (map.elements_kind() == kind) return map; + } + return base::Optional<MapRef>(); + } } -MapRef JSFunctionRef::initial_map() const { - AllowHandleAllocation handle_allocation; +int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const { AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<JSFunction>()->initial_map(), - broker()->isolate())); -} - -SharedFunctionInfoRef JSFunctionRef::shared() const { AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return SharedFunctionInfoRef( - broker(), handle(object<JSFunction>()->shared(), broker()->isolate())); -} -JSGlobalProxyRef JSFunctionRef::global_proxy() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return JSGlobalProxyRef(broker(), handle(object<JSFunction>()->global_proxy(), - broker()->isolate())); + return object<JSFunction>()->ComputeInstanceSizeWithMinSlack( + broker()->isolate()); } base::Optional<ScriptContextTableRef::LookupResult> @@ -221,50 +773,20 @@ ScriptContextTableRef::lookup(const NameRef& name) const { return result; } -ScriptContextTableRef NativeContextRef::script_context_table() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference handle_dereference; - return ScriptContextTableRef( - broker(), - handle(object<Context>()->script_context_table(), broker()->isolate())); -} - OddballType ObjectRef::oddball_type() const { return IsSmi() ? OddballType::kNone : AsHeapObject().type().oddball_type(); } ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference handle_dereference; - Handle<Object> value(object<FeedbackVector>()->Get(slot)->ToObject(), - broker()->isolate()); - return ObjectRef(broker(), value); -} - -JSObjectRef AllocationSiteRef::boilerplate() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference handle_dereference; - Handle<JSObject> value(object<AllocationSite>()->boilerplate(), + if (broker()->mode() == JSHeapBroker::kDisabled) { + AllowHandleAllocation handle_allocation; + AllowHandleDereference handle_dereference; + Handle<Object> value(object<FeedbackVector>()->Get(slot)->ToObject(), broker()->isolate()); - return JSObjectRef(broker(), value); -} - -ObjectRef AllocationSiteRef::nested_site() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference handle_dereference; - Handle<Object> obj(object<AllocationSite>()->nested_site(), - broker()->isolate()); - return ObjectRef(broker(), obj); -} - -bool AllocationSiteRef::PointsToLiteral() const { - AllowHandleDereference handle_dereference; - return object<AllocationSite>()->PointsToLiteral(); -} - -ElementsKind AllocationSiteRef::GetElementsKind() const { - AllowHandleDereference handle_dereference; - return object<AllocationSite>()->GetElementsKind(); + return ObjectRef(broker(), value); + } + int i = FeedbackVector::GetIndex(slot); + return ObjectRef(data()->AsFeedbackVector()->feedback().at(i)); } bool JSObjectRef::IsUnboxedDoubleField(FieldIndex index) const { @@ -285,114 +807,18 @@ ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const { broker()->isolate())); } -ElementsKind JSObjectRef::GetElementsKind() { - AllowHandleDereference handle_dereference; - return object<JSObject>()->GetElementsKind(); -} - -FixedArrayBaseRef JSObjectRef::elements() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference handle_dereference; - return FixedArrayBaseRef( - broker(), handle(object<JSObject>()->elements(), broker()->isolate())); -} - -namespace { - -// Determines whether the given array or object literal boilerplate satisfies -// all limits to be considered for fast deep-copying and computes the total -// size of all objects that are part of the graph. -bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth, - int* max_properties) { - DCHECK_GE(max_depth, 0); - DCHECK_GE(*max_properties, 0); - - // Make sure the boilerplate map is not deprecated. - if (!JSObject::TryMigrateInstance(boilerplate)) return false; - - // Check for too deep nesting. - if (max_depth == 0) return false; - - // Check the elements. - Isolate* const isolate = boilerplate->GetIsolate(); - Handle<FixedArrayBase> elements(boilerplate->elements(), isolate); - if (elements->length() > 0 && - elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) { - if (boilerplate->HasSmiOrObjectElements()) { - Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); - int length = elements->length(); - for (int i = 0; i < length; i++) { - if ((*max_properties)-- == 0) return false; - Handle<Object> value(fast_elements->get(i), isolate); - if (value->IsJSObject()) { - Handle<JSObject> value_object = Handle<JSObject>::cast(value); - if (!IsFastLiteralHelper(value_object, max_depth - 1, - max_properties)) { - return false; - } - } - } - } else if (boilerplate->HasDoubleElements()) { - if (elements->Size() > kMaxRegularHeapObjectSize) return false; - } else { - return false; - } - } - - // TODO(turbofan): Do we want to support out-of-object properties? - if (!(boilerplate->HasFastProperties() && - boilerplate->property_array()->length() == 0)) { - return false; - } - - // 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++) { - PropertyDetails details = descriptors->GetDetails(i); - if (details.location() != kField) continue; - DCHECK_EQ(kData, details.kind()); - if ((*max_properties)-- == 0) return false; - FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i); - if (boilerplate->IsUnboxedDoubleField(field_index)) continue; - Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate); - if (value->IsJSObject()) { - Handle<JSObject> value_object = Handle<JSObject>::cast(value); - if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) { - return false; - } - } - } - return true; -} - -} // namespace - -// Maximum depth and total number of elements and properties for literal -// graphs to be considered for fast deep-copying. The limit is chosen to -// match the maximum number of inobject properties, to ensure that the -// performance of using object literals is not worse than using constructor -// functions, see crbug.com/v8/6211 for details. -const int kMaxFastLiteralDepth = 3; -const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties; -// Determines whether the given array or object literal boilerplate satisfies -// all limits to be considered for fast deep-copying and computes the total -// size of all objects that are part of the graph. bool AllocationSiteRef::IsFastLiteral() const { - AllowHandleAllocation allow_handle_allocation; - AllowHandleDereference allow_handle_dereference; - int max_properties = kMaxFastLiteralProperties; - Handle<JSObject> boilerplate(object<AllocationSite>()->boilerplate(), - broker()->isolate()); - return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth, - &max_properties); -} - -PretenureFlag AllocationSiteRef::GetPretenureMode() const { - AllowHandleDereference allow_handle_dereference; - return object<AllocationSite>()->GetPretenureMode(); + if (broker()->mode() == JSHeapBroker::kDisabled) { + AllowHeapAllocation + allow_heap_allocation; // This is needed for TryMigrateInstance. + AllowHandleAllocation allow_handle_allocation; + AllowHandleDereference allow_handle_dereference; + return IsInlinableFastLiteral( + handle(object<AllocationSite>()->boilerplate(), broker()->isolate())); + } else { + return data()->AsAllocationSite()->boilerplate != nullptr; + } } void JSObjectRef::EnsureElementsTenured() { @@ -400,43 +826,20 @@ void JSObjectRef::EnsureElementsTenured() { // the compilation job starts. AllowHandleAllocation allow_handle_allocation; AllowHandleDereference allow_handle_dereference; + AllowHeapAllocation allow_heap_allocation; + Handle<FixedArrayBase> object_elements = elements().object<FixedArrayBase>(); if (Heap::InNewSpace(*object_elements)) { // If we would like to pretenure a fixed cow array, we must ensure that // the array is already in old space, otherwise we'll create too many // old-to-new-space pointers (overflowing the store buffer). - object_elements = Handle<FixedArrayBase>( + object_elements = broker()->isolate()->factory()->CopyAndTenureFixedCOWArray( - Handle<FixedArray>::cast(object_elements))); + Handle<FixedArray>::cast(object_elements)); object<JSObject>()->set_elements(*object_elements); } } -ElementsKind MapRef::elements_kind() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->elements_kind(); -} - -bool MapRef::is_deprecated() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->is_deprecated(); -} - -bool MapRef::CanBeDeprecated() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->CanBeDeprecated(); -} - -int MapRef::GetInObjectProperties() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->GetInObjectProperties(); -} - -int MapRef::NumberOfOwnDescriptors() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->NumberOfOwnDescriptors(); -} - FieldIndex MapRef::GetFieldIndexFor(int i) const { AllowHandleDereference allow_handle_dereference; return FieldIndex::ForDescriptor(*object<Map>(), i); @@ -447,28 +850,6 @@ int MapRef::GetInObjectPropertyOffset(int i) const { return object<Map>()->GetInObjectPropertyOffset(i); } -bool MapRef::is_dictionary_map() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->is_dictionary_map(); -} - -ObjectRef MapRef::constructor_or_backpointer() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef(broker(), handle(object<Map>()->constructor_or_backpointer(), - broker()->isolate())); -} - -int MapRef::instance_size() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->instance_size(); -} - -InstanceType MapRef::instance_type() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->instance_type(); -} - PropertyDetails MapRef::GetPropertyDetails(int i) const { AllowHandleDereference allow_handle_dereference; return object<Map>()->instance_descriptors()->GetDetails(i); @@ -482,37 +863,12 @@ NameRef MapRef::GetPropertyKey(int i) const { broker()->isolate())); } -bool MapRef::IsJSArrayMap() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->IsJSArrayMap(); -} - -bool MapRef::IsInobjectSlackTrackingInProgress() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->IsInobjectSlackTrackingInProgress(); -} - bool MapRef::IsFixedCowArrayMap() const { AllowHandleDereference allow_handle_dereference; return *object<Map>() == ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map(); } -bool MapRef::has_prototype_slot() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->has_prototype_slot(); -} - -bool MapRef::is_stable() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->is_stable(); -} - -bool MapRef::CanTransition() const { - AllowHandleDereference allow_handle_dereference; - return object<Map>()->CanTransition(); -} - MapRef MapRef::FindFieldOwner(int descriptor) const { AllowHandleAllocation handle_allocation; AllowHandleDereference allow_handle_dereference; @@ -522,86 +878,36 @@ MapRef MapRef::FindFieldOwner(int descriptor) const { return MapRef(broker(), owner); } -FieldTypeRef MapRef::GetFieldType(int descriptor) const { +ObjectRef MapRef::GetFieldType(int descriptor) const { AllowHandleAllocation handle_allocation; AllowHandleDereference allow_handle_dereference; Handle<FieldType> field_type( object<Map>()->instance_descriptors()->GetFieldType(descriptor), broker()->isolate()); - return FieldTypeRef(broker(), field_type); -} - -ElementsKind JSArrayRef::GetElementsKind() const { - AllowHandleDereference allow_handle_dereference; - return object<JSArray>()->GetElementsKind(); -} - -ObjectRef JSArrayRef::length() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef(broker(), - handle(object<JSArray>()->length(), broker()->isolate())); -} - -int StringRef::length() const { - AllowHandleDereference allow_handle_dereference; - return object<String>()->length(); + return ObjectRef(broker(), field_type); } uint16_t StringRef::GetFirstChar() { - AllowHandleDereference allow_handle_dereference; - return object<String>()->Get(0); -} - -double StringRef::ToNumber() { - AllowHandleDereference allow_handle_dereference; - AllowHandleAllocation allow_handle_allocation; - AllowHeapAllocation allow_heap_allocation; - int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY; - return StringToDouble(broker()->isolate(), - broker()->isolate()->unicode_cache(), object<String>(), - flags); -} - -ObjectRef JSRegExpRef::raw_properties_or_hash() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef(broker(), - handle(object<JSRegExp>()->raw_properties_or_hash(), - broker()->isolate())); -} - -ObjectRef JSRegExpRef::data() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef(broker(), - handle(object<JSRegExp>()->data(), broker()->isolate())); -} - -ObjectRef JSRegExpRef::source() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef(broker(), - handle(object<JSRegExp>()->source(), broker()->isolate())); -} - -ObjectRef JSRegExpRef::flags() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef(broker(), - handle(object<JSRegExp>()->flags(), broker()->isolate())); -} - -ObjectRef JSRegExpRef::last_index() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef( - broker(), handle(object<JSRegExp>()->last_index(), broker()->isolate())); + if (broker()->mode() == JSHeapBroker::kDisabled) { + AllowHandleDereference allow_handle_dereference; + return object<String>()->Get(0); + } else { + return data()->AsString()->first_char; + } } -int FixedArrayBaseRef::length() const { - AllowHandleDereference allow_handle_dereference; - return object<FixedArrayBase>()->length(); +base::Optional<double> StringRef::ToNumber() { + if (broker()->mode() == JSHeapBroker::kDisabled) { + AllowHandleDereference allow_handle_dereference; + AllowHandleAllocation allow_handle_allocation; + AllowHeapAllocation allow_heap_allocation; + int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY; + return StringToDouble(broker()->isolate(), + broker()->isolate()->unicode_cache(), + object<String>(), flags); + } else { + return data()->AsString()->to_number; + } } bool FixedArrayRef::is_the_hole(int i) const { @@ -626,166 +932,139 @@ double FixedDoubleArrayRef::get_scalar(int i) const { return object<FixedDoubleArray>()->get_scalar(i); } -int ScopeInfoRef::ContextLength() const { - AllowHandleDereference allow_handle_dereference; - return object<ScopeInfo>()->ContextLength(); -} +#define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \ + if (broker()->mode() == JSHeapBroker::kDisabled) { \ + AllowHandleAllocation handle_allocation; \ + AllowHandleDereference allow_handle_dereference; \ + return object<holder>()->name(); \ + } -int SharedFunctionInfoRef::internal_formal_parameter_count() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->internal_formal_parameter_count(); -} +// Macros for definining a const getter that, depending on the broker mode, +// either looks into the handle or into the serialized data. The first one is +// used for the rare case of a XYZRef class that does not have a corresponding +// XYZ class in objects.h. The second one is used otherwise. +#define BIMODAL_ACCESSOR(holder, result, name) \ + result##Ref holder##Ref::name() const { \ + if (broker()->mode() == JSHeapBroker::kDisabled) { \ + AllowHandleAllocation handle_allocation; \ + AllowHandleDereference allow_handle_dereference; \ + return result##Ref( \ + broker(), handle(object<holder>()->name(), broker()->isolate())); \ + } else { \ + return result##Ref(data()->As##holder()->name); \ + } \ + } -int SharedFunctionInfoRef::function_map_index() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->function_map_index(); -} +// Like HANDLE_ACCESSOR except that the result type is not an XYZRef. +#define BIMODAL_ACCESSOR_C(holder, result, name) \ + result holder##Ref::name() const { \ + IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \ + return data()->As##holder()->name; \ + } -bool SharedFunctionInfoRef::has_duplicate_parameters() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->has_duplicate_parameters(); -} +// Like HANDLE_ACCESSOR_C but for BitFields. +#define BIMODAL_ACCESSOR_B(holder, field, name, BitField) \ + typename BitField::FieldType holder##Ref::name() const { \ + IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \ + return BitField::decode(data()->As##holder()->field); \ + } -FunctionKind SharedFunctionInfoRef::kind() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->kind(); -} +// Macros for definining a const getter that always looks into the handle. +// (These will go away once we serialize everything.) The first one is used for +// the rare case of a XYZRef class that does not have a corresponding XYZ class +// in objects.h. The second one is used otherwise. +#define HANDLE_ACCESSOR(holder, result, name) \ + result##Ref holder##Ref::name() const { \ + AllowHandleAllocation handle_allocation; \ + AllowHandleDereference allow_handle_dereference; \ + return result##Ref(broker(), \ + handle(object<holder>()->name(), broker()->isolate())); \ + } -LanguageMode SharedFunctionInfoRef::language_mode() { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->language_mode(); -} +// Like HANDLE_ACCESSOR except that the result type is not an XYZRef. +#define HANDLE_ACCESSOR_C(holder, result, name) \ + result holder##Ref::name() const { \ + AllowHandleAllocation handle_allocation; \ + AllowHandleDereference allow_handle_dereference; \ + return object<holder>()->name(); \ + } -bool SharedFunctionInfoRef::native() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->native(); -} +BIMODAL_ACCESSOR(AllocationSite, Object, nested_site) +BIMODAL_ACCESSOR_C(AllocationSite, bool, CanInlineCall) +BIMODAL_ACCESSOR_C(AllocationSite, bool, PointsToLiteral) +BIMODAL_ACCESSOR_C(AllocationSite, ElementsKind, GetElementsKind) +BIMODAL_ACCESSOR_C(AllocationSite, PretenureFlag, GetPretenureMode) -bool SharedFunctionInfoRef::HasBreakInfo() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->HasBreakInfo(); -} +BIMODAL_ACCESSOR_C(BytecodeArray, int, register_count) -bool SharedFunctionInfoRef::HasBuiltinId() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->HasBuiltinId(); -} +BIMODAL_ACCESSOR_C(FixedArrayBase, int, length) -int SharedFunctionInfoRef::builtin_id() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->builtin_id(); -} +BIMODAL_ACCESSOR(HeapObject, Map, map) +HANDLE_ACCESSOR_C(HeapObject, bool, IsExternalString) +HANDLE_ACCESSOR_C(HeapObject, bool, IsSeqString) -bool SharedFunctionInfoRef::construct_as_builtin() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->construct_as_builtin(); -} +HANDLE_ACCESSOR_C(HeapNumber, double, value) -bool SharedFunctionInfoRef::HasBytecodeArray() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->HasBytecodeArray(); -} +HANDLE_ACCESSOR(JSArray, Object, length) -int SharedFunctionInfoRef::GetBytecodeArrayRegisterCount() const { - AllowHandleDereference allow_handle_dereference; - return object<SharedFunctionInfo>()->GetBytecodeArray()->register_count(); -} +BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype) +BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup) +BIMODAL_ACCESSOR(JSFunction, Map, initial_map) +BIMODAL_ACCESSOR(JSFunction, Object, prototype) +HANDLE_ACCESSOR_C(JSFunction, bool, IsConstructor) +HANDLE_ACCESSOR(JSFunction, JSGlobalProxy, global_proxy) +HANDLE_ACCESSOR(JSFunction, SharedFunctionInfo, shared) -MapRef NativeContextRef::fast_aliased_arguments_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), - handle(object<Context>()->fast_aliased_arguments_map(), - broker()->isolate())); -} +HANDLE_ACCESSOR(JSObject, FixedArrayBase, elements) -MapRef NativeContextRef::sloppy_arguments_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<Context>()->sloppy_arguments_map(), - broker()->isolate())); -} +HANDLE_ACCESSOR(JSRegExp, Object, data) +HANDLE_ACCESSOR(JSRegExp, Object, flags) +HANDLE_ACCESSOR(JSRegExp, Object, last_index) +HANDLE_ACCESSOR(JSRegExp, Object, raw_properties_or_hash) +HANDLE_ACCESSOR(JSRegExp, Object, source) -MapRef NativeContextRef::strict_arguments_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<Context>()->strict_arguments_map(), - broker()->isolate())); -} +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_field, has_prototype_slot, Map::HasPrototypeSlotBit) +BIMODAL_ACCESSOR_C(Map, int, instance_size) +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) -MapRef NativeContextRef::js_array_fast_elements_map_index() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), - handle(object<Context>()->js_array_fast_elements_map_index(), - broker()->isolate())); -} +HANDLE_ACCESSOR_C(MutableHeapNumber, double, value) -MapRef NativeContextRef::initial_array_iterator_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), - handle(object<Context>()->initial_array_iterator_map(), - broker()->isolate())); -} +#define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \ + BIMODAL_ACCESSOR(NativeContext, type, name) +BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR) +#undef DEF_NATIVE_CONTEXT_ACCESSOR -MapRef NativeContextRef::set_value_iterator_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<Context>()->set_value_iterator_map(), - broker()->isolate())); -} +HANDLE_ACCESSOR(PropertyCell, Object, value) +HANDLE_ACCESSOR_C(PropertyCell, PropertyDetails, property_details) -MapRef NativeContextRef::set_key_value_iterator_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), - handle(object<Context>()->set_key_value_iterator_map(), - broker()->isolate())); -} +HANDLE_ACCESSOR_C(ScopeInfo, int, ContextLength) -MapRef NativeContextRef::map_key_iterator_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<Context>()->map_key_iterator_map(), - broker()->isolate())); -} +BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id) +BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray) +#define DEF_SFI_ACCESSOR(type, name) \ + BIMODAL_ACCESSOR_C(SharedFunctionInfo, type, name) +BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR) +#undef DEF_SFI_ACCESSOR -MapRef NativeContextRef::map_value_iterator_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<Context>()->map_value_iterator_map(), - broker()->isolate())); -} +BIMODAL_ACCESSOR_C(String, int, length) -MapRef NativeContextRef::map_key_value_iterator_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), - handle(object<Context>()->map_key_value_iterator_map(), - broker()->isolate())); -} +// TODO(neis): Provide StringShape() on StringRef. -MapRef NativeContextRef::iterator_result_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<Context>()->iterator_result_map(), - broker()->isolate())); -} - -MapRef NativeContextRef::string_iterator_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), handle(object<Context>()->string_iterator_map(), - broker()->isolate())); -} - -MapRef NativeContextRef::promise_function_initial_map() const { - AllowHandleAllocation handle_allocation; - AllowHandleDereference allow_handle_dereference; - return MapRef(broker(), - handle(object<Context>()->promise_function()->initial_map(), - broker()->isolate())); +bool JSFunctionRef::has_initial_map() const { + IF_BROKER_DISABLED_ACCESS_HANDLE_C(JSFunction, has_initial_map); + return data()->AsJSFunction()->initial_map != nullptr; } MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const { @@ -794,6 +1073,25 @@ MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const { return get(index).AsMap(); } +MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const { + switch (kind) { + case PACKED_SMI_ELEMENTS: + return js_array_packed_smi_elements_map(); + case HOLEY_SMI_ELEMENTS: + return js_array_holey_smi_elements_map(); + case PACKED_DOUBLE_ELEMENTS: + return js_array_packed_double_elements_map(); + case HOLEY_DOUBLE_ELEMENTS: + return js_array_holey_double_elements_map(); + case PACKED_ELEMENTS: + return js_array_packed_elements_map(); + case HOLEY_ELEMENTS: + return js_array_holey_elements_map(); + default: + UNREACHABLE(); + } +} + bool ObjectRef::BooleanValue() { AllowHandleDereference allow_handle_dereference; return object<Object>()->BooleanValue(broker()->isolate()); @@ -831,18 +1129,70 @@ CellRef ModuleRef::GetCell(int cell_index) { broker()->isolate())); } -ObjectRef PropertyCellRef::value() const { - AllowHandleAllocation allow_handle_allocation; - AllowHandleDereference allow_handle_dereference; - return ObjectRef( - broker(), handle(object<PropertyCell>()->value(), broker()->isolate())); +ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object) { + switch (broker->mode()) { + case JSHeapBroker::kSerialized: + data_ = FLAG_strict_heap_broker ? broker->GetData(object) + : broker->GetOrCreateData(object); + break; + case JSHeapBroker::kSerializing: + data_ = broker->GetOrCreateData(object); + break; + case JSHeapBroker::kDisabled: + data_ = broker->GetData(object); + if (data_ == nullptr) { + AllowHandleDereference handle_dereference; + data_ = + new (broker->zone()) ObjectData(broker, object, object->IsSmi()); + } + break; + } + CHECK_NOT_NULL(data_); } -PropertyDetails PropertyCellRef::property_details() const { - AllowHandleDereference allow_handle_dereference; - return object<PropertyCell>()->property_details(); +base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const { + if (broker()->mode() == JSHeapBroker::kDisabled) { + AllowHandleAllocation handle_allocation; + AllowHandleDereference allow_handle_dereference; + return JSObjectRef(broker(), handle(object<AllocationSite>()->boilerplate(), + broker()->isolate())); + } else { + JSObjectData* boilerplate = data()->AsAllocationSite()->boilerplate; + if (boilerplate) { + return JSObjectRef(boilerplate); + } else { + return base::nullopt; + } + } +} + +ElementsKind JSObjectRef::GetElementsKind() const { + return map().elements_kind(); } +Handle<Object> ObjectRef::object() const { return data_->object; } + +JSHeapBroker* ObjectRef::broker() const { return data_->broker; } + +ObjectData* ObjectRef::data() const { return data_; } + +Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker, + const char* function, int line) { + if (FLAG_trace_heap_broker) { + PrintF("[%p] Skipping optimization in %s at line %d due to missing data\n", + broker, function, line); + } + return AdvancedReducer::NoChange(); +} + +#undef BIMODAL_ACCESSOR +#undef BIMODAL_ACCESSOR_B +#undef BIMODAL_ACCESSOR_C +#undef GET_OR_CREATE +#undef HANDLE_ACCESSOR +#undef HANDLE_ACCESSOR_C +#undef IF_BROKER_DISABLED_ACCESS_HANDLE_C + } // namespace compiler } // namespace internal } // namespace v8 |