js-heap-broker.h 19.8 KB
Newer Older
1 2 3 4 5 6 7 8
// 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"
9
#include "src/base/optional.h"
10
#include "src/compiler/refs-map.h"
11
#include "src/globals.h"
12
#include "src/handles.h"
13
#include "src/objects.h"
14
#include "src/objects/builtin-function-id.h"
15
#include "src/objects/instance-type.h"
16
#include "src/zone/zone-containers.h"
17 18 19

namespace v8 {
namespace internal {
20 21 22 23

class BytecodeArray;
class FixedDoubleArray;
class InternalizedString;
24
class JSBoundFunction;
25
class JSDataView;
26 27 28 29 30 31
class JSGlobalProxy;
class JSRegExp;
class JSTypedArray;
class NativeContext;
class ScriptContextTable;

32 33
namespace compiler {

34 35 36 37 38 39
enum class OddballType : uint8_t {
  kNone,     // Not an Oddball.
  kBoolean,  // True or False.
  kUndefined,
  kNull,
  kHole,
40
  kUninitialized,
41
  kOther  // Oddball, but none of the above.
42 43
};

44 45
// This list is sorted such that subtypes appear before their supertypes.
// DO NOT VIOLATE THIS PROPERTY!
46
#define HEAP_BROKER_OBJECT_LIST(V) \
47 48
  /* Subtypes of JSObject */       \
  V(JSArray)                       \
49
  V(JSBoundFunction)               \
50
  V(JSDataView)                    \
51 52 53
  V(JSFunction)                    \
  V(JSGlobalProxy)                 \
  V(JSRegExp)                      \
54
  V(JSTypedArray)                  \
55 56
  /* Subtypes of Context */        \
  V(NativeContext)                 \
57 58 59 60
  /* Subtypes of FixedArray */     \
  V(Context)                       \
  V(ScopeInfo)                     \
  V(ScriptContextTable)            \
61
  /* Subtypes of FixedArrayBase */ \
62
  V(BytecodeArray)                 \
63 64 65 66 67 68 69
  V(FixedArray)                    \
  V(FixedDoubleArray)              \
  /* Subtypes of Name */           \
  V(InternalizedString)            \
  V(String)                        \
  /* Subtypes of HeapObject */     \
  V(AllocationSite)                \
70 71
  V(Cell)                          \
  V(Code)                          \
72
  V(DescriptorArray)               \
73 74 75 76
  V(FeedbackVector)                \
  V(FixedArrayBase)                \
  V(HeapNumber)                    \
  V(JSObject)                      \
77 78
  V(Map)                           \
  V(Module)                        \
79 80 81
  V(MutableHeapNumber)             \
  V(Name)                          \
  V(PropertyCell)                  \
82
  V(SharedFunctionInfo)            \
83 84
  /* Subtypes of Object */         \
  V(HeapObject)
85

86 87
class CompilationDependencies;
class JSHeapBroker;
88
class ObjectData;
89
class PerIsolateCompilerCache;
90
#define FORWARD_DECL(Name) class Name##Ref;
91
HEAP_BROKER_OBJECT_LIST(FORWARD_DECL)
92 93
#undef FORWARD_DECL

94
class ObjectRef {
95
 public:
96
  ObjectRef(JSHeapBroker* broker, Handle<Object> object);
97
  ObjectRef(JSHeapBroker* broker, ObjectData* data)
98
      : data_(data), broker_(broker) {
99 100
    CHECK_NOT_NULL(data_);
  }
101 102

  Handle<Object> object() const;
103 104

  bool equals(const ObjectRef& other) const;
105 106 107

