Revert "[compiler] Directly read PropertyCells"
This reverts commit 42cd9eb78d
.
Reason for revert: Clusterfuzz issues, e.g.
https://bugs.chromium.org/p/chromium/issues/detail?id=1176318
Original change's description:
> [compiler] Directly read PropertyCells
>
> Main changes:
>
> - Introduce a new broker data kind kBackgroundSerialized for objects
> that can be serialized in the background (when direct reads are on).
> (I'm planning to remove kPossiblyBackgroundSerialized in a followup,
> in favor of a dynamic choice of kSerialized or kBackgroundSerialized).
> - Make PropertyCell use that new kind.
> - Introduce a bottleneck in runtime code for changes to PropertyCells
> and make sure that a certain protocol is followed that allows
> concurrent reads from the background thread.
> - Improve interface of PropertyCell in various ways.
>
> Bug: v8:7790
> Change-Id: If3d7926c3b894808811348b4b2bed153f5c06897
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2661462
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Commit-Queue: Georg Neis <neis@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#72586}
TBR=ulan@chromium.org,neis@chromium.org,verwaest@chromium.org,nicohartmann@chromium.org
Change-Id: Id04145760c49fa379bc5a3fc16eba664025a9180
Bug: v8:7790
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2685125
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72619}
This commit is contained in:
parent
d5416b9918
commit
87df0b7ecc
@ -256,6 +256,8 @@ class FieldConstnessDependency final : public CompilationDependency {
|
||||
|
||||
class GlobalPropertyDependency final : public CompilationDependency {
|
||||
public:
|
||||
// TODO(neis): Once the concurrent compiler frontend is always-on, we no
|
||||
// longer need to explicitly store the type and the read_only flag.
|
||||
GlobalPropertyDependency(const PropertyCellRef& cell, PropertyCellType type,
|
||||
bool read_only)
|
||||
: cell_(cell), type_(type), read_only_(read_only) {
|
||||
@ -437,13 +439,14 @@ PropertyConstness CompilationDependencies::DependOnFieldConstness(
|
||||
|
||||
void CompilationDependencies::DependOnGlobalProperty(
|
||||
const PropertyCellRef& cell) {
|
||||
DCHECK(!cell.IsNeverSerializedHeapObject());
|
||||
PropertyCellType type = cell.property_details().cell_type();
|
||||
bool read_only = cell.property_details().IsReadOnly();
|
||||
RecordDependency(zone_->New<GlobalPropertyDependency>(cell, type, read_only));
|
||||
}
|
||||
|
||||
bool CompilationDependencies::DependOnProtector(const PropertyCellRef& cell) {
|
||||
cell.SerializeAsProtector();
|
||||
DCHECK(!cell.IsNeverSerializedHeapObject());
|
||||
if (cell.value().AsSmi() != Protectors::kProtectorValid) return false;
|
||||
RecordDependency(zone_->New<ProtectorDependency>(cell));
|
||||
return true;
|
||||
|
@ -101,13 +101,6 @@ enum class OddballType : uint8_t {
|
||||
V(HeapNumber) \
|
||||
V(Map)
|
||||
|
||||
// This list is sorted such that subtypes appear before their supertypes.
|
||||
// DO NOT VIOLATE THIS PROPERTY!
|
||||
// Types in this list can be serialized on demand from the background thread.
|
||||
#define HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(V) \
|
||||
/* Subtypes of HeapObject */ \
|
||||
V(PropertyCell)
|
||||
|
||||
// This list is sorted such that subtypes appear before their supertypes.
|
||||
// DO NOT VIOLATE THIS PROPERTY!
|
||||
#define HEAP_BROKER_SERIALIZED_OBJECT_LIST(V) \
|
||||
@ -139,6 +132,7 @@ enum class OddballType : uint8_t {
|
||||
V(FunctionTemplateInfo) \
|
||||
V(JSReceiver) \
|
||||
V(Name) \
|
||||
V(PropertyCell) \
|
||||
V(SourceTextModule) \
|
||||
/* Subtypes of Object */ \
|
||||
V(HeapObject)
|
||||
@ -152,7 +146,6 @@ class PropertyAccessInfo;
|
||||
#define FORWARD_DECL(Name) class Name##Ref;
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
#undef FORWARD_DECL
|
||||
|
||||
@ -182,14 +175,12 @@ class V8_EXPORT_PRIVATE ObjectRef {
|
||||
#define HEAP_IS_METHOD_DECL(Name) bool Is##Name() const;
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(HEAP_IS_METHOD_DECL)
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(HEAP_IS_METHOD_DECL)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(HEAP_IS_METHOD_DECL)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(HEAP_IS_METHOD_DECL)
|
||||
#undef HEAP_IS_METHOD_DECL
|
||||
|
||||
#define HEAP_AS_METHOD_DECL(Name) Name##Ref As##Name() const;
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(HEAP_AS_METHOD_DECL)
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(HEAP_AS_METHOD_DECL)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(HEAP_AS_METHOD_DECL)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(HEAP_AS_METHOD_DECL)
|
||||
#undef HEAP_AS_METHOD_DECL
|
||||
|
||||
@ -313,16 +304,9 @@ class PropertyCellRef : public HeapObjectRef {
|
||||
|
||||
Handle<PropertyCell> object() const;
|
||||
|
||||
// Can be called from a background thread.
|
||||
V8_WARN_UNUSED_RESULT bool Serialize() const;
|
||||
void SerializeAsProtector() const {
|
||||
bool serialized = Serialize();
|
||||
// A protector always holds a Smi value and its cell type never changes, so
|
||||
// Serialize can't fail.
|
||||
CHECK(serialized);
|
||||
}
|
||||
|
||||
PropertyDetails property_details() const;
|
||||
|
||||
void Serialize();
|
||||
ObjectRef value() const;
|
||||
};
|
||||
|
||||
|
@ -653,7 +653,6 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
|
||||
} else {
|
||||
PropertyCellRef array_constructor_protector(
|
||||
broker(), factory()->array_constructor_protector());
|
||||
array_constructor_protector.SerializeAsProtector();
|
||||
can_inline_call = array_constructor_protector.value().AsSmi() ==
|
||||
Protectors::kProtectorValid;
|
||||
}
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "src/objects/literal-objects-inl.h"
|
||||
#include "src/objects/module-inl.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/property-details.h"
|
||||
#include "src/objects/template-objects-inl.h"
|
||||
#include "src/objects/templates.h"
|
||||
#include "src/utils/utils.h"
|
||||
@ -46,8 +45,9 @@ namespace compiler {
|
||||
|
||||
#define FORWARD_DECL(Name) class Name##Data;
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
// TODO(solanes, v8:10866): Remove once FLAG_turbo_direct_heap_access is
|
||||
// removed.
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(FORWARD_DECL)
|
||||
#undef FORWARD_DECL
|
||||
|
||||
@ -84,7 +84,6 @@ enum ObjectDataKind {
|
||||
kSmi,
|
||||
kSerializedHeapObject,
|
||||
kPossiblyBackgroundSerializedHeapObject,
|
||||
kBackgroundSerializedHeapObject,
|
||||
kUnserializedHeapObject,
|
||||
kNeverSerializedHeapObject,
|
||||
kUnserializedReadOnlyHeapObject
|
||||
@ -139,8 +138,7 @@ class ObjectData : public ZoneObject {
|
||||
CHECK_IMPLIES(broker->mode() == JSHeapBroker::kSerialized,
|
||||
kind == kUnserializedReadOnlyHeapObject || kind == kSmi ||
|
||||
kind == kNeverSerializedHeapObject ||
|
||||
kind == kPossiblyBackgroundSerializedHeapObject ||
|
||||
kind == kBackgroundSerializedHeapObject);
|
||||
kind == kPossiblyBackgroundSerializedHeapObject);
|
||||
CHECK_IMPLIES(kind == kUnserializedReadOnlyHeapObject,
|
||||
IsReadOnlyHeapObject(*object));
|
||||
}
|
||||
@ -148,14 +146,14 @@ class ObjectData : public ZoneObject {
|
||||
#define DECLARE_IS(Name) bool Is##Name() const;
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(DECLARE_IS)
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(DECLARE_IS)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(DECLARE_IS)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(DECLARE_IS)
|
||||
#undef DECLARE_IS
|
||||
|
||||
#define DECLARE_AS(Name) Name##Data* As##Name();
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(DECLARE_AS)
|
||||
// TODO(solanes, v8:10866): Remove once FLAG_turbo_direct_heap_access is
|
||||
// removed.
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(DECLARE_AS)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(DECLARE_AS)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(DECLARE_AS)
|
||||
#undef DECLARE_AS
|
||||
|
||||
@ -199,26 +197,17 @@ class HeapObjectData : public ObjectData {
|
||||
class PropertyCellData : public HeapObjectData {
|
||||
public:
|
||||
PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
|
||||
Handle<PropertyCell> object,
|
||||
ObjectDataKind kind = ObjectDataKind::kSerializedHeapObject);
|
||||
Handle<PropertyCell> object);
|
||||
|
||||
bool Serialize(JSHeapBroker* broker);
|
||||
PropertyDetails property_details() const { return property_details_; }
|
||||
|
||||
PropertyDetails property_details() const {
|
||||
CHECK(serialized());
|
||||
return property_details_;
|
||||
}
|
||||
|
||||
ObjectData* value() const {
|
||||
DCHECK(serialized());
|
||||
return value_;
|
||||
}
|
||||
void Serialize(JSHeapBroker* broker);
|
||||
ObjectData* value() const { return value_; }
|
||||
|
||||
private:
|
||||
PropertyDetails property_details_ = PropertyDetails::Empty();
|
||||
ObjectData* value_ = nullptr;
|
||||
PropertyDetails const property_details_;
|
||||
|
||||
bool serialized() const { return value_ != nullptr; }
|
||||
ObjectData* value_ = nullptr;
|
||||
};
|
||||
|
||||
// TODO(mslekova): Once we have real-world usage data, we might want to
|
||||
@ -301,65 +290,16 @@ void JSHeapBroker::IncrementTracingIndentation() { ++trace_indentation_; }
|
||||
void JSHeapBroker::DecrementTracingIndentation() { --trace_indentation_; }
|
||||
|
||||
PropertyCellData::PropertyCellData(JSHeapBroker* broker, ObjectData** storage,
|
||||
Handle<PropertyCell> object,
|
||||
ObjectDataKind kind)
|
||||
: HeapObjectData(broker, storage, object, kind) {}
|
||||
Handle<PropertyCell> object)
|
||||
: HeapObjectData(broker, storage, object),
|
||||
property_details_(object->property_details()) {}
|
||||
|
||||
bool PropertyCellData::Serialize(JSHeapBroker* broker) {
|
||||
if (serialized()) return true;
|
||||
void PropertyCellData::Serialize(JSHeapBroker* broker) {
|
||||
if (value_ != nullptr) return;
|
||||
|
||||
TraceScope tracer(broker, this, "PropertyCellData::Serialize");
|
||||
auto cell = Handle<PropertyCell>::cast(object());
|
||||
|
||||
// While this code runs on a background thread, the property cell might
|
||||
// undergo state transitions via calls to PropertyCell::Transition. These
|
||||
// transitions follow a certain protocol on which we rely here to ensure that
|
||||
// we only report success when we can guarantee consistent data. A key
|
||||
// property is that after transitioning from cell type A to B (A != B), there
|
||||
// will never be a transition back to A, unless A is kConstant and the new
|
||||
// value is the hole (i.e. the property cell was invalidated, which is a final
|
||||
// state).
|
||||
|
||||
PropertyDetails property_details = cell->property_details(kAcquireLoad);
|
||||
|
||||
Handle<Object> value =
|
||||
broker->CanonicalPersistentHandle(cell->value(kAcquireLoad));
|
||||
if (broker->ObjectMayBeUninitialized(value)) {
|
||||
DCHECK(!broker->IsMainThread());
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
PropertyDetails property_details_again =
|
||||
cell->property_details(kAcquireLoad);
|
||||
if (property_details != property_details_again) {
|
||||
DCHECK(!broker->IsMainThread());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (property_details.cell_type() == PropertyCellType::kConstant) {
|
||||
Handle<Object> value_again =
|
||||
broker->CanonicalPersistentHandle(cell->value(kAcquireLoad));
|
||||
if (*value != *value_again) {
|
||||
DCHECK(!broker->IsMainThread());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectData* value_data = broker->TryGetOrCreateData(value, false);
|
||||
if (value_data == nullptr) {
|
||||
DCHECK(!broker->IsMainThread());
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyCell::CheckDataIsCompatible(property_details, *value);
|
||||
|
||||
DCHECK(!serialized());
|
||||
property_details_ = property_details;
|
||||
value_ = value_data;
|
||||
DCHECK(serialized());
|
||||
return true;
|
||||
value_ = broker->GetOrCreateData(cell->value());
|
||||
}
|
||||
|
||||
void FunctionTemplateInfoData::SerializeCallCode(JSHeapBroker* broker) {
|
||||
@ -1277,8 +1217,7 @@ HeapObjectData::HeapObjectData(JSHeapBroker* broker, ObjectData** storage,
|
||||
CHECK_IMPLIES(kind == kSerializedHeapObject,
|
||||
broker->mode() == JSHeapBroker::kSerializing);
|
||||
CHECK_IMPLIES(broker->mode() == JSHeapBroker::kSerialized,
|
||||
kind == kPossiblyBackgroundSerializedHeapObject ||
|
||||
kind == kBackgroundSerializedHeapObject);
|
||||
kind == kPossiblyBackgroundSerializedHeapObject);
|
||||
}
|
||||
|
||||
InstanceType HeapObjectData::GetMapInstanceType() const {
|
||||
@ -2189,17 +2128,15 @@ class CodeData : public HeapObjectData {
|
||||
}
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(DEFINE_IS)
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(DEFINE_IS)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(DEFINE_IS)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(DEFINE_IS)
|
||||
#undef DEFINE_IS
|
||||
|
||||
#define DEFINE_AS(Name) \
|
||||
Name##Data* ObjectData::As##Name() { \
|
||||
CHECK(Is##Name()); \
|
||||
CHECK(kind_ == kSerializedHeapObject || \
|
||||
kind_ == kPossiblyBackgroundSerializedHeapObject || \
|
||||
kind_ == kBackgroundSerializedHeapObject); \
|
||||
return static_cast<Name##Data*>(this); \
|
||||
#define DEFINE_AS(Name) \
|
||||
Name##Data* ObjectData::As##Name() { \
|
||||
CHECK(Is##Name()); \
|
||||
CHECK(kind_ == kSerializedHeapObject || \
|
||||
kind_ == kPossiblyBackgroundSerializedHeapObject); \
|
||||
return static_cast<Name##Data*>(this); \
|
||||
}
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(DEFINE_AS)
|
||||
#undef DEFINE_AS
|
||||
@ -2211,15 +2148,6 @@ HEAP_BROKER_SERIALIZED_OBJECT_LIST(DEFINE_AS)
|
||||
}
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(DEFINE_AS)
|
||||
#undef DEFINE_AS
|
||||
#define DEFINE_AS(Name) \
|
||||
Name##Data* ObjectData::As##Name() { \
|
||||
CHECK(Is##Name()); \
|
||||
CHECK(kind_ == kSerializedHeapObject || \
|
||||
kind_ == kBackgroundSerializedHeapObject); \
|
||||
return static_cast<Name##Data*>(this); \
|
||||
}
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(DEFINE_AS)
|
||||
#undef DEFINE_AS
|
||||
|
||||
// TODO(solanes, v8:10866): Remove once FLAG_turbo_direct_heap_access is
|
||||
// removed.
|
||||
@ -2824,6 +2752,8 @@ void JSHeapBroker::InitializeAndStartSerializing(
|
||||
|
||||
// Throw away the dummy data that we created while disabled.
|
||||
refs_->Clear();
|
||||
refs_ = nullptr;
|
||||
|
||||
refs_ =
|
||||
zone()->New<RefsMap>(kInitialRefsBucketCount, AddressMatcher(), zone());
|
||||
|
||||
@ -2838,7 +2768,7 @@ void JSHeapBroker::InitializeAndStartSerializing(
|
||||
CollectArrayAndObjectPrototypes();
|
||||
|
||||
Factory* const f = isolate()->factory();
|
||||
if (!FLAG_turbo_direct_heap_access) {
|
||||
{
|
||||
ObjectData* data;
|
||||
data = GetOrCreateData(f->array_buffer_detaching_protector());
|
||||
if (!data->should_access_heap()) data->AsPropertyCell()->Serialize(this);
|
||||
@ -2892,9 +2822,6 @@ ObjectData* JSHeapBroker::TryGetOrCreateData(Handle<Object> object,
|
||||
return *storage;
|
||||
}
|
||||
|
||||
CHECK(mode() == JSHeapBroker::kSerializing ||
|
||||
mode() == JSHeapBroker::kSerialized);
|
||||
|
||||
ObjectData* object_data;
|
||||
if (object->IsSmi()) {
|
||||
entry = refs_->LookupOrInsert(object.address());
|
||||
@ -2933,26 +2860,8 @@ ObjectData* JSHeapBroker::TryGetOrCreateData(Handle<Object> object,
|
||||
object_data = zone()->New<name##Data>(this, &(entry->value), \
|
||||
Handle<name>::cast(object));
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(
|
||||
CREATE_DATA_FOR_POSSIBLE_SERIALIZATION)
|
||||
CREATE_DATA_FOR_POSSIBLE_SERIALIZATION)
|
||||
#undef CREATE_DATA_FOR_POSSIBLE_SERIALIZATION
|
||||
#define CREATE_DATA_FOR_BACKGROUND_SERIALIZATION(name) \
|
||||
} else if (object->Is##name()) { \
|
||||
if (FLAG_turbo_direct_heap_access) { \
|
||||
entry = refs_->LookupOrInsert(object.address()); \
|
||||
object_data = zone()->New<name##Data>( \
|
||||
this, &(entry->value), Handle<name>::cast(object), \
|
||||
kBackgroundSerializedHeapObject); \
|
||||
} else if (mode() == kSerializing) { \
|
||||
entry = refs_->LookupOrInsert(object.address()); \
|
||||
object_data = zone()->New<name##Data>(this, &(entry->value), \
|
||||
Handle<name>::cast(object)); \
|
||||
} else { \
|
||||
CHECK(!crash_on_error); \
|
||||
return nullptr; \
|
||||
}
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(
|
||||
CREATE_DATA_FOR_BACKGROUND_SERIALIZATION)
|
||||
#undef CREATE_DATA_FOR_SERIALIZATION
|
||||
#define CREATE_DATA_FOR_SERIALIZATION(name) \
|
||||
} else if (object->Is##name()) { \
|
||||
if (mode() == kSerializing) { \
|
||||
@ -2990,23 +2899,9 @@ ObjectData* JSHeapBroker::GetOrCreateData(
|
||||
}
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(DEFINE_IS_AND_AS)
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(DEFINE_IS_AND_AS)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(DEFINE_IS_AND_AS)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(DEFINE_IS_AND_AS)
|
||||
#undef DEFINE_IS_AND_AS
|
||||
|
||||
bool JSHeapBroker::StackHasOverflowed() const {
|
||||
DCHECK_IMPLIES(local_isolate_ == nullptr,
|
||||
ThreadId::Current() == isolate_->thread_id());
|
||||
return (local_isolate_ != nullptr)
|
||||
? StackLimitCheck::HasOverflowed(local_isolate_)
|
||||
: StackLimitCheck(isolate_).HasOverflowed();
|
||||
}
|
||||
|
||||
bool JSHeapBroker::ObjectMayBeUninitialized(Handle<Object> object) const {
|
||||
return !IsMainThread() && object->IsHeapObject() &&
|
||||
isolate()->heap()->IsPendingAllocation(HeapObject::cast(*object));
|
||||
}
|
||||
|
||||
bool ObjectRef::IsSmi() const { return data()->is_smi(); }
|
||||
|
||||
int ObjectRef::AsSmi() const {
|
||||
@ -4279,7 +4174,6 @@ Handle<Object> ObjectRef::object() const {
|
||||
|
||||
HEAP_BROKER_SERIALIZED_OBJECT_LIST(DEF_OBJECT_GETTER)
|
||||
HEAP_BROKER_POSSIBLY_BACKGROUND_SERIALIZED_OBJECT_LIST(DEF_OBJECT_GETTER)
|
||||
HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(DEF_OBJECT_GETTER)
|
||||
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(DEF_OBJECT_GETTER)
|
||||
#undef DEF_OBJECT_GETTER
|
||||
|
||||
@ -4532,11 +4426,10 @@ bool JSBoundFunctionRef::Serialize() {
|
||||
return data()->AsJSBoundFunction()->Serialize(broker());
|
||||
}
|
||||
|
||||
bool PropertyCellRef::Serialize() const {
|
||||
if (data_->should_access_heap()) return true;
|
||||
CHECK(broker()->mode() == JSHeapBroker::kSerializing ||
|
||||
broker()->mode() == JSHeapBroker::kSerialized);
|
||||
return data()->AsPropertyCell()->Serialize(broker());
|
||||
void PropertyCellRef::Serialize() {
|
||||
if (data_->should_access_heap()) return;
|
||||
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
|
||||
data()->AsPropertyCell()->Serialize(broker());
|
||||
}
|
||||
|
||||
void FunctionTemplateInfoRef::SerializeCallCode() {
|
||||
@ -4676,8 +4569,6 @@ bool GlobalAccessFeedback::immutable() const {
|
||||
|
||||
base::Optional<ObjectRef> GlobalAccessFeedback::GetConstantHint() const {
|
||||
if (IsPropertyCell()) {
|
||||
bool cell_serialized = property_cell().Serialize();
|
||||
CHECK(cell_serialized); // Can't fail on the main thread.
|
||||
return property_cell().value();
|
||||
} else if (IsScriptContextSlot() && immutable()) {
|
||||
return script_context().get(slot_index());
|
||||
@ -5000,10 +4891,7 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForGlobalAccess(
|
||||
// The wanted name belongs (or did belong) to a property on the global
|
||||
// object and the feedback is the cell holding its value.
|
||||
PropertyCellRef cell(this, Handle<PropertyCell>::cast(feedback_value));
|
||||
ObjectRef(
|
||||
this,
|
||||
CanonicalPersistentHandle(
|
||||
Handle<PropertyCell>::cast(feedback_value)->value(kAcquireLoad)));
|
||||
cell.Serialize();
|
||||
return *zone()->New<GlobalAccessFeedback>(cell, nexus.kind());
|
||||
}
|
||||
|
||||
@ -5480,6 +5368,14 @@ TemplateObjectFeedback const& ProcessedFeedback::AsTemplateObject() const {
|
||||
return *static_cast<TemplateObjectFeedback const*>(this);
|
||||
}
|
||||
|
||||
bool JSHeapBroker::StackHasOverflowed() const {
|
||||
DCHECK_IMPLIES(local_isolate_ == nullptr,
|
||||
ThreadId::Current() == isolate_->thread_id());
|
||||
return (local_isolate_ != nullptr)
|
||||
? StackLimitCheck::HasOverflowed(local_isolate_)
|
||||
: StackLimitCheck(isolate_).HasOverflowed();
|
||||
}
|
||||
|
||||
OffHeapBytecodeArray::OffHeapBytecodeArray(BytecodeArrayRef bytecode_array)
|
||||
: array_(bytecode_array) {}
|
||||
|
||||
|
@ -313,16 +313,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
|
||||
friend class HeapObjectRef;
|
||||
friend class ObjectRef;
|
||||
friend class ObjectData;
|
||||
friend class PropertyCellData;
|
||||
|
||||
bool IsMainThread() const {
|
||||
return local_isolate() == nullptr || local_isolate()->is_main_thread();
|
||||
}
|
||||
|
||||
// If this returns false, the object is guaranteed to be fully initialized and
|
||||
// thus safe to read from a memory safety perspective. The converse does not
|
||||
// necessarily hold.
|
||||
bool ObjectMayBeUninitialized(Handle<Object> object) const;
|
||||
|
||||
bool CanUseFeedback(const FeedbackNexus& nexus) const;
|
||||
const ProcessedFeedback& NewInsufficientFeedback(FeedbackSlotKind kind) const;
|
||||
|
@ -802,9 +802,9 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
|
||||
Node* node, Node* lookup_start_object, Node* receiver, Node* value,
|
||||
NameRef const& name, AccessMode access_mode, Node* key,
|
||||
PropertyCellRef const& property_cell, Node* effect) {
|
||||
if (!property_cell.Serialize()) {
|
||||
TRACE_BROKER_MISSING(broker(), "usable data for " << property_cell);
|
||||
return NoChange();
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
if (effect == nullptr) {
|
||||
effect = NodeProperties::GetEffectInput(node);
|
||||
}
|
||||
|
||||
ObjectRef property_cell_value = property_cell.value();
|
||||
@ -819,11 +819,6 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
|
||||
PropertyCellType property_cell_type = property_details.cell_type();
|
||||
DCHECK_EQ(kData, property_details.kind());
|
||||
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
if (effect == nullptr) {
|
||||
effect = NodeProperties::GetEffectInput(node);
|
||||
}
|
||||
|
||||
// We have additional constraints for stores.
|
||||
if (access_mode == AccessMode::kStore) {
|
||||
DCHECK_EQ(receiver, lookup_start_object);
|
||||
@ -928,6 +923,10 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
|
||||
DCHECK_EQ(receiver, lookup_start_object);
|
||||
DCHECK(!property_details.IsReadOnly());
|
||||
switch (property_details.cell_type()) {
|
||||
case PropertyCellType::kUndefined: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
case PropertyCellType::kConstant: {
|
||||
// Record a code dependency on the cell, and just deoptimize if the new
|
||||
// value doesn't match the previous value stored inside the cell.
|
||||
@ -998,8 +997,6 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
|
||||
jsgraph()->Constant(property_cell), value, effect, control);
|
||||
break;
|
||||
}
|
||||
case PropertyCellType::kUndefined:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,8 +594,6 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
|
||||
|
||||
PropertyCellRef string_length_protector(
|
||||
broker(), factory()->string_length_protector());
|
||||
string_length_protector.SerializeAsProtector();
|
||||
|
||||
if (string_length_protector.value().AsSmi() ==
|
||||
Protectors::kProtectorValid) {
|
||||
// We can just deoptimize if the {length} is out-of-bounds. Besides
|
||||
|
@ -1203,10 +1203,6 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl(
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_turbo_direct_heap_access) {
|
||||
isolate->heap()->PublishPendingAllocations();
|
||||
}
|
||||
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
|
@ -2991,9 +2991,7 @@ SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
|
||||
base::Optional<PropertyCellRef> cell = global_object.GetPropertyCell(
|
||||
name, SerializationPolicy::kSerializeIfNeeded);
|
||||
if (access_mode == AccessMode::kLoad && cell.has_value()) {
|
||||
result_hints->AddConstant(
|
||||
handle(cell->object()->value(), broker()->isolate()), zone(),
|
||||
broker());
|
||||
result_hints->AddConstant(cell->value().object(), zone(), broker());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -967,9 +967,11 @@ void Oddball::OddballVerify(Isolate* isolate) {
|
||||
}
|
||||
|
||||
void PropertyCell::PropertyCellVerify(Isolate* isolate) {
|
||||
// TODO(torque): replace with USE_TORQUE_VERIFIER(PropertyCell) once
|
||||
// it supports UniqueName type.
|
||||
TorqueGeneratedClassVerifiers::PropertyCellVerify(*this, isolate);
|
||||
|
||||
CHECK(name().IsUniqueName());
|
||||
CheckDataIsCompatible(property_details(), value());
|
||||
}
|
||||
|
||||
void CodeDataContainer::CodeDataContainerVerify(Isolate* isolate) {
|
||||
|
@ -1524,11 +1524,11 @@ void PropertyCell::PropertyCellPrint(std::ostream& os) { // NOLINT
|
||||
PrintHeader(os, "PropertyCell");
|
||||
os << "\n - name: ";
|
||||
name().NamePrint(os);
|
||||
os << "\n - value: " << Brief(value(kAcquireLoad));
|
||||
os << "\n - value: " << Brief(value());
|
||||
os << "\n - details: ";
|
||||
PropertyDetails details = property_details(kAcquireLoad);
|
||||
details.PrintAsSlowTo(os, true);
|
||||
os << "\n - cell_type: " << details.cell_type();
|
||||
property_details().PrintAsSlowTo(os, true);
|
||||
PropertyCellType cell_type = property_details().cell_type();
|
||||
os << "\n - cell_type: " << cell_type;
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define V8_EXECUTION_PROTECTORS_INL_H_
|
||||
|
||||
#include "src/execution/protectors.h"
|
||||
#include "src/objects/contexts-inl.h"
|
||||
#include "src/objects/property-cell-inl.h"
|
||||
#include "src/objects/smi.h"
|
||||
|
||||
|
@ -53,7 +53,9 @@ DECLARED_PROTECTORS_ON_ISOLATE(V)
|
||||
TraceProtectorInvalidation(#name); \
|
||||
} \
|
||||
isolate->CountUsage(v8::Isolate::kInvalidated##name##Protector); \
|
||||
isolate->factory()->cell()->InvalidateProtector(); \
|
||||
PropertyCell::SetValueWithInvalidation( \
|
||||
isolate, #cell, isolate->factory()->cell(), \
|
||||
handle(Smi::FromInt(kProtectorInvalid), isolate)); \
|
||||
DCHECK(!Is##name##Intact(isolate)); \
|
||||
}
|
||||
DECLARED_PROTECTORS_ON_ISOLATE(INVALIDATE_PROTECTOR_ON_ISOLATE_DEFINITION)
|
||||
|
@ -1372,8 +1372,6 @@ Handle<FeedbackCell> Factory::NewManyClosuresCell(Handle<HeapObject> value) {
|
||||
}
|
||||
|
||||
Handle<PropertyCell> Factory::NewPropertyCell(Handle<Name> name,
|
||||
PropertyDetails details,
|
||||
Handle<Object> value,
|
||||
AllocationType allocation) {
|
||||
DCHECK(name->IsUniqueName());
|
||||
STATIC_ASSERT(PropertyCell::kSize <= kMaxRegularHeapObjectSize);
|
||||
@ -1382,18 +1380,12 @@ Handle<PropertyCell> Factory::NewPropertyCell(Handle<Name> name,
|
||||
Handle<PropertyCell> cell(PropertyCell::cast(result), isolate());
|
||||
cell->set_dependent_code(DependentCode::cast(*empty_weak_fixed_array()),
|
||||
SKIP_WRITE_BARRIER);
|
||||
cell->set_property_details(PropertyDetails(Smi::zero()));
|
||||
cell->set_name(*name);
|
||||
cell->set_value(*value);
|
||||
cell->set_property_details_raw(details.AsSmi());
|
||||
cell->set_value(*the_hole_value());
|
||||
return cell;
|
||||
}
|
||||
|
||||
Handle<PropertyCell> Factory::NewProtector() {
|
||||
return NewPropertyCell(
|
||||
empty_string(), PropertyDetails::Empty(PropertyCellType::kConstantType),
|
||||
handle(Smi::FromInt(Protectors::kProtectorValid), isolate()));
|
||||
}
|
||||
|
||||
Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions,
|
||||
int slack) {
|
||||
int capacity = TransitionArray::LengthFor(number_of_transitions + slack);
|
||||
@ -2058,8 +2050,8 @@ Handle<JSGlobalObject> Factory::NewJSGlobalObject(
|
||||
PropertyDetails d(kAccessor, details.attributes(),
|
||||
PropertyCellType::kMutable);
|
||||
Handle<Name> name(descs->GetKey(i), isolate());
|
||||
Handle<Object> value(descs->GetStrongValue(i), isolate());
|
||||
Handle<PropertyCell> cell = NewPropertyCell(name, d, value);
|
||||
Handle<PropertyCell> cell = NewPropertyCell(name);
|
||||
cell->set_value(descs->GetStrongValue(i));
|
||||
// |dictionary| already contains enough space for all properties.
|
||||
USE(GlobalDictionary::Add(isolate(), dictionary, name, cell, d));
|
||||
}
|
||||
|
@ -386,9 +386,7 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
|
||||
Handle<Cell> NewCell(Handle<Object> value);
|
||||
|
||||
Handle<PropertyCell> NewPropertyCell(
|
||||
Handle<Name> name, PropertyDetails details, Handle<Object> value,
|
||||
AllocationType allocation = AllocationType::kOld);
|
||||
Handle<PropertyCell> NewProtector();
|
||||
Handle<Name> name, AllocationType allocation = AllocationType::kOld);
|
||||
|
||||
Handle<FeedbackCell> NewNoClosuresCell(Handle<HeapObject> value);
|
||||
Handle<FeedbackCell> NewOneClosureCell(Handle<HeapObject> value);
|
||||
|
@ -857,22 +857,117 @@ void Heap::CreateInitialObjects() {
|
||||
set_empty_script(*script);
|
||||
|
||||
// Protectors
|
||||
set_array_buffer_detaching_protector(*factory->NewProtector());
|
||||
set_array_constructor_protector(*factory->NewProtector());
|
||||
set_array_iterator_protector(*factory->NewProtector());
|
||||
set_array_species_protector(*factory->NewProtector());
|
||||
set_is_concat_spreadable_protector(*factory->NewProtector());
|
||||
set_map_iterator_protector(*factory->NewProtector());
|
||||
set_no_elements_protector(*factory->NewProtector());
|
||||
set_promise_hook_protector(*factory->NewProtector());
|
||||
set_promise_resolve_protector(*factory->NewProtector());
|
||||
set_promise_species_protector(*factory->NewProtector());
|
||||
set_promise_then_protector(*factory->NewProtector());
|
||||
set_regexp_species_protector(*factory->NewProtector());
|
||||
set_set_iterator_protector(*factory->NewProtector());
|
||||
set_string_iterator_protector(*factory->NewProtector());
|
||||
set_string_length_protector(*factory->NewProtector());
|
||||
set_typed_array_species_protector(*factory->NewProtector());
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_array_constructor_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_no_elements_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_array_iterator_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_map_iterator_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_set_iterator_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_is_concat_spreadable_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_array_species_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_typed_array_species_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_promise_species_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_regexp_species_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_string_iterator_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_string_length_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_array_buffer_detaching_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_promise_hook_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_promise_resolve_protector(*cell);
|
||||
}
|
||||
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_promise_then_protector(*cell);
|
||||
}
|
||||
|
||||
set_serialized_objects(roots.empty_fixed_array());
|
||||
set_serialized_global_proxy_sizes(roots.empty_fixed_array());
|
||||
|
@ -2603,8 +2603,12 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
native_context()->set_regexp_last_match_info(*last_match_info);
|
||||
|
||||
// Install the species protector cell.
|
||||
Handle<PropertyCell> cell = factory->NewProtector();
|
||||
native_context()->set_regexp_species_protector(*cell);
|
||||
{
|
||||
Handle<PropertyCell> cell =
|
||||
factory->NewPropertyCell(factory->empty_string());
|
||||
cell->set_value(Smi::FromInt(Protectors::kProtectorValid));
|
||||
native_context()->set_regexp_species_protector(*cell);
|
||||
}
|
||||
|
||||
DCHECK(regexp_fun->HasFastProperties());
|
||||
}
|
||||
|
@ -322,7 +322,16 @@ template <typename Dictionary>
|
||||
void GlobalDictionaryShape::DetailsAtPut(Dictionary dict, InternalIndex entry,
|
||||
PropertyDetails value) {
|
||||
DCHECK(entry.is_found());
|
||||
dict.CellAt(entry).UpdatePropertyDetailsExceptCellType(value);
|
||||
PropertyCell cell = dict.CellAt(entry);
|
||||
// Deopt when when making a writable property read-only. The reverse direction
|
||||
// is uninteresting because Turbofan does not currently rely on read-only
|
||||
// unless the property is also configurable, in which case it will stay
|
||||
// read-only forever.
|
||||
if (!cell.property_details().IsReadOnly() && value.IsReadOnly()) {
|
||||
cell.dependent_code().DeoptimizeDependentCodeGroup(
|
||||
DependentCode::kPropertyCellChangedGroup);
|
||||
}
|
||||
cell.set_property_details(value);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -2453,16 +2453,19 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
|
||||
if (entry.is_not_found()) {
|
||||
DCHECK_IMPLIES(global_obj->map().is_prototype_map(),
|
||||
Map::IsPrototypeChainInvalidated(global_obj->map()));
|
||||
auto cell = isolate->factory()->NewPropertyCell(name);
|
||||
cell->set_value(*value);
|
||||
auto cell_type = value->IsUndefined(roots) ? PropertyCellType::kUndefined
|
||||
: PropertyCellType::kConstant;
|
||||
details = details.set_cell_type(cell_type);
|
||||
auto cell = isolate->factory()->NewPropertyCell(name, details, value);
|
||||
value = cell;
|
||||
dictionary =
|
||||
GlobalDictionary::Add(isolate, dictionary, name, cell, details);
|
||||
GlobalDictionary::Add(isolate, dictionary, name, value, details);
|
||||
global_obj->set_global_dictionary(*dictionary, kReleaseStore);
|
||||
} else {
|
||||
PropertyCell::PrepareForValue(isolate, dictionary, entry, value, details);
|
||||
DCHECK_EQ(dictionary->CellAt(entry).value(), *value);
|
||||
Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
|
||||
isolate, dictionary, entry, value, details);
|
||||
cell->set_value(*value);
|
||||
}
|
||||
} else {
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
|
@ -494,8 +494,8 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
|
||||
|
||||
Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
|
||||
isolate(), dictionary, dictionary_entry(), value, details);
|
||||
cell->set_value(*value);
|
||||
property_details_ = cell->property_details();
|
||||
DCHECK_EQ(cell->value(), *value);
|
||||
} else {
|
||||
PropertyDetails details(kData, attributes, PropertyConstness::kMutable);
|
||||
if (V8_DICT_MODE_PROTOTYPES_BOOL) {
|
||||
@ -554,12 +554,13 @@ void LookupIterator::PrepareTransitionToDataProperty(
|
||||
if (map->is_dictionary_map()) {
|
||||
state_ = TRANSITION;
|
||||
if (map->IsJSGlobalObjectMap()) {
|
||||
Handle<PropertyCell> cell = isolate_->factory()->NewPropertyCell(name());
|
||||
DCHECK(cell->value(isolate_).IsTheHole(isolate_));
|
||||
DCHECK(!value->IsTheHole(isolate_));
|
||||
// Don't set enumeration index (it will be set during value store).
|
||||
property_details_ = PropertyDetails(
|
||||
kData, attributes, PropertyCell::InitialType(isolate_, value));
|
||||
transition_ = isolate_->factory()->NewPropertyCell(
|
||||
name(), property_details_, value);
|
||||
transition_ = cell;
|
||||
has_property_ = true;
|
||||
} else {
|
||||
// Don't set enumeration index (it will be set during value store).
|
||||
@ -1033,13 +1034,9 @@ void LookupIterator::WriteDataValue(Handle<Object> value,
|
||||
DCHECK_EQ(PropertyConstness::kConst, property_details_.constness());
|
||||
}
|
||||
} else if (holder->IsJSGlobalObject(isolate_)) {
|
||||
// PropertyCell::PrepareForValue already wrote the value into the cell.
|
||||
#ifdef DEBUG
|
||||
GlobalDictionary dictionary =
|
||||
JSGlobalObject::cast(*holder).global_dictionary(isolate_, kAcquireLoad);
|
||||
PropertyCell cell = dictionary.CellAt(isolate_, dictionary_entry());
|
||||
DCHECK_EQ(cell.value(), *value);
|
||||
#endif // DEBUG
|
||||
dictionary.CellAt(isolate_, dictionary_entry()).set_value(*value);
|
||||
} else {
|
||||
DCHECK_IMPLIES(holder->IsJSProxy(isolate_), name()->IsPrivate(isolate_));
|
||||
// Check similar to fast mode case above.
|
||||
@ -1144,9 +1141,7 @@ LookupIterator::State LookupIterator::LookupInSpecialHolder(
|
||||
number_ = dict.FindEntry(isolate(), name_);
|
||||
if (number_.is_not_found()) return NOT_FOUND;
|
||||
PropertyCell cell = dict.CellAt(isolate_, number_);
|
||||
if (cell.value(isolate_).IsTheHole(isolate_)) {
|
||||
return NOT_FOUND;
|
||||
}
|
||||
if (cell.value(isolate_).IsTheHole(isolate_)) return NOT_FOUND;
|
||||
property_details_ = cell.property_details();
|
||||
has_property_ = true;
|
||||
switch (property_details_.kind()) {
|
||||
|
@ -2150,7 +2150,7 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
|
||||
os << " value=";
|
||||
HeapStringAllocator allocator;
|
||||
StringStream accumulator(&allocator);
|
||||
cell.value(kAcquireLoad).ShortPrint(&accumulator);
|
||||
cell.value().ShortPrint(&accumulator);
|
||||
os << accumulator.ToCString().get();
|
||||
os << '>';
|
||||
break;
|
||||
@ -6355,7 +6355,8 @@ void PropertyCell::ClearAndInvalidate(ReadOnlyRoots roots) {
|
||||
DCHECK(!value().IsTheHole(roots));
|
||||
PropertyDetails details = property_details();
|
||||
details = details.set_cell_type(PropertyCellType::kConstant);
|
||||
Transition(details, roots.the_hole_value_handle());
|
||||
set_value(roots.the_hole_value());
|
||||
set_property_details(details);
|
||||
dependent_code().DeoptimizeDependentCodeGroup(
|
||||
DependentCode::kPropertyCellChangedGroup);
|
||||
}
|
||||
@ -6367,15 +6368,15 @@ Handle<PropertyCell> PropertyCell::InvalidateAndReplaceEntry(
|
||||
Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
|
||||
Handle<Name> name(cell->name(), isolate);
|
||||
PropertyDetails details = cell->property_details();
|
||||
Handle<Object> value(cell->value(), isolate);
|
||||
|
||||
DCHECK(details.IsConfigurable());
|
||||
DCHECK(!value->IsTheHole(isolate));
|
||||
DCHECK(!cell->value().IsTheHole(isolate));
|
||||
|
||||
// Swap with a copy of type kMutable.
|
||||
// Swap with a copy.
|
||||
Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(name);
|
||||
new_cell->set_value(cell->value());
|
||||
// Cell is officially mutable henceforth.
|
||||
details = details.set_cell_type(PropertyCellType::kMutable);
|
||||
Handle<PropertyCell> new_cell =
|
||||
isolate->factory()->NewPropertyCell(name, details, value);
|
||||
new_cell->set_property_details(details);
|
||||
dictionary->ValueAtPut(entry, *new_cell);
|
||||
|
||||
cell->ClearAndInvalidate(ReadOnlyRoots(isolate));
|
||||
@ -6423,6 +6424,7 @@ PropertyCellType PropertyCell::UpdatedType(Isolate* isolate,
|
||||
case PropertyCellType::kMutable:
|
||||
return PropertyCellType::kMutable;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
Handle<PropertyCell> PropertyCell::PrepareForValue(
|
||||
@ -6445,8 +6447,17 @@ Handle<PropertyCell> PropertyCell::PrepareForValue(
|
||||
cell = PropertyCell::InvalidateAndReplaceEntry(isolate, dictionary, entry);
|
||||
}
|
||||
|
||||
// Install new property details.
|
||||
details = details.set_cell_type(new_type);
|
||||
cell->Transition(details, value);
|
||||
cell->set_property_details(details);
|
||||
|
||||
if (new_type == PropertyCellType::kConstant ||
|
||||
new_type == PropertyCellType::kConstantType) {
|
||||
// Store the value now to ensure that the cell contains the constant or
|
||||
// type information. Otherwise subsequent store operation will turn
|
||||
// the cell to mutable.
|
||||
cell->set_value(*value);
|
||||
}
|
||||
|
||||
// Deopt when transitioning from a constant type or when making a writable
|
||||
// property read-only. Making a read-only property writable again is not
|
||||
@ -6463,58 +6474,17 @@ Handle<PropertyCell> PropertyCell::PrepareForValue(
|
||||
}
|
||||
|
||||
// static
|
||||
void PropertyCell::InvalidateProtector() {
|
||||
if (value() != Smi::FromInt(Protectors::kProtectorInvalid)) {
|
||||
DCHECK_EQ(value(), Smi::FromInt(Protectors::kProtectorValid));
|
||||
set_value(Smi::FromInt(Protectors::kProtectorInvalid), kReleaseStore);
|
||||
dependent_code().DeoptimizeDependentCodeGroup(
|
||||
void PropertyCell::SetValueWithInvalidation(Isolate* isolate,
|
||||
const char* cell_name,
|
||||
Handle<PropertyCell> cell,
|
||||
Handle<Object> new_value) {
|
||||
if (cell->value() != *new_value) {
|
||||
cell->set_value(*new_value);
|
||||
cell->dependent_code().DeoptimizeDependentCodeGroup(
|
||||
DependentCode::kPropertyCellChangedGroup);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool PropertyCell::CheckDataIsCompatible(PropertyDetails details,
|
||||
Object value) {
|
||||
DisallowGarbageCollection no_gc;
|
||||
PropertyCellType cell_type = details.cell_type();
|
||||
if (value.IsTheHole()) {
|
||||
CHECK_EQ(cell_type, PropertyCellType::kConstant);
|
||||
} else {
|
||||
CHECK_EQ(value.IsAccessorInfo() || value.IsAccessorPair(),
|
||||
details.kind() == kAccessor);
|
||||
DCHECK_IMPLIES(cell_type == PropertyCellType::kUndefined,
|
||||
value.IsUndefined());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool PropertyCell::CanTransitionTo(PropertyDetails new_details,
|
||||
Object new_value) const {
|
||||
// Extending the implementation of PropertyCells with additional states
|
||||
// and/or transitions likely requires changes to PropertyCellData::Serialize.
|
||||
DisallowGarbageCollection no_gc;
|
||||
DCHECK(CheckDataIsCompatible(new_details, new_value));
|
||||
switch (property_details().cell_type()) {
|
||||
case PropertyCellType::kUndefined:
|
||||
return new_details.cell_type() != PropertyCellType::kUndefined;
|
||||
case PropertyCellType::kConstant:
|
||||
return !value().IsTheHole() &&
|
||||
new_details.cell_type() != PropertyCellType::kUndefined;
|
||||
case PropertyCellType::kConstantType:
|
||||
return new_details.cell_type() == PropertyCellType::kConstantType ||
|
||||
new_details.cell_type() == PropertyCellType::kMutable ||
|
||||
(new_details.cell_type() == PropertyCellType::kConstant &&
|
||||
new_value.IsTheHole());
|
||||
case PropertyCellType::kMutable:
|
||||
return new_details.cell_type() == PropertyCellType::kMutable ||
|
||||
(new_details.cell_type() == PropertyCellType::kConstant &&
|
||||
new_value.IsTheHole());
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
int JSGeneratorObject::source_position() const {
|
||||
CHECK(is_suspended());
|
||||
DCHECK(function().shared().HasBytecodeArray());
|
||||
|
@ -22,43 +22,15 @@ CAST_ACCESSOR(PropertyCell)
|
||||
|
||||
ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
|
||||
ACCESSORS(PropertyCell, name, Name, kNameOffset)
|
||||
ACCESSORS(PropertyCell, property_details_raw, Smi, kPropertyDetailsRawOffset)
|
||||
RELEASE_ACQUIRE_ACCESSORS(PropertyCell, property_details_raw, Smi,
|
||||
kPropertyDetailsRawOffset)
|
||||
ACCESSORS(PropertyCell, value, Object, kValueOffset)
|
||||
RELEASE_ACQUIRE_ACCESSORS(PropertyCell, value, Object, kValueOffset)
|
||||
ACCESSORS(PropertyCell, property_details_raw, Smi, kPropertyDetailsRawOffset)
|
||||
|
||||
PropertyDetails PropertyCell::property_details() const {
|
||||
return PropertyDetails(Smi::cast(property_details_raw()));
|
||||
}
|
||||
|
||||
PropertyDetails PropertyCell::property_details(AcquireLoadTag tag) const {
|
||||
return PropertyDetails(Smi::cast(property_details_raw(tag)));
|
||||
}
|
||||
|
||||
void PropertyCell::UpdatePropertyDetailsExceptCellType(
|
||||
PropertyDetails details) {
|
||||
DCHECK(CheckDataIsCompatible(details, value()));
|
||||
PropertyDetails old_details = property_details();
|
||||
CHECK_EQ(old_details.cell_type(), details.cell_type());
|
||||
set_property_details_raw(details.AsSmi(), kReleaseStore);
|
||||
// Deopt when making a writable property read-only. The reverse direction
|
||||
// is uninteresting because Turbofan does not currently rely on read-only
|
||||
// unless the property is also configurable, in which case it will stay
|
||||
// read-only forever.
|
||||
if (!old_details.IsReadOnly() && details.IsReadOnly()) {
|
||||
dependent_code().DeoptimizeDependentCodeGroup(
|
||||
DependentCode::kPropertyCellChangedGroup);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyCell::Transition(PropertyDetails new_details,
|
||||
Handle<Object> new_value) {
|
||||
DCHECK(CanTransitionTo(new_details, *new_value));
|
||||
// This code must be in sync with its counterpart in
|
||||
// PropertyCellData::Serialize.
|
||||
set_value(*new_value, kReleaseStore);
|
||||
set_property_details_raw(new_details.AsSmi(), kReleaseStore);
|
||||
void PropertyCell::set_property_details(PropertyDetails details) {
|
||||
set_property_details_raw(details.AsSmi());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -20,24 +20,16 @@ class PropertyCell : public HeapObject {
|
||||
DECL_GETTER(name, Name)
|
||||
|
||||
// [property_details]: details of the global property.
|
||||
DECL_GETTER(property_details_raw, Smi)
|
||||
DECL_ACQUIRE_GETTER(property_details_raw, Smi)
|
||||
inline PropertyDetails property_details() const;
|
||||
inline PropertyDetails property_details(AcquireLoadTag tag) const;
|
||||
inline void UpdatePropertyDetailsExceptCellType(PropertyDetails details);
|
||||
DECL_ACCESSORS(property_details_raw, Smi)
|
||||
|
||||
// [value]: value of the global property.
|
||||
DECL_GETTER(value, Object)
|
||||
DECL_ACQUIRE_GETTER(value, Object)
|
||||
DECL_ACCESSORS(value, Object)
|
||||
|
||||
// [dependent_code]: code that depends on the type of the global property.
|
||||
DECL_ACCESSORS(dependent_code, DependentCode)
|
||||
|
||||
// Changes the value and/or property details.
|
||||
// For global properties:
|
||||
inline void Transition(PropertyDetails new_details, Handle<Object> new_value);
|
||||
// For protectors:
|
||||
void InvalidateProtector();
|
||||
inline PropertyDetails property_details() const;
|
||||
inline void set_property_details(PropertyDetails details);
|
||||
|
||||
static PropertyCellType InitialType(Isolate* isolate, Handle<Object> value);
|
||||
|
||||
@ -60,9 +52,9 @@ class PropertyCell : public HeapObject {
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary,
|
||||
InternalIndex entry);
|
||||
|
||||
// Whether or not the {details} and {value} fit together. This is an
|
||||
// approximation with false positives.
|
||||
static bool CheckDataIsCompatible(PropertyDetails details, Object value);
|
||||
static void SetValueWithInvalidation(Isolate* isolate, const char* cell_name,
|
||||
Handle<PropertyCell> cell,
|
||||
Handle<Object> new_value);
|
||||
|
||||
DECL_CAST(PropertyCell)
|
||||
DECL_PRINTER(PropertyCell)
|
||||
@ -79,16 +71,6 @@ class PropertyCell : public HeapObject {
|
||||
friend class Factory;
|
||||
|
||||
DECL_SETTER(name, Name)
|
||||
DECL_SETTER(value, Object)
|
||||
DECL_RELEASE_SETTER(value, Object)
|
||||
DECL_SETTER(property_details_raw, Smi)
|
||||
DECL_RELEASE_SETTER(property_details_raw, Smi)
|
||||
|
||||
#ifdef DEBUG
|
||||
// Whether the property cell can transition to the given state. This is an
|
||||
// approximation with false positives.
|
||||
bool CanTransitionTo(PropertyDetails new_details, Object new_value) const;
|
||||
#endif // DEBUG
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -215,7 +215,7 @@ enum class PropertyCellType {
|
||||
kUndefined, // The PREMONOMORPHIC of property cells.
|
||||
kConstant, // Cell has been assigned only once.
|
||||
kConstantType, // Cell has been assigned only one type.
|
||||
// Value for dictionaries not holding cells, must be 0:
|
||||
// Value for dictionaries not holding cells, must have value 0:
|
||||
kNoCell = kMutable,
|
||||
};
|
||||
|
||||
@ -262,14 +262,6 @@ class PropertyDetails {
|
||||
return PropertyDetails(kData, NONE, cell_type);
|
||||
}
|
||||
|
||||
bool operator==(PropertyDetails const& other) {
|
||||
return value_ == other.value_;
|
||||
}
|
||||
|
||||
bool operator!=(PropertyDetails const& other) {
|
||||
return value_ != other.value_;
|
||||
}
|
||||
|
||||
int pointer() const { return DescriptorPointer::decode(value_); }
|
||||
|
||||
PropertyDetails set_pointer(int i) const {
|
||||
|
@ -881,8 +881,7 @@ void TestNameDictionaryLookup() {
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(keys); i++) {
|
||||
Handle<Object> value =
|
||||
factory->NewPropertyCell(keys[i], fake_details, keys[i]);
|
||||
Handle<Object> value = factory->NewPropertyCell(keys[i]);
|
||||
dictionary =
|
||||
Dictionary::Add(isolate, dictionary, keys[i], value, fake_details);
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --concurrent-recompilation --block-concurrent-recompilation
|
||||
// Flags: --nostress-opt --no-always-opt
|
||||
|
||||
// --nostress-opt is in place because this particular optimization
|
||||
// (guaranteeing that the Array prototype chain has no elements) is
|
||||
// maintained isolate-wide. Once it's been "broken" by the change
|
||||
// to the Object prototype below, future compiles will not use the
|
||||
// optimization anymore, and the code will remain optimized despite
|
||||
// additional changes to the prototype chain.
|
||||
|
||||
if (!%IsConcurrentRecompilationSupported()) {
|
||||
print("Concurrent recompilation is disabled. Skipping this test.");
|
||||
quit();
|
||||
}
|
||||
|
||||
function f1(a, i) {
|
||||
return a[i] + 0.5;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(f1);
|
||||
var arr = [0.0,,2.5];
|
||||
assertEquals(0.5, f1(arr, 0));
|
||||
assertEquals(0.5, f1(arr, 0));
|
||||
|
||||
// Optimized code of f1 depends on initial object and array maps.
|
||||
%OptimizeFunctionOnNextCall(f1, "concurrent");
|
||||
// Kick off recompilation.
|
||||
assertEquals(0.5, f1(arr, 0));
|
||||
// Invalidate current initial object map.
|
||||
Object.prototype[1] = 1.5;
|
||||
assertEquals(2, f1(arr, 1));
|
||||
// Not yet optimized since concurrent recompilation is blocked.
|
||||
assertUnoptimized(f1, "no sync");
|
||||
// Let concurrent recompilation proceed.
|
||||
%UnblockConcurrentRecompilation();
|
||||
// Sync with background thread to conclude optimization, which may or may not
|
||||
// bailout due to map dependency, depending on whether the compiler read the
|
||||
// NoElements protector before or after the store to Object.prototype above.
|
||||
assertEquals(2, f1(arr, 1));
|
||||
// Clear type info for stress runs.
|
||||
%ClearFunctionFeedback(f1);
|
@ -28,7 +28,6 @@
|
||||
// Flags: --allow-natives-syntax
|
||||
// Flags: --concurrent-recompilation --block-concurrent-recompilation
|
||||
// Flags: --nostress-opt --no-always-opt
|
||||
// Flags: --no-turbo-direct-heap-access
|
||||
|
||||
// --nostress-opt is in place because this particular optimization
|
||||
// (guaranteeing that the Array prototype chain has no elements) is
|
||||
@ -45,6 +44,7 @@ if (!%IsConcurrentRecompilationSupported()) {
|
||||
function f1(a, i) {
|
||||
return a[i] + 0.5;
|
||||
}
|
||||
%PrepareFunctionForOptimization(f1);
|
||||
|
||||
%PrepareFunctionForOptimization(f1);
|
||||
var arr = [0.0,,2.5];
|
||||
@ -53,9 +53,7 @@ assertEquals(0.5, f1(arr, 0));
|
||||
|
||||
// Optimized code of f1 depends on initial object and array maps.
|
||||
%OptimizeFunctionOnNextCall(f1, "concurrent");
|
||||
// Kick off recompilation. Note that the NoElements protector is read by the
|
||||
// compiler in the main-thread phase of compilation, i.e., before the store to
|
||||
// Object.prototype below.
|
||||
// Kick off recompilation;
|
||||
assertEquals(0.5, f1(arr, 0));
|
||||
// Invalidate current initial object map after compile graph has been created.
|
||||
Object.prototype[1] = 1.5;
|
||||
@ -67,5 +65,5 @@ assertUnoptimized(f1, "no sync");
|
||||
// Sync with background thread to conclude optimization, which bails out
|
||||
// due to map dependency.
|
||||
assertUnoptimized(f1, "sync");
|
||||
// Clear type info for stress runs.
|
||||
//Clear type info for stress runs.
|
||||
%ClearFunctionFeedback(f1);
|
@ -1046,8 +1046,7 @@
|
||||
'compiler/regress-905555-2': [SKIP],
|
||||
'compiler/regress-905555': [SKIP],
|
||||
'compiler/regress-9945-1': [SKIP],
|
||||
'concurrent-initial-prototype-change-1': [SKIP],
|
||||
'concurrent-initial-prototype-change-2': [SKIP],
|
||||
'concurrent-initial-prototype-change': [SKIP],
|
||||
'regress/regress-356053': [SKIP],
|
||||
'regress/regress-embedded-cons-string': [SKIP],
|
||||
|
||||
|
@ -54,14 +54,14 @@ INCOMPATIBLE_FLAGS_PER_VARIANT = {
|
||||
"nooptimization": ["--opt", "--always-opt", "--no-liftoff", "--wasm-tier-up"],
|
||||
"slow_path": ["--no-force-slow-path"],
|
||||
"stress_concurrent_allocation": ["--single-threaded-gc", "--predictable"],
|
||||
"stress_concurrent_inlining": ["--single-threaded", "--predictable", "--no-turbo-direct-heap-access"],
|
||||
"stress_concurrent_inlining": ["--single-threaded", "--predictable"],
|
||||
"stress_incremental_marking": ["--no-stress-incremental-marking"],
|
||||
"future": ["--parallel-compile-tasks", "--no-turbo-direct-heap-access"],
|
||||
"future": ["--parallel-compile-tasks"],
|
||||
"stress_js_bg_compile_wasm_code_gc": ["--no-stress-background-compile", "--parallel-compile-tasks"],
|
||||
"stress": ["--no-stress-opt", "--always-opt", "--no-always-opt", "--liftoff", "--max-inlined-bytecode-size=*",
|
||||
"--max-inlined-bytecode-size-cumulative=*", "--stress-inline"],
|
||||
"turboprop": ["--interrupt-budget=*", "--no-turbo-direct-heap-access", "--no-turboprop"],
|
||||
"turboprop_as_toptier": ["--interrupt-budget=*", "--no-turbo-direct-heap-access", "--no-turboprop", "--no-turboprop-as-toptier"],
|
||||
"turboprop": ["--interrupt-budget=*", "--no-turboprop"],
|
||||
"turboprop_as_toptier": ["--interrupt-budget=*", "--no-turboprop", "--no-turboprop-as-toptier"],
|
||||
"code_serializer": ["--cache=after-execute", "--cache=full-code-cache", "--cache=none"],
|
||||
"no_local_heaps": ["--concurrent-inlining", "--turboprop"],
|
||||
"experimental_regexp": ["--no-enable-experimental-regexp-engine", "--no-default-to-experimental-regexp-engine"],
|
||||
@ -96,7 +96,7 @@ INCOMPATIBLE_FLAGS_PER_EXTRA_FLAG = {
|
||||
"--stress_concurrent_allocation": ["--single-threaded-gc", "--predictable"],
|
||||
"--stress_concurrent_inlining": ["--single-threaded", "--predictable"],
|
||||
"--stress-flush-bytecode": ["--no-stress-flush-bytecode"],
|
||||
"--future": ["--parallel-compile-tasks", "--no-turbo-direct-heap-access"],
|
||||
"--future": ["--parallel-compile-tasks"],
|
||||
"--stress-incremental-marking": INCOMPATIBLE_FLAGS_PER_VARIANT["stress_incremental_marking"],
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user