blob: ffc10d2b93a023c8d17bafeecfdb0d0aef2f8825 [file] [log] [blame]
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_JS_HEAP_BROKER_H_
#define V8_COMPILER_JS_HEAP_BROKER_H_
#include "src/base/compiler-specific.h"
#include "src/base/optional.h"
#include "src/common/globals.h"
#include "src/compiler/access-info.h"
#include "src/compiler/refs-map.h"
#include "src/handles/handles.h"
#include "src/interpreter/bytecode-array-accessor.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/function-kind.h"
#include "src/objects/objects.h"
#include "src/utils/ostreams.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
namespace compiler {
class BytecodeAnalysis;
class ObjectRef;
std::ostream& operator<<(std::ostream& os, const ObjectRef& ref);
struct FeedbackSource {
FeedbackSource(Handle<FeedbackVector> vector_, FeedbackSlot slot_)
: vector(vector_), slot(slot_) {}
explicit FeedbackSource(FeedbackNexus const& nexus);
explicit FeedbackSource(VectorSlotPair const& pair);
Handle<FeedbackVector> const vector;
FeedbackSlot const slot;
struct Hash {
size_t operator()(FeedbackSource const& source) const {
return base::hash_combine(source.vector.address(), source.slot);
}
};
struct Equal {
bool operator()(FeedbackSource const& lhs,
FeedbackSource const& rhs) const {
return lhs.vector.equals(rhs.vector) && lhs.slot == rhs.slot;
}
};
};
#define TRACE_BROKER(broker, x) \
do { \
if (broker->tracing_enabled() && FLAG_trace_heap_broker_verbose) \
broker->Trace() << x << '\n'; \
} while (false)
#define TRACE_BROKER_MISSING(broker, x) \
do { \
if (broker->tracing_enabled()) \
broker->Trace() << __FUNCTION__ << ": missing " << x << '\n'; \
} while (false)
class V8_EXPORT_PRIVATE JSHeapBroker {
public:
JSHeapBroker(Isolate* isolate, Zone* broker_zone, bool tracing_enabled);
void SetNativeContextRef();
void SerializeStandardObjects();
Isolate* isolate() const { return isolate_; }
Zone* zone() const { return current_zone_; }
bool tracing_enabled() const { return tracing_enabled_; }
NativeContextRef native_context() const { return native_context_.value(); }
PerIsolateCompilerCache* compiler_cache() const { return compiler_cache_; }
enum BrokerMode { kDisabled, kSerializing, kSerialized, kRetired };
BrokerMode mode() const { return mode_; }
void StartSerializing();
void StopSerializing();
void Retire();
bool SerializingAllowed() const;
// Returns nullptr iff handle unknown.
ObjectData* GetData(Handle<Object>) const;
// Never returns nullptr.
ObjectData* GetOrCreateData(Handle<Object>);
// Like the previous but wraps argument in handle first (for convenience).
ObjectData* GetOrCreateData(Object);
// Check if {object} is any native context's %ArrayPrototype% or
// %ObjectPrototype%.
bool IsArrayOrObjectPrototype(const JSObjectRef& object) const;
bool HasFeedback(FeedbackSource const& source) const;
// The processed {feedback} can be {nullptr}, indicating that the original
// feedback didn't contain information relevant for Turbofan.
void SetFeedback(FeedbackSource const& source,
ProcessedFeedback const* feedback);
ProcessedFeedback const* GetFeedback(FeedbackSource const& source) const;
// Convenience wrappers around GetFeedback.
GlobalAccessFeedback const* GetGlobalAccessFeedback(
FeedbackSource const& source) const;
// TODO(neis): Move these into serializer when we're always in the background.
ElementAccessFeedback const* ProcessFeedbackMapsForElementAccess(
MapHandles const& maps, KeyedAccessMode const& keyed_mode);
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(
FeedbackSource const& source);
BytecodeAnalysis const& GetBytecodeAnalysis(
Handle<BytecodeArray> bytecode_array, BailoutId osr_offset,
bool analyze_liveness, bool serialize);
base::Optional<NameRef> GetNameFeedback(FeedbackNexus const& nexus);
// If there is no result stored for {map}, we return an Invalid
// PropertyAccessInfo.
PropertyAccessInfo GetAccessInfoForLoadingThen(MapRef map);
void CreateAccessInfoForLoadingThen(MapRef map,
CompilationDependencies* dependencies);
PropertyAccessInfo GetAccessInfoForLoadingExec(MapRef map);
PropertyAccessInfo const& CreateAccessInfoForLoadingExec(
MapRef map, CompilationDependencies* dependencies);
std::ostream& Trace();
void IncrementTracingIndentation();
void DecrementTracingIndentation();
private:
friend class HeapObjectRef;
friend class ObjectRef;
friend class ObjectData;
void SerializeShareableObjects();
void CollectArrayAndObjectPrototypes();
Isolate* const isolate_;
Zone* const broker_zone_;
Zone* current_zone_;
base::Optional<NativeContextRef> native_context_;
RefsMap* refs_;
ZoneUnorderedSet<Handle<JSObject>, Handle<JSObject>::hash,
Handle<JSObject>::equal_to>
array_and_object_prototypes_;
BrokerMode mode_ = kDisabled;
bool const tracing_enabled_;
StdoutStream trace_out_;
unsigned trace_indentation_ = 0;
PerIsolateCompilerCache* compiler_cache_;
ZoneUnorderedMap<FeedbackSource, ProcessedFeedback const*,
FeedbackSource::Hash, FeedbackSource::Equal>
feedback_;
ZoneUnorderedMap<ObjectData*, BytecodeAnalysis*> bytecode_analyses_;
typedef ZoneUnorderedMap<MapRef, PropertyAccessInfo, ObjectRef::Hash,
ObjectRef::Equal>
MapToAccessInfos;
MapToAccessInfos ais_for_loading_then_;
MapToAccessInfos ais_for_loading_exec_;
static const size_t kMinimalRefsBucketCount = 8; // must be power of 2
static const size_t kInitialRefsBucketCount = 1024; // must be power of 2
};
class TraceScope {
public:
TraceScope(JSHeapBroker* broker, const char* label)
: TraceScope(broker, static_cast<void*>(broker), label) {}
TraceScope(JSHeapBroker* broker, ObjectData* data, const char* label)
: TraceScope(broker, static_cast<void*>(data), label) {}
TraceScope(JSHeapBroker* broker, void* subject, const char* label)
: broker_(broker) {
TRACE_BROKER(broker_, "Running " << label << " on " << subject);
broker_->IncrementTracingIndentation();
}
~TraceScope() { broker_->DecrementTracingIndentation(); }
private:
JSHeapBroker* const broker_;
};
#define ASSIGN_RETURN_NO_CHANGE_IF_DATA_MISSING(something_var, \
optionally_something) \
auto optionally_something_ = optionally_something; \
if (!optionally_something_) \
return NoChangeBecauseOfMissingData(broker(), __FUNCTION__, __LINE__); \
something_var = *optionally_something_;
class Reduction;
Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
const char* function, int line);
// Miscellaneous definitions that should be moved elsewhere once concurrent
// compilation is finished.
bool CanInlineElementAccess(MapRef const& map);
class OffHeapBytecodeArray final : public interpreter::AbstractBytecodeArray {
public:
explicit OffHeapBytecodeArray(BytecodeArrayRef bytecode_array);
int length() const override;
int parameter_count() const override;
uint8_t get(int index) const override;
void set(int index, uint8_t value) override;
Address GetFirstBytecodeAddress() const override;
Handle<Object> GetConstantAtIndex(int index, Isolate* isolate) const override;
bool IsConstantAtIndexSmi(int index) const override;
Smi GetConstantAtIndexAsSmi(int index) const override;
private:
BytecodeArrayRef array_;
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_JS_HEAP_BROKER_H_