  bool IsSmi() const;
  int AsSmi() const;
108

109
#define HEAP_IS_METHOD_DECL(Name) bool Is##Name() const;
110
  HEAP_BROKER_OBJECT_LIST(HEAP_IS_METHOD_DECL)
111 112
#undef HEAP_IS_METHOD_DECL

113
#define HEAP_AS_METHOD_DECL(Name) Name##Ref As##Name() const;
114
  HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL)
115 116
#undef HEAP_AS_METHOD_DECL

117 118
  bool IsNullOrUndefined() const;

119
  bool BooleanValue() const;
120 121
  double OddballToNumber() const;

122 123
  Isolate* isolate() const;

124
 protected:
125 126
  JSHeapBroker* broker() const;
  ObjectData* data() const;
127
  ObjectData* data_;  // Should be used only by object() getters.
128

129
 private:
130
  JSHeapBroker* broker_;
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
// Temporary class that carries information from a Map. We'd like to remove
// this class and use MapRef instead, but we can't as long as we support the
// kDisabled broker mode. That's because obtaining the MapRef via
// HeapObjectRef::map() requires a HandleScope when the broker is disabled.
// During OptimizeGraph we generally don't have a HandleScope, however. There
// are two places where we therefore use GetHeapObjectType() instead. Both that
// function and this class should eventually be removed.
class HeapObjectType {
 public:
  enum Flag : uint8_t { kUndetectable = 1 << 0, kCallable = 1 << 1 };

  typedef base::Flags<Flag> Flags;

  HeapObjectType(InstanceType instance_type, Flags flags,
                 OddballType oddball_type)
      : instance_type_(instance_type),
        oddball_type_(oddball_type),
        flags_(flags) {
    DCHECK_EQ(instance_type == ODDBALL_TYPE,
              oddball_type != OddballType::kNone);
  }

  OddballType oddball_type() const { return oddball_type_; }
  InstanceType instance_type() const { return instance_type_; }
  Flags flags() const { return flags_; }

  bool is_callable() const { return flags_ & kCallable; }
  bool is_undetectable() const { return flags_ & kUndetectable; }

 private:
  InstanceType const instance_type_;
  OddballType const oddball_type_;
  Flags const flags_;
};

168 169
class HeapObjectRef : public ObjectRef {
 public:
170
  using ObjectRef::ObjectRef;
171
  Handle<HeapObject> object() const;
172

173
  MapRef map() const;
174 175 176

  // See the comment on the HeapObjectType class.
  HeapObjectType GetHeapObjectType() const;
177 178
};

179 180 181
class PropertyCellRef : public HeapObjectRef {
 public:
  using HeapObjectRef::HeapObjectRef;
182
  Handle<PropertyCell> object() const;
183 184

  PropertyDetails property_details() const;
185
  ObjectRef value() const;
186 187
};

188 189
class JSObjectRef : public HeapObjectRef {
 public:
190
  using HeapObjectRef::HeapObjectRef;
191
  Handle<JSObject> object() const;
192 193

  double RawFastDoublePropertyAt(FieldIndex index) const;
194
  ObjectRef RawFastPropertyAt(FieldIndex index) const;
195

196 197
  FixedArrayBaseRef elements() const;
  void EnsureElementsTenured();
198
  ElementsKind GetElementsKind() const;
199 200 201

  void SerializeObjectCreateMap();
  base::Optional<MapRef> GetObjectCreateMap() const;
202 203
};

204 205 206 207 208 209 210 211 212
class JSDataViewRef : public JSObjectRef {
 public:
  using JSObjectRef::JSObjectRef;
  Handle<JSDataView> object() const;

  size_t byte_length() const;
  size_t byte_offset() const;
};

213 214 215 216 217 218 219 220 221 222 223 224 225
class JSBoundFunctionRef : public JSObjectRef {
 public:
  using JSObjectRef::JSObjectRef;
  Handle<JSBoundFunction> object() const;

  void Serialize();

  // The following are available only after calling Serialize().
  ObjectRef bound_target_function() const;
  ObjectRef bound_this() const;
  FixedArrayRef bound_arguments() const;
};

226
class JSFunctionRef : public JSObjectRef {
227
 public:
228
  using JSObjectRef::JSObjectRef;
229
  Handle<JSFunction> object() const;
230 231

  bool has_initial_map() const;
232 233
  bool has_prototype() const;
  bool PrototypeRequiresRuntimeLookup() const;
234 235 236 237 238 239

  void Serialize();

  // The following are available only after calling Serialize().
  ObjectRef prototype() const;
  MapRef initial_map() const;
240
  ContextRef context() const;
241
  NativeContextRef native_context() const;
242
  SharedFunctionInfoRef shared() const;
243
  int InitialMapInstanceSizeWithMinSlack() const;
244 245
};

246 247
class JSRegExpRef : public JSObjectRef {
 public:
248
  using JSObjectRef::JSObjectRef;
249
  Handle<JSRegExp> object() const;
250

251 252 253 254 255
  ObjectRef raw_properties_or_hash() const;
  ObjectRef data() const;
  ObjectRef source() const;
  ObjectRef flags() const;
  ObjectRef last_index() const;
256 257
};

258
class HeapNumberRef : public HeapObjectRef {
259
 public:
260
  using HeapObjectRef::HeapObjectRef;
261
  Handle<HeapNumber> object() const;
262

263
  double value() const;
264 265
};

266 267
class MutableHeapNumberRef : public HeapObjectRef {
 public:
268
  using HeapObjectRef::HeapObjectRef;
269
  Handle<MutableHeapNumber> object() const;
270

271 272 273
  double value() const;
};

274
class ContextRef : public HeapObjectRef {
275
 public:
276
  using HeapObjectRef::HeapObjectRef;
277
  Handle<Context> object() const;
278

279
  void Serialize();
280
  ContextRef previous() const;
281
  ObjectRef get(int index) const;
282 283
};

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
#define BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V)                    \
  V(JSFunction, array_function)                                       \
  V(JSFunction, boolean_function)                                     \
  V(JSFunction, bigint_function)                                      \
  V(JSFunction, number_function)                                      \
  V(JSFunction, object_function)                                      \
  V(JSFunction, promise_function)                                     \
  V(JSFunction, promise_then)                                         \
  V(JSFunction, string_function)                                      \
  V(JSFunction, symbol_function)                                      \
  V(JSGlobalProxy, global_proxy_object)                               \
  V(JSObject, promise_prototype)                                      \
  V(Map, bound_function_with_constructor_map)                         \
  V(Map, bound_function_without_constructor_map)                      \
  V(Map, fast_aliased_arguments_map)                                  \
  V(Map, initial_array_iterator_map)                                  \
  V(Map, initial_string_iterator_map)                                 \
  V(Map, iterator_result_map)                                         \
  V(Map, js_array_holey_double_elements_map)                          \
  V(Map, js_array_holey_elements_map)                                 \
  V(Map, js_array_holey_smi_elements_map)                             \
  V(Map, js_array_packed_double_elements_map)                         \
  V(Map, js_array_packed_elements_map)                                \
  V(Map, js_array_packed_smi_elements_map)                            \
  V(Map, sloppy_arguments_map)                                        \
  V(Map, slow_object_with_null_prototype_map)                         \
  V(Map, strict_arguments_map)                                        \
  V(ScriptContextTable, script_context_table)                         \
  V(SharedFunctionInfo, promise_capability_default_reject_shared_fun) \
  V(SharedFunctionInfo, promise_catch_finally_shared_fun)             \
  V(SharedFunctionInfo, promise_then_finally_shared_fun)              \
  V(SharedFunctionInfo, promise_capability_default_resolve_shared_fun)
316

317 318 319
// Those are set by Bootstrapper::ExportFromRuntime, which may not yet have
// happened when Turbofan is invoked via --always-opt.
#define BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(V) \
320
  V(Map, async_function_object_map)              \
321 322 323 324 325 326 327 328 329 330
  V(Map, map_key_iterator_map)                   \
  V(Map, map_key_value_iterator_map)             \
  V(Map, map_value_iterator_map)                 \
  V(Map, set_key_value_iterator_map)             \
  V(Map, set_value_iterator_map)

#define BROKER_NATIVE_CONTEXT_FIELDS(V)      \
  BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \
  BROKER_OPTIONAL_NATIVE_CONTEXT_FIELDS(V)

331 332
class NativeContextRef : public ContextRef {
 public:
333
  using ContextRef::ContextRef;
334 335
  Handle<NativeContext> object() const;

336
  void Serialize();
337

338 339 340
#define DECL_ACCESSOR(type, name) type##Ref name() const;
  BROKER_NATIVE_CONTEXT_FIELDS(DECL_ACCESSOR)
#undef DECL_ACCESSOR
341

342
  MapRef GetFunctionMapFromIndex(int index) const;
343
  MapRef GetInitialJSArrayMap(ElementsKind kind) const;
344
  base::Optional<JSFunctionRef> GetConstructorFunction(const MapRef& map) const;
345 346 347 348
};

class NameRef : public HeapObjectRef {
 public:
349
  using HeapObjectRef::HeapObjectRef;
350
  Handle<Name> object() const;
351 352 353 354
};

class ScriptContextTableRef : public HeapObjectRef {
 public:
355
  using HeapObjectRef::HeapObjectRef;
356
  Handle<ScriptContextTable> object() const;
357 358 359 360 361 362 363 364

  struct LookupResult {
    ContextRef context;
    bool immutable;
    int index;
  };

  base::Optional<LookupResult> lookup(const NameRef& name) const;
365 366
};

367 368 369
class DescriptorArrayRef : public HeapObjectRef {
 public:
  using HeapObjectRef::HeapObjectRef;
370
  Handle<DescriptorArray> object() const;
371 372
};

373 374
class FeedbackVectorRef : public HeapObjectRef {
 public:
375
  using HeapObjectRef::HeapObjectRef;
376
  Handle<FeedbackVector> object() const;
377

378
  ObjectRef get(FeedbackSlot slot) const;
379 380

  void SerializeSlots();
381 382 383 384
};

class AllocationSiteRef : public HeapObjectRef {
 public:
385
  using HeapObjectRef::HeapObjectRef;
386
  Handle<AllocationSite> object() const;
387

388
  bool PointsToLiteral() const;
389
  PretenureFlag GetPretenureMode() const;
390
  ObjectRef nested_site() const;
391 392 393 394 395 396 397 398 399 400

  // {IsFastLiteral} 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.
  //
  // If PointsToLiteral() is false, then IsFastLiteral() is also false.
  bool IsFastLiteral() const;
  // We only serialize boilerplate if IsFastLiteral is true.
  base::Optional<JSObjectRef> boilerplate() const;

401
  ElementsKind GetElementsKind() const;
402
  bool CanInlineCall() const;
403 404 405 406
};

class MapRef : public HeapObjectRef {
 public:
407
  using HeapObjectRef::HeapObjectRef;
408
  Handle<Map> object() const;
409 410 411 412

  int instance_size() const;
  InstanceType instance_type() const;
  int GetInObjectProperties() const;
413
  int GetInObjectPropertiesStartInWords() const;
414
  int NumberOfOwnDescriptors() const;
415
  int GetInObjectPropertyOffset(int index) const;
416
  int constructor_function_index() const;
417
  ElementsKind elements_kind() const;
418
  bool is_stable() const;
419
  bool is_extensible() const;
420
  bool is_constructor() const;
421
  bool has_prototype_slot() const;
422
  bool is_access_check_needed() const;
423 424
  bool is_deprecated() const;
  bool CanBeDeprecated() const;
425
  bool CanTransition() const;
426
  bool IsInobjectSlackTrackingInProgress() const;
427
  bool is_dictionary_map() const;
428
  bool IsFixedCowArrayMap() const;
429
  bool IsPrimitiveMap() const;
430 431
  bool is_undetectable() const;
  bool is_callable() const;
432
  bool has_hidden_prototype() const;
433

434 435 436 437
#define DEF_TESTER(Type, ...) bool Is##Type##Map() const;
  INSTANCE_TYPE_CHECKERS(DEF_TESTER)
#undef DEF_TESTER

438
  ObjectRef GetConstructor() const;
439 440

  void SerializePrototype();
441
  ObjectRef prototype() const;
442

443 444
  OddballType oddball_type() const;

445 446
  base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;

447
  // Concerning the underlying instance_descriptors:
448
  void SerializeOwnDescriptors();
449 450 451 452 453
  MapRef FindFieldOwner(int descriptor_index) const;
  PropertyDetails GetPropertyDetails(int descriptor_index) const;
  NameRef GetPropertyKey(int descriptor_index) const;
  FieldIndex GetFieldIndexFor(int descriptor_index) const;
  ObjectRef GetFieldType(int descriptor_index) const;
454
  bool IsUnboxedDoubleField(int descriptor_index) const;
455 456 457 458
};

class FixedArrayBaseRef : public HeapObjectRef {
 public:
459
  using HeapObjectRef::HeapObjectRef;
460
  Handle<FixedArrayBase> object() const;
461 462 463 464 465 466

  int length() const;
};

class FixedArrayRef : public FixedArrayBaseRef {
 public:
467
  using FixedArrayBaseRef::FixedArrayBaseRef;
468
  Handle<FixedArray> object() const;
469

470
  ObjectRef get(int i) const;
471 472 473 474
};

class FixedDoubleArrayRef : public FixedArrayBaseRef {
 public:
475
  using FixedArrayBaseRef::FixedArrayBaseRef;
476
  Handle<FixedDoubleArray> object() const;
477 478

  double get_scalar(int i) const;
479
  bool is_the_hole(int i) const;
480 481
};

482 483 484
class BytecodeArrayRef : public FixedArrayBaseRef {
 public:
  using FixedArrayBaseRef::FixedArrayBaseRef;
485
  Handle<BytecodeArray> object() const;
486 487 488 489

  int register_count() const;
};

490 491
class JSArrayRef : public JSObjectRef {
 public:
492
  using JSObjectRef::JSObjectRef;
493
  Handle<JSArray> object() const;
494

495
  ObjectRef length() const;
496 497
};

498 499
class ScopeInfoRef : public HeapObjectRef {
 public:
500
  using HeapObjectRef::HeapObjectRef;
501
  Handle<ScopeInfo> object() const;
502 503 504 505

  int ContextLength() const;
};

506 507 508 509 510 511 512 513 514 515 516 517 518 519
#define BROKER_SFI_FIELDS(V)                \
  V(int, internal_formal_parameter_count)   \
  V(bool, has_duplicate_parameters)         \
  V(int, function_map_index)                \
  V(FunctionKind, kind)                     \
  V(LanguageMode, language_mode)            \
  V(bool, native)                           \
  V(bool, HasBreakInfo)                     \
  V(bool, HasBuiltinFunctionId)             \
  V(bool, HasBuiltinId)                     \
  V(BuiltinFunctionId, builtin_function_id) \
  V(bool, construct_as_builtin)             \
  V(bool, HasBytecodeArray)

520 521
class SharedFunctionInfoRef : public HeapObjectRef {
 public:
522
  using HeapObjectRef::HeapObjectRef;
523
  Handle<SharedFunctionInfo> object() const;
524

525
  int builtin_id() const;
526
  BytecodeArrayRef GetBytecodeArray() const;
527 528
#define DECL_ACCESSOR(type, name) type name() const;
  BROKER_SFI_FIELDS(DECL_ACCESSOR)
529
#undef DECL_ACCESSOR
530 531
};

532 533
class StringRef : public NameRef {
 public:
534
  using NameRef::NameRef;
535
  Handle<String> object() const;
536 537 538

  int length() const;
  uint16_t GetFirstChar();
539
  base::Optional<double> ToNumber();
540 541
  bool IsSeqString() const;
  bool IsExternalString() const;
542 543
};

544 545 546
class JSTypedArrayRef : public JSObjectRef {
 public:
  using JSObjectRef::JSObjectRef;
547
  Handle<JSTypedArray> object() const;
548 549 550 551 552 553 554 555 556 557

