Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
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.cc1410
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