summaryrefslogtreecommitdiff
path: root/chromium/v8/src/compiler/js-heap-broker.h
blob: ffc10d2b93a023c8d17bafeecfdb0d0aef2f8825 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// 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_