  bool is_on_heap() const;
  size_t length_value() const;
  void* elements_external_pointer() const;

  void Serialize();

  HeapObjectRef buffer() const;
};

558 559
class ModuleRef : public HeapObjectRef {
 public:
560
  using HeapObjectRef::HeapObjectRef;
561
  Handle<Module> object() const;
562

563 564 565
  void Serialize();

  CellRef GetCell(int cell_index) const;
566 567 568 569
};

class CellRef : public HeapObjectRef {
 public:
570
  using HeapObjectRef::HeapObjectRef;
571
  Handle<Cell> object() const;
572 573

  ObjectRef value() const;
574 575 576 577
};

class JSGlobalProxyRef : public JSObjectRef {
 public:
578
  using JSObjectRef::JSObjectRef;
579
  Handle<JSGlobalProxy> object() const;
580 581 582 583
};

class CodeRef : public HeapObjectRef {
 public:
584
  using HeapObjectRef::HeapObjectRef;
585
  Handle<Code> object() const;
586 587
};

588 589 590
class InternalizedStringRef : public StringRef {
 public:
  using StringRef::StringRef;
591
  Handle<InternalizedString> object() const;
592 593 594 595
};

class V8_EXPORT_PRIVATE JSHeapBroker : public NON_EXPORTED_BASE(ZoneObject) {
 public:
596
  JSHeapBroker(Isolate* isolate, Zone* broker_zone);
597
  void SetNativeContextRef();
598
  void SerializeStandardObjects();
599 600

  Isolate* isolate() const { return isolate_; }
601
  Zone* zone() const { return current_zone_; }
602
  NativeContextRef native_context() const { return native_context_.value(); }
603
  PerIsolateCompilerCache* compiler_cache() const { return compiler_cache_; }
604

605
  enum BrokerMode { kDisabled, kSerializing, kSerialized, kRetired };
606
  BrokerMode mode() const { return mode_; }
607 608 609
  void StartSerializing();
  void StopSerializing();
  void Retire();
610
  bool SerializingAllowed() const;
611 612 613 614 615

  // Returns nullptr iff handle unknown.
  ObjectData* GetData(Handle<Object>) const;
  // Never returns nullptr.
  ObjectData* GetOrCreateData(Handle<Object>);
616 617
  // Like the previous but wraps argument in handle first (for convenience).
  ObjectData* GetOrCreateData(Object*);
618

619 620 621 622
  // Check if {object} is any native context's %ArrayPrototype% or
  // %ObjectPrototype%.
  bool IsArrayOrObjectPrototype(const JSObjectRef& object) const;

623
  void Trace(const char* format, ...) const;
624 625
  void IncrementTracingIndentation();
  void DecrementTracingIndentation();
626

627 628
 private:
  friend class HeapObjectRef;
629
  friend class ObjectRef;
630
  friend class ObjectData;
631

632
  void SerializeShareableObjects();
633
  void CollectArrayAndObjectPrototypes();
634

635
  Isolate* const isolate_;
636 637
  Zone* const broker_zone_;
  Zone* current_zone_;
638
  base::Optional<NativeContextRef> native_context_;
639
  RefsMap* refs_;
640 641 642
  ZoneUnorderedSet<Handle<JSObject>, Handle<JSObject>::hash,
                   Handle<JSObject>::equal_to>
      array_and_object_prototypes_;
643 644

  BrokerMode mode_ = kDisabled;
645
  unsigned tracing_indentation_ = 0;
646
  PerIsolateCompilerCache* compiler_cache_;
647

648 649
  static const size_t kMinimalRefsBucketCount = 8;     // must be power of 2
  static const size_t kInitialRefsBucketCount = 1024;  // must be power of 2
650 651
};

652 653 654 655 656
#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__); \
657 658 659 660 661 662
  something_var = *optionally_something_;

class Reduction;
Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
                                       const char* function, int line);

663 664 665 666 667
}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_JS_HEAP_BROKER_H_