Commit 9905c0b3 authored by Mike Stanton's avatar Mike Stanton Committed by V8 LUCI CQ

[compiler] Mark HeapNumberRef as never serialized

This CL simplifies the approach to HeapNumbers in concurrent
compilation. We'll only create a HeapNumberRef for immutable
HeapNumbers -- this means that we don't need to validate the read
of the value with a compilation dependency check. Mutable
HeapNumbers are handled differently (the value is read for
constant folding, and protected with a constant field dependency).

This CL includes 2 reverts:
Revert "[compiler] Make HeapNumberRef background serialized"
Revert "[compiler] Fix endianness issue when reading HeapNumber"

Bug: v8:7790
Change-Id: I24e65583b787c214b917e96e789d711c2a7c9694
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2891576
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74567}
parent add69092
...@@ -227,22 +227,6 @@ class ConstantInDictionaryPrototypeChainDependency final ...@@ -227,22 +227,6 @@ class ConstantInDictionaryPrototypeChainDependency final
PropertyKind kind_; PropertyKind kind_;
}; };
class HeapNumberValueDependency final : public CompilationDependency {
public:
HeapNumberValueDependency(Handle<HeapNumber> number, uint64_t value)
: number_(number), value_(value) {}
bool IsValid() const override { return number_->value_as_bits() == value_; }
void Install(const MaybeObjectHandle& code) const override {
SLOW_DCHECK(IsValid());
}
private:
Handle<HeapNumber> number_;
const uint64_t value_;
};
class TransitionDependency final : public CompilationDependency { class TransitionDependency final : public CompilationDependency {
public: public:
explicit TransitionDependency(const MapRef& map) : map_(map) { explicit TransitionDependency(const MapRef& map) : map_(map) {
...@@ -764,11 +748,6 @@ CompilationDependencies::DependOnInitialMapInstanceSizePrediction( ...@@ -764,11 +748,6 @@ CompilationDependencies::DependOnInitialMapInstanceSizePrediction(
return SlackTrackingPrediction(initial_map, instance_size); return SlackTrackingPrediction(initial_map, instance_size);
} }
void CompilationDependencies::DependOnHeapNumberValue(Handle<HeapNumber> number,
uint64_t value) {
RecordDependency(zone_->New<HeapNumberValueDependency>(number, value));
}
CompilationDependency const* CompilationDependency const*
CompilationDependencies::TransitionDependencyOffTheRecord( CompilationDependencies::TransitionDependencyOffTheRecord(
const MapRef& target_map) const { const MapRef& target_map) const {
......
...@@ -97,10 +97,6 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject { ...@@ -97,10 +97,6 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
// Record the assumption that {site}'s {ElementsKind} doesn't change. // Record the assumption that {site}'s {ElementsKind} doesn't change.
void DependOnElementsKind(const AllocationSiteRef& site); void DependOnElementsKind(const AllocationSiteRef& site);
// HeapNumber::value() when read from the background thread may be
// invalid, and must be checked at the end of compilation.
void DependOnHeapNumberValue(Handle<HeapNumber> number, uint64_t value);
// For each given map, depend on the stability of (the maps of) all prototypes // For each given map, depend on the stability of (the maps of) all prototypes
// up to (and including) the {last_prototype}. // up to (and including) the {last_prototype}.
template <class MapContainer> template <class MapContainer>
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "src/api/api-inl.h" #include "src/api/api-inl.h"
#include "src/ast/modules.h" #include "src/ast/modules.h"
#include "src/codegen/code-factory.h" #include "src/codegen/code-factory.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/graph-reducer.h" #include "src/compiler/graph-reducer.h"
#include "src/compiler/js-heap-broker.h" #include "src/compiler/js-heap-broker.h"
#include "src/execution/protectors-inl.h" #include "src/execution/protectors-inl.h"
...@@ -73,10 +72,8 @@ namespace { ...@@ -73,10 +72,8 @@ namespace {
bool IsReadOnlyHeapObject(Object object) { bool IsReadOnlyHeapObject(Object object) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
// HeapNumber is excluded because we have a uniform background
// serialization treatment for it.
return (object.IsCode() && Code::cast(object).is_builtin()) || return (object.IsCode() && Code::cast(object).is_builtin()) ||
(object.IsHeapObject() && !object.IsHeapNumber() && (object.IsHeapObject() &&
ReadOnlyHeap::Contains(HeapObject::cast(object))); ReadOnlyHeap::Contains(HeapObject::cast(object)));
} }
...@@ -757,29 +754,18 @@ class RegExpBoilerplateDescriptionData : public HeapObjectData { ...@@ -757,29 +754,18 @@ class RegExpBoilerplateDescriptionData : public HeapObjectData {
int flags_; int flags_;
}; };
// for HeapNumber, we should always read from the Data object, which records
// the one time we read the value, possibly on main thread (in the case of
// bytecode serialization), or possibly on the background thread. The read of
// this value has no guarantee of being correct. Therefore, instantiation of
// a HeapNumberData must be associated with the creation of a compilation
// dependency which will check later on the main thread if the bits of the
// heap number are exactly correct.
class HeapNumberData : public HeapObjectData { class HeapNumberData : public HeapObjectData {
public: public:
HeapNumberData(JSHeapBroker* broker, ObjectData** storage, HeapNumberData(JSHeapBroker* broker, ObjectData** storage,
Handle<HeapNumber> object, Handle<HeapNumber> object,
ObjectDataKind kind = ObjectDataKind::kSerializedHeapObject) ObjectDataKind kind = ObjectDataKind::kSerializedHeapObject)
: HeapObjectData(broker, storage, object, kind) { : HeapObjectData(broker, storage, object, kind),
const uint64_t value_as_bits = object->value_as_bits_relaxed(); value_(object->value()) {}
STATIC_ASSERT(sizeof(value_) == sizeof(value_as_bits));
value_ = *reinterpret_cast<const double*>(&value_as_bits);
broker->dependencies()->DependOnHeapNumberValue(object, value_as_bits);
}
double value() const { return value_; } double value() const { return value_; }
private: private:
double value_; double const value_;
}; };
class ContextData : public HeapObjectData { class ContextData : public HeapObjectData {
...@@ -3299,15 +3285,7 @@ BIMODAL_ACCESSOR_C(FeedbackVector, double, invocation_count) ...@@ -3299,15 +3285,7 @@ BIMODAL_ACCESSOR_C(FeedbackVector, double, invocation_count)
BIMODAL_ACCESSOR(HeapObject, Map, map) BIMODAL_ACCESSOR(HeapObject, Map, map)
double HeapNumberRef::value() const { BIMODAL_ACCESSOR_C(HeapNumber, double, value)
if (data_->should_access_heap()) {
// TODO(mvstanton): it would make things simpler to eliminate the
// kUnserializedHeapObject case, even for OSR compiles.
CHECK_EQ(data_->kind(), kUnserializedHeapObject);
return object()->value();
}
return ObjectRef::data()->AsHeapNumber()->value();
}
// These JSBoundFunction fields are immutable after initialization. Moreover, // These JSBoundFunction fields are immutable after initialization. Moreover,
// as long as JSObjects are still serialized on the main thread, all // as long as JSObjects are still serialized on the main thread, all
......
...@@ -123,7 +123,7 @@ enum class RefSerializationKind { ...@@ -123,7 +123,7 @@ enum class RefSerializationKind {
V(FeedbackVector, RefSerializationKind::kNeverSerialized) \ V(FeedbackVector, RefSerializationKind::kNeverSerialized) \
V(FixedArrayBase, RefSerializationKind::kBackgroundSerialized) \ V(FixedArrayBase, RefSerializationKind::kBackgroundSerialized) \
V(FunctionTemplateInfo, RefSerializationKind::kNeverSerialized) \ V(FunctionTemplateInfo, RefSerializationKind::kNeverSerialized) \
V(HeapNumber, RefSerializationKind::kBackgroundSerialized) \ V(HeapNumber, RefSerializationKind::kNeverSerialized) \
V(JSReceiver, RefSerializationKind::kBackgroundSerialized) \ V(JSReceiver, RefSerializationKind::kBackgroundSerialized) \
V(Map, RefSerializationKind::kBackgroundSerialized) \ V(Map, RefSerializationKind::kBackgroundSerialized) \
V(Name, RefSerializationKind::kNeverSerialized) \ V(Name, RefSerializationKind::kNeverSerialized) \
...@@ -429,6 +429,11 @@ class RegExpBoilerplateDescriptionRef : public HeapObjectRef { ...@@ -429,6 +429,11 @@ class RegExpBoilerplateDescriptionRef : public HeapObjectRef {
int flags() const; int flags() const;
}; };
// HeapNumberRef is only created for immutable HeapNumbers. Mutable
// HeapNumbers (those owned by in-object or backing store fields with
// representation type Double are not exposed to the compiler through
// HeapNumberRef. Instead, we read their value, and protect that read
// with a field-constness Dependency.
class HeapNumberRef : public HeapObjectRef { class HeapNumberRef : public HeapObjectRef {
public: public:
DEFINE_REF_CONSTRUCTOR(HeapNumber, HeapObjectRef) DEFINE_REF_CONSTRUCTOR(HeapNumber, HeapObjectRef)
......
...@@ -348,16 +348,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker { ...@@ -348,16 +348,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
RootIndexMap const& root_index_map() { return root_index_map_; } RootIndexMap const& root_index_map() { return root_index_map_; }
CompilationDependencies* dependencies() const {
DCHECK_NOT_NULL(dependencies_);
return dependencies_;
}
void set_dependencies(CompilationDependencies* dependencies) {
DCHECK_NULL(dependencies_);
dependencies_ = dependencies;
}
class MapUpdaterMutexDepthScope final { class MapUpdaterMutexDepthScope final {
public: public:
explicit MapUpdaterMutexDepthScope(JSHeapBroker* ptr) explicit MapUpdaterMutexDepthScope(JSHeapBroker* ptr)
...@@ -451,7 +441,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker { ...@@ -451,7 +441,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
Isolate* const isolate_; Isolate* const isolate_;
Zone* const zone_ = nullptr; Zone* const zone_ = nullptr;
CompilationDependencies* dependencies_ = nullptr;
base::Optional<NativeContextRef> target_native_context_; base::Optional<NativeContextRef> target_native_context_;
RefsMap* refs_; RefsMap* refs_;
RootIndexMap root_index_map_; RootIndexMap root_index_map_;
......
...@@ -183,7 +183,6 @@ class PipelineData { ...@@ -183,7 +183,6 @@ class PipelineData {
: nullptr; : nullptr;
dependencies_ = dependencies_ =
info_->zone()->New<CompilationDependencies>(broker_, info_->zone()); info_->zone()->New<CompilationDependencies>(broker_, info_->zone());
broker_->set_dependencies(dependencies_);
} }
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
......
...@@ -25,20 +25,6 @@ uint64_t HeapNumber::value_as_bits() const { ...@@ -25,20 +25,6 @@ uint64_t HeapNumber::value_as_bits() const {
return base::ReadUnalignedValue<uint64_t>(field_address(kValueOffset)); return base::ReadUnalignedValue<uint64_t>(field_address(kValueOffset));
} }
uint64_t HeapNumber::value_as_bits_relaxed() const {
#if defined(V8_TARGET_BIG_ENDIAN)
return (static_cast<uint64_t>(RELAXED_READ_UINT32_FIELD(*this, kValueOffset))
<< 32) |
static_cast<uint64_t>(
RELAXED_READ_UINT32_FIELD(*this, kValueOffset + kUInt32Size));
#else
return static_cast<uint64_t>(RELAXED_READ_UINT32_FIELD(*this, kValueOffset)) |
(static_cast<uint64_t>(
RELAXED_READ_UINT32_FIELD(*this, kValueOffset + kUInt32Size))
<< 32);
#endif
}
void HeapNumber::set_value_as_bits(uint64_t bits) { void HeapNumber::set_value_as_bits(uint64_t bits) {
base::WriteUnalignedValue<uint64_t>(field_address(kValueOffset), bits); base::WriteUnalignedValue<uint64_t>(field_address(kValueOffset), bits);
} }
......
...@@ -20,7 +20,6 @@ namespace internal { ...@@ -20,7 +20,6 @@ namespace internal {
class HeapNumber class HeapNumber
: public TorqueGeneratedHeapNumber<HeapNumber, PrimitiveHeapObject> { : public TorqueGeneratedHeapNumber<HeapNumber, PrimitiveHeapObject> {
public: public:
inline uint64_t value_as_bits_relaxed() const;
inline uint64_t value_as_bits() const; inline uint64_t value_as_bits() const;
inline void set_value_as_bits(uint64_t bits); inline void set_value_as_bits(uint64_t bits);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment