1 // Copyright 2018 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/compiler/js-heap-broker.h" 6 7 #include "src/compiler/graph-reducer.h" 8 #include "src/objects-inl.h" 9 #include "src/objects/js-array-inl.h" 10 #include "src/objects/js-regexp-inl.h" 11 #include "src/objects/module-inl.h" 12 #include "src/utils.h" 13 14 namespace v8 { 15 namespace internal { 16 namespace compiler { 17 18 #define FORWARD_DECL(Name) class Name##Data; 19 HEAP_BROKER_OBJECT_LIST(FORWARD_DECL) 20 #undef FORWARD_DECL 21 22 // TODO(neis): It would be nice to share the serialized data for read-only 23 // objects. 24 25 class ObjectData : public ZoneObject { 26 public: 27 static ObjectData* Serialize(JSHeapBroker* broker, Handle<Object> object); 28 29 ObjectData(JSHeapBroker* broker_, Handle<Object> object_, bool is_smi_) 30 : broker(broker_), object(object_), is_smi(is_smi_) { 31 broker->AddData(object, this); 32 } 33 34 #define DECLARE_IS_AND_AS(Name) \ 35 bool Is##Name() const; \ 36 Name##Data* As##Name(); 37 HEAP_BROKER_OBJECT_LIST(DECLARE_IS_AND_AS) 38 #undef DECLARE_IS_AND_AS 39 40 JSHeapBroker* const broker; 41 Handle<Object> const object; 42 bool const is_smi; 43 }; 44 45 // TODO(neis): Perhaps add a boolean that indicates whether serialization of an 46 // object has completed. That could be used to add safety checks. 47 48 #define GET_OR_CREATE(name) \ 49 broker->GetOrCreateData(handle(object_->name(), broker->isolate())) 50 51 class HeapObjectData : public ObjectData { 52 public: 53 static HeapObjectData* Serialize(JSHeapBroker* broker, 54 Handle<HeapObject> object); 55 56 HeapObjectType const type; 57 MapData* const map; 58 59 HeapObjectData(JSHeapBroker* broker_, Handle<HeapObject> object_, 60 HeapObjectType type_) 61 : ObjectData(broker_, object_, false), 62 type(type_), 63 map(GET_OR_CREATE(map)->AsMap()) { 64 CHECK(broker_->SerializingAllowed()); 65 } 66 }; 67 68 class PropertyCellData : public HeapObjectData { 69 public: 70 PropertyCellData(JSHeapBroker* broker_, Handle<PropertyCell> object_, 71 HeapObjectType type_) 72 : HeapObjectData(broker_, object_, type_) {} 73 }; 74 75 class JSObjectData : public HeapObjectData { 76 public: 77 JSObjectData(JSHeapBroker* broker_, Handle<JSObject> object_, 78 HeapObjectType type_) 79 : HeapObjectData(broker_, object_, type_) {} 80 }; 81 82 class JSFunctionData : public JSObjectData { 83 public: 84 JSGlobalProxyData* const global_proxy; 85 MapData* const initial_map; // Can be nullptr. 86 bool const has_prototype; 87 ObjectData* const prototype; // Can be nullptr. 88 bool const PrototypeRequiresRuntimeLookup; 89 SharedFunctionInfoData* const shared; 90 91 JSFunctionData(JSHeapBroker* broker_, Handle<JSFunction> object_, 92 HeapObjectType type_); 93 }; 94 95 class JSRegExpData : public JSObjectData { 96 public: 97 JSRegExpData(JSHeapBroker* broker_, Handle<JSRegExp> object_, 98 HeapObjectType type_) 99 : JSObjectData(broker_, object_, type_) {} 100 }; 101 102 class HeapNumberData : public HeapObjectData { 103 public: 104 HeapNumberData(JSHeapBroker* broker_, Handle<HeapNumber> object_, 105 HeapObjectType type_) 106 : HeapObjectData(broker_, object_, type_) {} 107 }; 108 109 class MutableHeapNumberData : public HeapObjectData { 110 public: 111 MutableHeapNumberData(JSHeapBroker* broker_, 112 Handle<MutableHeapNumber> object_, HeapObjectType type_) 113 : HeapObjectData(broker_, object_, type_) {} 114 }; 115 116 class ContextData : public HeapObjectData { 117 public: 118 ContextData(JSHeapBroker* broker_, Handle<Context> object_, 119 HeapObjectType type_) 120 : HeapObjectData(broker_, object_, type_) {} 121 }; 122 123 class NativeContextData : public ContextData { 124 public: 125 #define DECL_MEMBER(type, name) type##Data* const name; 126 BROKER_NATIVE_CONTEXT_FIELDS(DECL_MEMBER) 127 #undef DECL_MEMBER 128 129 NativeContextData(JSHeapBroker* broker_, Handle<NativeContext> object_, 130 HeapObjectType type_) 131 : ContextData(broker_, object_, type_) 132 #define INIT_MEMBER(type, name) , name(GET_OR_CREATE(name)->As##type()) 133 BROKER_NATIVE_CONTEXT_FIELDS(INIT_MEMBER) 134 #undef INIT_MEMBER 135 { 136 } 137 }; 138 139 class NameData : public HeapObjectData { 140 public: 141 NameData(JSHeapBroker* broker, Handle<Name> object, HeapObjectType type) 142 : HeapObjectData(broker, object, type) {} 143 }; 144 145 class StringData : public NameData { 146 public: 147 StringData(JSHeapBroker* broker, Handle<String> object, HeapObjectType type) 148 : NameData(broker, object, type), 149 length(object->length()), 150 first_char(length > 0 ? object->Get(0) : 0) { 151 int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY; 152 if (length <= kMaxLengthForDoubleConversion) { 153 to_number = StringToDouble( 154 broker->isolate(), broker->isolate()->unicode_cache(), object, flags); 155 } 156 } 157 158 int const length; 159 uint16_t const first_char; 160 base::Optional<double> to_number; 161 162 private: 163 static constexpr int kMaxLengthForDoubleConversion = 23; 164 }; 165 166 class InternalizedStringData : public StringData { 167 public: 168 InternalizedStringData(JSHeapBroker* broker, 169 Handle<InternalizedString> object, HeapObjectType type) 170 : StringData(broker, object, type) {} 171 }; 172 173 namespace { 174 175 bool IsFastLiteralHelper(Handle<JSObject> boilerplate, int max_depth, 176 int* max_properties) { 177 DCHECK_GE(max_depth, 0); 178 DCHECK_GE(*max_properties, 0); 179 180 // Make sure the boilerplate map is not deprecated. 181 if (!JSObject::TryMigrateInstance(boilerplate)) return false; 182 183 // Check for too deep nesting. 184 if (max_depth == 0) return false; 185 186 // Check the elements. 187 Isolate* const isolate = boilerplate->GetIsolate(); 188 Handle<FixedArrayBase> elements(boilerplate->elements(), isolate); 189 if (elements->length() > 0 && 190 elements->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) { 191 if (boilerplate->HasSmiOrObjectElements()) { 192 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); 193 int length = elements->length(); 194 for (int i = 0; i < length; i++) { 195 if ((*max_properties)-- == 0) return false; 196 Handle<Object> value(fast_elements->get(i), isolate); 197 if (value->IsJSObject()) { 198 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 199 if (!IsFastLiteralHelper(value_object, max_depth - 1, 200 max_properties)) { 201 return false; 202 } 203 } 204 } 205 } else if (boilerplate->HasDoubleElements()) { 206 if (elements->Size() > kMaxRegularHeapObjectSize) return false; 207 } else { 208 return false; 209 } 210 } 211 212 // TODO(turbofan): Do we want to support out-of-object properties? 213 if (!(boilerplate->HasFastProperties() && 214 boilerplate->property_array()->length() == 0)) { 215 return false; 216 } 217 218 // Check the in-object properties. 219 Handle<DescriptorArray> descriptors( 220 boilerplate->map()->instance_descriptors(), isolate); 221 int limit = boilerplate->map()->NumberOfOwnDescriptors(); 222 for (int i = 0; i < limit; i++) { 223 PropertyDetails details = descriptors->GetDetails(i); 224 if (details.location() != kField) continue; 225 DCHECK_EQ(kData, details.kind()); 226 if ((*max_properties)-- == 0) return false; 227 FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i); 228 if (boilerplate->IsUnboxedDoubleField(field_index)) continue; 229 Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate); 230 if (value->IsJSObject()) { 231 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 232 if (!IsFastLiteralHelper(value_object, max_depth - 1, max_properties)) { 233 return false; 234 } 235 } 236 } 237 return true; 238 } 239 240 // Maximum depth and total number of elements and properties for literal 241 // graphs to be considered for fast deep-copying. The limit is chosen to 242 // match the maximum number of inobject properties, to ensure that the 243 // performance of using object literals is not worse than using constructor 244 // functions, see crbug.com/v8/6211 for details. 245 const int kMaxFastLiteralDepth = 3; 246 const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties; 247 248 // Determines whether the given array or object literal boilerplate satisfies 249 // all limits to be considered for fast deep-copying and computes the total 250 // size of all objects that are part of the graph. 251 bool IsInlinableFastLiteral(Handle<JSObject> boilerplate) { 252 int max_properties = kMaxFastLiteralProperties; 253 return IsFastLiteralHelper(boilerplate, kMaxFastLiteralDepth, 254 &max_properties); 255 } 256 257 } // namespace 258 259 class AllocationSiteData : public HeapObjectData { 260 public: 261 AllocationSiteData(JSHeapBroker* broker, Handle<AllocationSite> object_, 262 HeapObjectType type_) 263 : HeapObjectData(broker, object_, type_), 264 PointsToLiteral(object_->PointsToLiteral()), 265 GetPretenureMode(object_->GetPretenureMode()), 266 nested_site(GET_OR_CREATE(nested_site)) { 267 if (PointsToLiteral) { 268 if (IsInlinableFastLiteral( 269 handle(object_->boilerplate(), broker->isolate()))) { 270 boilerplate = GET_OR_CREATE(boilerplate)->AsJSObject(); 271 } 272 } else { 273 GetElementsKind = object_->GetElementsKind(); 274 CanInlineCall = object_->CanInlineCall(); 275 } 276 } 277 278 bool const PointsToLiteral; 279 PretenureFlag const GetPretenureMode; 280 ObjectData* const nested_site; 281 JSObjectData* boilerplate = nullptr; 282 283 // These are only valid if PointsToLiteral is false. 284 ElementsKind GetElementsKind = NO_ELEMENTS; 285 bool CanInlineCall = false; 286 }; 287 288 // Only used in JSNativeContextSpecialization. 289 class ScriptContextTableData : public HeapObjectData { 290 public: 291 ScriptContextTableData(JSHeapBroker* broker_, 292 Handle<ScriptContextTable> object_, 293 HeapObjectType type_) 294 : HeapObjectData(broker_, object_, type_) {} 295 }; 296 297 class MapData : public HeapObjectData { 298 public: 299 InstanceType const instance_type; 300 int const instance_size; 301 byte const bit_field; 302 byte const bit_field2; 303 uint32_t const bit_field3; 304 305 MapData(JSHeapBroker* broker_, Handle<Map> object_, HeapObjectType type_); 306 307 // Extra information. 308 void SerializeElementsKindGeneralizations(); 309 const ZoneVector<MapData*>& elements_kind_generalizations() { 310 return elements_kind_generalizations_; 311 } 312 313 private: 314 ZoneVector<MapData*> elements_kind_generalizations_; 315 }; 316 317 MapData::MapData(JSHeapBroker* broker_, Handle<Map> object_, 318 HeapObjectType type_) 319 : HeapObjectData(broker_, object_, type_), 320 instance_type(object_->instance_type()), 321 instance_size(object_->instance_size()), 322 bit_field(object_->bit_field()), 323 bit_field2(object_->bit_field2()), 324 bit_field3(object_->bit_field3()), 325 elements_kind_generalizations_(broker->zone()) {} 326 327 JSFunctionData::JSFunctionData(JSHeapBroker* broker_, 328 Handle<JSFunction> object_, HeapObjectType type_) 329 : JSObjectData(broker_, object_, type_), 330 global_proxy(GET_OR_CREATE(global_proxy)->AsJSGlobalProxy()), 331 initial_map(object_->has_prototype_slot() && object_->has_initial_map() 332 ? GET_OR_CREATE(initial_map)->AsMap() 333 : nullptr), 334 has_prototype(object_->has_prototype_slot() && object_->has_prototype()), 335 prototype(has_prototype ? GET_OR_CREATE(prototype) : nullptr), 336 PrototypeRequiresRuntimeLookup(object_->PrototypeRequiresRuntimeLookup()), 337 shared(GET_OR_CREATE(shared)->AsSharedFunctionInfo()) { 338 if (initial_map != nullptr && initial_map->instance_type == JS_ARRAY_TYPE) { 339 initial_map->SerializeElementsKindGeneralizations(); 340 } 341 } 342 343 void MapData::SerializeElementsKindGeneralizations() { 344 broker->Trace("Computing ElementsKind generalizations of %p.\n", *object); 345 DCHECK_EQ(instance_type, JS_ARRAY_TYPE); 346 MapRef self(this); 347 ElementsKind from_kind = self.elements_kind(); 348 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) { 349 ElementsKind to_kind = static_cast<ElementsKind>(i); 350 if (IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { 351 Handle<Map> target = 352 Map::AsElementsKind(broker->isolate(), self.object<Map>(), to_kind); 353 elements_kind_generalizations_.push_back( 354 broker->GetOrCreateData(target)->AsMap()); 355 } 356 } 357 } 358 359 class FeedbackVectorData : public HeapObjectData { 360 public: 361 const ZoneVector<ObjectData*>& feedback() { return feedback_; } 362 363 FeedbackVectorData(JSHeapBroker* broker_, Handle<FeedbackVector> object_, 364 HeapObjectType type_); 365 366 private: 367 ZoneVector<ObjectData*> feedback_; 368 }; 369 370 FeedbackVectorData::FeedbackVectorData(JSHeapBroker* broker_, 371 Handle<FeedbackVector> object_, 372 HeapObjectType type_) 373 : HeapObjectData(broker_, object_, type_), feedback_(broker_->zone()) { 374 feedback_.reserve(object_->length()); 375 for (int i = 0; i < object_->length(); ++i) { 376 MaybeObject* value = object_->get(i); 377 feedback_.push_back(value->IsObject() 378 ? broker->GetOrCreateData( 379 handle(value->ToObject(), broker->isolate())) 380 : nullptr); 381 } 382 DCHECK_EQ(object_->length(), feedback_.size()); 383 } 384 385 class FixedArrayBaseData : public HeapObjectData { 386 public: 387 int const length; 388 389 FixedArrayBaseData(JSHeapBroker* broker_, Handle<FixedArrayBase> object_, 390 HeapObjectType type_) 391 : HeapObjectData(broker_, object_, type_), length(object_->length()) {} 392 }; 393 394 class FixedArrayData : public FixedArrayBaseData { 395 public: 396 FixedArrayData(JSHeapBroker* broker_, Handle<FixedArray> object_, 397 HeapObjectType type_) 398 : FixedArrayBaseData(broker_, object_, type_) {} 399 }; 400 401 class FixedDoubleArrayData : public FixedArrayBaseData { 402 public: 403 FixedDoubleArrayData(JSHeapBroker* broker_, Handle<FixedDoubleArray> object_, 404 HeapObjectType type_) 405 : FixedArrayBaseData(broker_, object_, type_) {} 406 }; 407 408 class BytecodeArrayData : public FixedArrayBaseData { 409 public: 410 int const register_count; 411 412 BytecodeArrayData(JSHeapBroker* broker_, Handle<BytecodeArray> object_, 413 HeapObjectType type_) 414 : FixedArrayBaseData(broker_, object_, type_), 415 register_count(object_->register_count()) {} 416 }; 417 418 class JSArrayData : public JSObjectData { 419 public: 420 JSArrayData(JSHeapBroker* broker_, Handle<JSArray> object_, 421 HeapObjectType type_) 422 : JSObjectData(broker_, object_, type_) {} 423 }; 424 425 class ScopeInfoData : public HeapObjectData { 426 public: 427 ScopeInfoData(JSHeapBroker* broker_, Handle<ScopeInfo> object_, 428 HeapObjectType type_) 429 : HeapObjectData(broker_, object_, type_) {} 430 }; 431 432 class SharedFunctionInfoData : public HeapObjectData { 433 public: 434 int const builtin_id; 435 BytecodeArrayData* const GetBytecodeArray; // Can be nullptr. 436 #define DECL_MEMBER(type, name) type const name; 437 BROKER_SFI_FIELDS(DECL_MEMBER) 438 #undef DECL_MEMBER 439 440 SharedFunctionInfoData(JSHeapBroker* broker_, 441 Handle<SharedFunctionInfo> object_, 442 HeapObjectType type_) 443 : HeapObjectData(broker_, object_, type_), 444 builtin_id(object_->HasBuiltinId() ? object_->builtin_id() 445 : Builtins::kNoBuiltinId), 446 GetBytecodeArray( 447 object_->HasBytecodeArray() 448 ? GET_OR_CREATE(GetBytecodeArray)->AsBytecodeArray() 449 : nullptr) 450 #define INIT_MEMBER(type, name) , name(object_->name()) 451 BROKER_SFI_FIELDS(INIT_MEMBER) 452 #undef INIT_MEMBER 453 { 454 DCHECK_EQ(HasBuiltinId, builtin_id != Builtins::kNoBuiltinId); 455 DCHECK_EQ(HasBytecodeArray, GetBytecodeArray != nullptr); 456 } 457 }; 458 459 class ModuleData : public HeapObjectData { 460 public: 461 ModuleData(JSHeapBroker* broker_, Handle<Module> object_, 462 HeapObjectType type_) 463 : HeapObjectData(broker_, object_, type_) {} 464 }; 465 466 class CellData : public HeapObjectData { 467 public: 468 CellData(JSHeapBroker* broker_, Handle<Cell> object_, HeapObjectType type_) 469 : HeapObjectData(broker_, object_, type_) {} 470 }; 471 472 class JSGlobalProxyData : public JSObjectData { 473 public: 474 JSGlobalProxyData(JSHeapBroker* broker_, Handle<JSGlobalProxy> object_, 475 HeapObjectType type_) 476 : JSObjectData(broker_, object_, type_) {} 477 }; 478 479 class CodeData : public HeapObjectData { 480 public: 481 CodeData(JSHeapBroker* broker_, Handle<Code> object_, HeapObjectType type_) 482 : HeapObjectData(broker_, object_, type_) {} 483 }; 484 485 #define DEFINE_IS_AND_AS(Name) \ 486 bool ObjectData::Is##Name() const { \ 487 if (broker->mode() == JSHeapBroker::kDisabled) { \ 488 AllowHandleDereference allow_handle_dereference; \ 489 return object->Is##Name(); \ 490 } \ 491 if (is_smi) return false; \ 492 InstanceType instance_type = \ 493 static_cast<const HeapObjectData*>(this)->type.instance_type(); \ 494 return InstanceTypeChecker::Is##Name(instance_type); \ 495 } \ 496 Name##Data* ObjectData::As##Name() { \ 497 CHECK_NE(broker->mode(), JSHeapBroker::kDisabled); \ 498 CHECK(Is##Name()); \ 499 return static_cast<Name##Data*>(this); \ 500 } 501 HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS) 502 #undef DEFINE_IS_AND_AS 503 504 ObjectData* ObjectData::Serialize(JSHeapBroker* broker, Handle<Object> object) { 505 CHECK(broker->SerializingAllowed()); 506 return object->IsSmi() ? new (broker->zone()) ObjectData(broker, object, true) 507 : HeapObjectData::Serialize( 508 broker, Handle<HeapObject>::cast(object)); 509 } 510 511 HeapObjectData* HeapObjectData::Serialize(JSHeapBroker* broker, 512 Handle<HeapObject> object) { 513 CHECK(broker->SerializingAllowed()); 514 Handle<Map> map(object->map(), broker->isolate()); 515 HeapObjectType type = broker->HeapObjectTypeFromMap(map); 516 517 #define RETURN_CREATE_DATA_IF_MATCH(name) \ 518 if (object->Is##name()) { \ 519 return new (broker->zone()) \ 520 name##Data(broker, Handle<name>::cast(object), type); \ 521 } 522 HEAP_BROKER_OBJECT_LIST(RETURN_CREATE_DATA_IF_MATCH) 523 #undef RETURN_CREATE_DATA_IF_MATCH 524 UNREACHABLE(); 525 } 526 527 bool ObjectRef::equals(const ObjectRef& other) const { 528 return data_ == other.data_; 529 } 530 531 StringRef ObjectRef::TypeOf() const { 532 AllowHandleAllocation handle_allocation; 533 AllowHandleDereference handle_dereference; 534 return StringRef(broker(), 535 Object::TypeOf(broker()->isolate(), object<Object>())); 536 } 537 538 Isolate* ObjectRef::isolate() const { return broker()->isolate(); } 539 540 base::Optional<ContextRef> ContextRef::previous() const { 541 AllowHandleAllocation handle_allocation; 542 AllowHandleDereference handle_dereference; 543 Context* previous = object<Context>()->previous(); 544 if (previous == nullptr) return base::Optional<ContextRef>(); 545 return ContextRef(broker(), handle(previous, broker()->isolate())); 546 } 547 548 ObjectRef ContextRef::get(int index) const { 549 AllowHandleAllocation handle_allocation; 550 AllowHandleDereference handle_dereference; 551 Handle<Object> value(object<Context>()->get(index), broker()->isolate()); 552 return ObjectRef(broker(), value); 553 } 554 555 JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* zone) 556 : isolate_(isolate), 557 zone_(zone), 558 refs_(zone), 559 mode_(FLAG_concurrent_compiler_frontend ? kSerializing : kDisabled) { 560 Trace("%s", "Constructing heap broker.\n"); 561 } 562 563 void JSHeapBroker::Trace(const char* format, ...) const { 564 if (FLAG_trace_heap_broker) { 565 PrintF("[%p] ", this); 566 va_list arguments; 567 va_start(arguments, format); 568 base::OS::VPrint(format, arguments); 569 va_end(arguments); 570 } 571 } 572 573 bool JSHeapBroker::SerializingAllowed() const { 574 return mode() == kSerializing || 575 (!FLAG_strict_heap_broker && mode() == kSerialized); 576 } 577 578 void JSHeapBroker::SerializeStandardObjects() { 579 Trace("Serializing standard objects.\n"); 580 581 Builtins* const b = isolate()->builtins(); 582 Factory* const f = isolate()->factory(); 583 584 // Stuff used by JSGraph: 585 GetOrCreateData(f->empty_fixed_array()); 586 587 // Stuff used by JSCreateLowering: 588 GetOrCreateData(f->block_context_map()); 589 GetOrCreateData(f->catch_context_map()); 590 GetOrCreateData(f->eval_context_map()); 591 GetOrCreateData(f->fixed_array_map()); 592 GetOrCreateData(f->fixed_double_array_map()); 593 GetOrCreateData(f->function_context_map()); 594 GetOrCreateData(f->many_closures_cell_map()); 595 GetOrCreateData(f->mutable_heap_number_map()); 596 GetOrCreateData(f->name_dictionary_map()); 597 GetOrCreateData(f->one_pointer_filler_map()); 598 GetOrCreateData(f->sloppy_arguments_elements_map()); 599 GetOrCreateData(f->with_context_map()); 600 601 // Stuff used by TypedOptimization: 602 // Strings produced by typeof: 603 GetOrCreateData(f->boolean_string()); 604 GetOrCreateData(f->number_string()); 605 GetOrCreateData(f->string_string()); 606 GetOrCreateData(f->bigint_string()); 607 GetOrCreateData(f->symbol_string()); 608 GetOrCreateData(f->undefined_string()); 609 GetOrCreateData(f->object_string()); 610 GetOrCreateData(f->function_string()); 611 612 // Stuff used by JSTypedLowering: 613 GetOrCreateData(f->length_string()); 614 Builtins::Name builtins[] = { 615 Builtins::kArgumentsAdaptorTrampoline, 616 Builtins::kCallFunctionForwardVarargs, 617 Builtins::kStringAdd_CheckNone_NotTenured, 618 Builtins::kStringAdd_CheckNone_Tenured, 619 Builtins::kStringAdd_ConvertLeft_NotTenured, 620 Builtins::kStringAdd_ConvertRight_NotTenured, 621 }; 622 for (auto id : builtins) { 623 GetOrCreateData(b->builtin_handle(id)); 624 } 625 for (int32_t id = 0; id < Builtins::builtin_count; ++id) { 626 if (Builtins::KindOf(id) == Builtins::TFJ) { 627 GetOrCreateData(b->builtin_handle(id)); 628 } 629 } 630 631 Trace("Finished serializing standard objects.\n"); 632 } 633 634 HeapObjectType JSHeapBroker::HeapObjectTypeFromMap(Map* map) const { 635 AllowHandleDereference allow_handle_dereference; 636 OddballType oddball_type = OddballType::kNone; 637 if (map->instance_type() == ODDBALL_TYPE) { 638 ReadOnlyRoots roots(isolate_); 639 if (map == roots.undefined_map()) { 640 oddball_type = OddballType::kUndefined; 641 } else if (map == roots.null_map()) { 642 oddball_type = OddballType::kNull; 643 } else if (map == roots.boolean_map()) { 644 oddball_type = OddballType::kBoolean; 645 } else if (map == roots.the_hole_map()) { 646 oddball_type = OddballType::kHole; 647 } else if (map == roots.uninitialized_map()) { 648 oddball_type = OddballType::kUninitialized; 649 } else { 650 oddball_type = OddballType::kOther; 651 DCHECK(map == roots.termination_exception_map() || 652 map == roots.arguments_marker_map() || 653 map == roots.optimized_out_map() || 654 map == roots.stale_register_map()); 655 } 656 } 657 HeapObjectType::Flags flags(0); 658 if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable; 659 if (map->is_callable()) flags |= HeapObjectType::kCallable; 660 661 return HeapObjectType(map->instance_type(), flags, oddball_type); 662 } 663 664 ObjectData* JSHeapBroker::GetData(Handle<Object> object) const { 665 auto it = refs_.find(object.address()); 666 return it != refs_.end() ? it->second : nullptr; 667 } 668 669 ObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object) { 670 CHECK(SerializingAllowed()); 671 ObjectData* data = GetData(object); 672 if (data == nullptr) { 673 // TODO(neis): Remove these Allow* once we serialize everything upfront. 674 AllowHandleAllocation handle_allocation; 675 AllowHandleDereference handle_dereference; 676 data = ObjectData::Serialize(this, object); 677 } 678 CHECK_NOT_NULL(data); 679 return data; 680 } 681 682 void JSHeapBroker::AddData(Handle<Object> object, ObjectData* data) { 683 Trace("Creating data %p for handle %" V8PRIuPTR " (", data, object.address()); 684 if (FLAG_trace_heap_broker) { 685 object->ShortPrint(); 686 PrintF(")\n"); 687 } 688 CHECK_NOT_NULL(isolate()->handle_scope_data()->canonical_scope); 689 CHECK(refs_.insert({object.address(), data}).second); 690 } 691 692 #define DEFINE_IS_AND_AS(Name) \ 693 bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \ 694 Name##Ref ObjectRef::As##Name() const { \ 695 DCHECK(Is##Name()); \ 696 return Name##Ref(data()); \ 697 } 698 HEAP_BROKER_OBJECT_LIST(DEFINE_IS_AND_AS) 699 #undef DEFINE_IS_AND_AS 700 701 bool ObjectRef::IsSmi() const { return data()->is_smi; } 702 703 int ObjectRef::AsSmi() const { 704 DCHECK(IsSmi()); 705 // Handle-dereference is always allowed for Handle<Smi>. 706 return object<Smi>()->value(); 707 } 708 709 HeapObjectType HeapObjectRef::type() const { 710 if (broker()->mode() == JSHeapBroker::kDisabled) { 711 AllowHandleDereference allow_handle_dereference; 712 return broker()->HeapObjectTypeFromMap(object<HeapObject>()->map()); 713 } else { 714 return data()->AsHeapObject()->type; 715 } 716 } 717 718 base::Optional<MapRef> HeapObjectRef::TryGetObjectCreateMap() const { 719 AllowHandleAllocation handle_allocation; 720 AllowHandleDereference allow_handle_dereference; 721 Handle<Map> instance_map; 722 if (Map::TryGetObjectCreateMap(broker()->isolate(), object<HeapObject>()) 723 .ToHandle(&instance_map)) { 724 return MapRef(broker(), instance_map); 725 } else { 726 return base::Optional<MapRef>(); 727 } 728 } 729 730 base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const { 731 if (broker()->mode() == JSHeapBroker::kDisabled) { 732 AllowHandleAllocation handle_allocation; 733 AllowHeapAllocation heap_allocation; 734 AllowHandleDereference allow_handle_dereference; 735 return MapRef(broker(), Map::AsElementsKind(broker()->isolate(), 736 object<Map>(), kind)); 737 } else { 738 if (kind == elements_kind()) return *this; 739 const ZoneVector<MapData*>& elements_kind_generalizations = 740 data()->AsMap()->elements_kind_generalizations(); 741 for (auto data : elements_kind_generalizations) { 742 MapRef map(data); 743 if (map.elements_kind() == kind) return map; 744 } 745 return base::Optional<MapRef>(); 746 } 747 } 748 749 int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const { 750 AllowHandleDereference allow_handle_dereference; 751 AllowHandleAllocation handle_allocation; 752 753 return object<JSFunction>()->ComputeInstanceSizeWithMinSlack( 754 broker()->isolate()); 755 } 756 757 base::Optional<ScriptContextTableRef::LookupResult> 758 ScriptContextTableRef::lookup(const NameRef& name) const { 759 AllowHandleAllocation handle_allocation; 760 AllowHandleDereference handle_dereference; 761 if (!name.IsString()) return {}; 762 ScriptContextTable::LookupResult lookup_result; 763 auto table = object<ScriptContextTable>(); 764 if (!ScriptContextTable::Lookup(broker()->isolate(), table, 765 name.object<String>(), &lookup_result)) { 766 return {}; 767 } 768 Handle<Context> script_context = ScriptContextTable::GetContext( 769 broker()->isolate(), table, lookup_result.context_index); 770 LookupResult result{ContextRef(broker(), script_context), 771 lookup_result.mode == VariableMode::kConst, 772 lookup_result.slot_index}; 773 return result; 774 } 775 776 OddballType ObjectRef::oddball_type() const { 777 return IsSmi() ? OddballType::kNone : AsHeapObject().type().oddball_type(); 778 } 779 780 ObjectRef FeedbackVectorRef::get(FeedbackSlot slot) const { 781 if (broker()->mode() == JSHeapBroker::kDisabled) { 782 AllowHandleAllocation handle_allocation; 783 AllowHandleDereference handle_dereference; 784 Handle<Object> value(object<FeedbackVector>()->Get(slot)->ToObject(), 785 broker()->isolate()); 786 return ObjectRef(broker(), value); 787 } 788 int i = FeedbackVector::GetIndex(slot); 789 return ObjectRef(data()->AsFeedbackVector()->feedback().at(i)); 790 } 791 792 bool JSObjectRef::IsUnboxedDoubleField(FieldIndex index) const { 793 AllowHandleDereference handle_dereference; 794 return object<JSObject>()->IsUnboxedDoubleField(index); 795 } 796 797 double JSObjectRef::RawFastDoublePropertyAt(FieldIndex index) const { 798 AllowHandleDereference handle_dereference; 799 return object<JSObject>()->RawFastDoublePropertyAt(index); 800 } 801 802 ObjectRef JSObjectRef::RawFastPropertyAt(FieldIndex index) const { 803 AllowHandleAllocation handle_allocation; 804 AllowHandleDereference handle_dereference; 805 return ObjectRef(broker(), 806 handle(object<JSObject>()->RawFastPropertyAt(index), 807 broker()->isolate())); 808 } 809 810 811 bool AllocationSiteRef::IsFastLiteral() const { 812 if (broker()->mode() == JSHeapBroker::kDisabled) { 813 AllowHeapAllocation 814 allow_heap_allocation; // This is needed for TryMigrateInstance. 815 AllowHandleAllocation allow_handle_allocation; 816 AllowHandleDereference allow_handle_dereference; 817 return IsInlinableFastLiteral( 818 handle(object<AllocationSite>()->boilerplate(), broker()->isolate())); 819 } else { 820 return data()->AsAllocationSite()->boilerplate != nullptr; 821 } 822 } 823 824 void JSObjectRef::EnsureElementsTenured() { 825 // TODO(jarin) Eventually, we will pretenure the boilerplates before 826 // the compilation job starts. 827 AllowHandleAllocation allow_handle_allocation; 828 AllowHandleDereference allow_handle_dereference; 829 AllowHeapAllocation allow_heap_allocation; 830 831 Handle<FixedArrayBase> object_elements = elements().object<FixedArrayBase>(); 832 if (Heap::InNewSpace(*object_elements)) { 833 // If we would like to pretenure a fixed cow array, we must ensure that 834 // the array is already in old space, otherwise we'll create too many 835 // old-to-new-space pointers (overflowing the store buffer). 836 object_elements = 837 broker()->isolate()->factory()->CopyAndTenureFixedCOWArray( 838 Handle<FixedArray>::cast(object_elements)); 839 object<JSObject>()->set_elements(*object_elements); 840 } 841 } 842 843 FieldIndex MapRef::GetFieldIndexFor(int i) const { 844 AllowHandleDereference allow_handle_dereference; 845 return FieldIndex::ForDescriptor(*object<Map>(), i); 846 } 847 848 int MapRef::GetInObjectPropertyOffset(int i) const { 849 AllowHandleDereference allow_handle_dereference; 850 return object<Map>()->GetInObjectPropertyOffset(i); 851 } 852 853 PropertyDetails MapRef::GetPropertyDetails(int i) const { 854 AllowHandleDereference allow_handle_dereference; 855 return object<Map>()->instance_descriptors()->GetDetails(i); 856 } 857 858 NameRef MapRef::GetPropertyKey(int i) const { 859 AllowHandleAllocation handle_allocation; 860 AllowHandleDereference allow_handle_dereference; 861 return NameRef(broker(), 862 handle(object<Map>()->instance_descriptors()->GetKey(i), 863 broker()->isolate())); 864 } 865 866 bool MapRef::IsFixedCowArrayMap() const { 867 AllowHandleDereference allow_handle_dereference; 868 return *object<Map>() == 869 ReadOnlyRoots(broker()->isolate()).fixed_cow_array_map(); 870 } 871 872 MapRef MapRef::FindFieldOwner(int descriptor) const { 873 AllowHandleAllocation handle_allocation; 874 AllowHandleDereference allow_handle_dereference; 875 Handle<Map> owner( 876 object<Map>()->FindFieldOwner(broker()->isolate(), descriptor), 877 broker()->isolate()); 878 return MapRef(broker(), owner); 879 } 880 881 ObjectRef MapRef::GetFieldType(int descriptor) const { 882 AllowHandleAllocation handle_allocation; 883 AllowHandleDereference allow_handle_dereference; 884 Handle<FieldType> field_type( 885 object<Map>()->instance_descriptors()->GetFieldType(descriptor), 886 broker()->isolate()); 887 return ObjectRef(broker(), field_type); 888 } 889 890 uint16_t StringRef::GetFirstChar() { 891 if (broker()->mode() == JSHeapBroker::kDisabled) { 892 AllowHandleDereference allow_handle_dereference; 893 return object<String>()->Get(0); 894 } else { 895 return data()->AsString()->first_char; 896 } 897 } 898 899 base::Optional<double> StringRef::ToNumber() { 900 if (broker()->mode() == JSHeapBroker::kDisabled) { 901 AllowHandleDereference allow_handle_dereference; 902 AllowHandleAllocation allow_handle_allocation; 903 AllowHeapAllocation allow_heap_allocation; 904 int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY; 905 return StringToDouble(broker()->isolate(), 906 broker()->isolate()->unicode_cache(), 907 object<String>(), flags); 908 } else { 909 return data()->AsString()->to_number; 910 } 911 } 912 913 bool FixedArrayRef::is_the_hole(int i) const { 914 AllowHandleDereference allow_handle_dereference; 915 return object<FixedArray>()->is_the_hole(broker()->isolate(), i); 916 } 917 918 ObjectRef FixedArrayRef::get(int i) const { 919 AllowHandleAllocation handle_allocation; 920 AllowHandleDereference allow_handle_dereference; 921 return ObjectRef(broker(), 922 handle(object<FixedArray>()->get(i), broker()->isolate())); 923 } 924 925 bool FixedDoubleArrayRef::is_the_hole(int i) const { 926 AllowHandleDereference allow_handle_dereference; 927 return object<FixedDoubleArray>()->is_the_hole(i); 928 } 929 930 double FixedDoubleArrayRef::get_scalar(int i) const { 931 AllowHandleDereference allow_handle_dereference; 932 return object<FixedDoubleArray>()->get_scalar(i); 933 } 934 935 #define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \ 936 if (broker()->mode() == JSHeapBroker::kDisabled) { \ 937 AllowHandleAllocation handle_allocation; \ 938 AllowHandleDereference allow_handle_dereference; \ 939 return object<holder>()->name(); \ 940 } 941 942 // Macros for definining a const getter that, depending on the broker mode, 943 // either looks into the handle or into the serialized data. The first one is 944 // used for the rare case of a XYZRef class that does not have a corresponding 945 // XYZ class in objects.h. The second one is used otherwise. 946 #define BIMODAL_ACCESSOR(holder, result, name) \ 947 result##Ref holder##Ref::name() const { \ 948 if (broker()->mode() == JSHeapBroker::kDisabled) { \ 949 AllowHandleAllocation handle_allocation; \ 950 AllowHandleDereference allow_handle_dereference; \ 951 return result##Ref( \ 952 broker(), handle(object<holder>()->name(), broker()->isolate())); \ 953 } else { \ 954 return result##Ref(data()->As##holder()->name); \ 955 } \ 956 } 957 958 // Like HANDLE_ACCESSOR except that the result type is not an XYZRef. 959 #define BIMODAL_ACCESSOR_C(holder, result, name) \ 960 result holder##Ref::name() const { \ 961 IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \ 962 return data()->As##holder()->name; \ 963 } 964 965 // Like HANDLE_ACCESSOR_C but for BitFields. 966 #define BIMODAL_ACCESSOR_B(holder, field, name, BitField) \ 967 typename BitField::FieldType holder##Ref::name() const { \ 968 IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name); \ 969 return BitField::decode(data()->As##holder()->field); \ 970 } 971 972 // Macros for definining a const getter that always looks into the handle. 973 // (These will go away once we serialize everything.) The first one is used for 974 // the rare case of a XYZRef class that does not have a corresponding XYZ class 975 // in objects.h. The second one is used otherwise. 976 #define HANDLE_ACCESSOR(holder, result, name) \ 977 result##Ref holder##Ref::name() const { \ 978 AllowHandleAllocation handle_allocation; \ 979 AllowHandleDereference allow_handle_dereference; \ 980 return result##Ref(broker(), \ 981 handle(object<holder>()->name(), broker()->isolate())); \ 982 } 983 984 // Like HANDLE_ACCESSOR except that the result type is not an XYZRef. 985 #define HANDLE_ACCESSOR_C(holder, result, name) \ 986 result holder##Ref::name() const { \ 987 AllowHandleAllocation handle_allocation; \ 988 AllowHandleDereference allow_handle_dereference; \ 989 return object<holder>()->name(); \ 990 } 991 992 BIMODAL_ACCESSOR(AllocationSite, Object, nested_site) 993 BIMODAL_ACCESSOR_C(AllocationSite, bool, CanInlineCall) 994 BIMODAL_ACCESSOR_C(AllocationSite, bool, PointsToLiteral) 995 BIMODAL_ACCESSOR_C(AllocationSite, ElementsKind, GetElementsKind) 996 BIMODAL_ACCESSOR_C(AllocationSite, PretenureFlag, GetPretenureMode) 997 998 BIMODAL_ACCESSOR_C(BytecodeArray, int, register_count) 999 1000 BIMODAL_ACCESSOR_C(FixedArrayBase, int, length) 1001 1002 BIMODAL_ACCESSOR(HeapObject, Map, map) 1003 HANDLE_ACCESSOR_C(HeapObject, bool, IsExternalString) 1004 HANDLE_ACCESSOR_C(HeapObject, bool, IsSeqString) 1005 1006 HANDLE_ACCESSOR_C(HeapNumber, double, value) 1007 1008 HANDLE_ACCESSOR(JSArray, Object, length) 1009 1010 BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype) 1011 BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup) 1012 BIMODAL_ACCESSOR(JSFunction, Map, initial_map) 1013 BIMODAL_ACCESSOR(JSFunction, Object, prototype) 1014 HANDLE_ACCESSOR_C(JSFunction, bool, IsConstructor) 1015 HANDLE_ACCESSOR(JSFunction, JSGlobalProxy, global_proxy) 1016 HANDLE_ACCESSOR(JSFunction, SharedFunctionInfo, shared) 1017 1018 HANDLE_ACCESSOR(JSObject, FixedArrayBase, elements) 1019 1020 HANDLE_ACCESSOR(JSRegExp, Object, data) 1021 HANDLE_ACCESSOR(JSRegExp, Object, flags) 1022 HANDLE_ACCESSOR(JSRegExp, Object, last_index) 1023 HANDLE_ACCESSOR(JSRegExp, Object, raw_properties_or_hash) 1024 HANDLE_ACCESSOR(JSRegExp, Object, source) 1025 1026 BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits) 1027 BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit) 1028 BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit) 1029 BIMODAL_ACCESSOR_B(Map, bit_field, has_prototype_slot, Map::HasPrototypeSlotBit) 1030 BIMODAL_ACCESSOR_C(Map, int, instance_size) 1031 HANDLE_ACCESSOR_C(Map, bool, CanBeDeprecated) 1032 HANDLE_ACCESSOR_C(Map, bool, CanTransition) 1033 HANDLE_ACCESSOR_C(Map, bool, IsInobjectSlackTrackingInProgress) 1034 HANDLE_ACCESSOR_C(Map, bool, IsJSArrayMap) 1035 HANDLE_ACCESSOR_C(Map, bool, is_stable) 1036 HANDLE_ACCESSOR_C(Map, InstanceType, instance_type) 1037 HANDLE_ACCESSOR_C(Map, int, GetInObjectProperties) 1038 HANDLE_ACCESSOR_C(Map, int, GetInObjectPropertiesStartInWords) 1039 HANDLE_ACCESSOR_C(Map, int, NumberOfOwnDescriptors) 1040 HANDLE_ACCESSOR(Map, Object, constructor_or_backpointer) 1041 1042 HANDLE_ACCESSOR_C(MutableHeapNumber, double, value) 1043 1044 #define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \ 1045 BIMODAL_ACCESSOR(NativeContext, type, name) 1046 BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR) 1047 #undef DEF_NATIVE_CONTEXT_ACCESSOR 1048 1049 HANDLE_ACCESSOR(PropertyCell, Object, value) 1050 HANDLE_ACCESSOR_C(PropertyCell, PropertyDetails, property_details) 1051 1052 HANDLE_ACCESSOR_C(ScopeInfo, int, ContextLength) 1053 1054 BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id) 1055 BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray) 1056 #define DEF_SFI_ACCESSOR(type, name) \ 1057 BIMODAL_ACCESSOR_C(SharedFunctionInfo, type, name) 1058 BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR) 1059 #undef DEF_SFI_ACCESSOR 1060 1061 BIMODAL_ACCESSOR_C(String, int, length) 1062 1063 // TODO(neis): Provide StringShape() on StringRef. 1064 1065 bool JSFunctionRef::has_initial_map() const { 1066 IF_BROKER_DISABLED_ACCESS_HANDLE_C(JSFunction, has_initial_map); 1067 return data()->AsJSFunction()->initial_map != nullptr; 1068 } 1069 1070 MapRef NativeContextRef::GetFunctionMapFromIndex(int index) const { 1071 DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX); 1072 DCHECK_GE(index, Context::FIRST_FUNCTION_MAP_INDEX); 1073 return get(index).AsMap(); 1074 } 1075 1076 MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const { 1077 switch (kind) { 1078 case PACKED_SMI_ELEMENTS: 1079 return js_array_packed_smi_elements_map(); 1080 case HOLEY_SMI_ELEMENTS: 1081 return js_array_holey_smi_elements_map(); 1082 case PACKED_DOUBLE_ELEMENTS: 1083 return js_array_packed_double_elements_map(); 1084 case HOLEY_DOUBLE_ELEMENTS: 1085 return js_array_holey_double_elements_map(); 1086 case PACKED_ELEMENTS: 1087 return js_array_packed_elements_map(); 1088 case HOLEY_ELEMENTS: 1089 return js_array_holey_elements_map(); 1090 default: 1091 UNREACHABLE(); 1092 } 1093 } 1094 1095 bool ObjectRef::BooleanValue() { 1096 AllowHandleDereference allow_handle_dereference; 1097 return object<Object>()->BooleanValue(broker()->isolate()); 1098 } 1099 1100 double ObjectRef::OddballToNumber() const { 1101 OddballType type = oddball_type(); 1102 1103 switch (type) { 1104 case OddballType::kBoolean: { 1105 ObjectRef true_ref(broker(), 1106 broker()->isolate()->factory()->true_value()); 1107 return this->equals(true_ref) ? 1 : 0; 1108 break; 1109 } 1110 case OddballType::kUndefined: { 1111 return std::numeric_limits<double>::quiet_NaN(); 1112 break; 1113 } 1114 case OddballType::kNull: { 1115 return 0; 1116 break; 1117 } 1118 default: { 1119 UNREACHABLE(); 1120 break; 1121 } 1122 } 1123 } 1124 1125 CellRef ModuleRef::GetCell(int cell_index) { 1126 AllowHandleAllocation handle_allocation; 1127 AllowHandleDereference allow_handle_dereference; 1128 return CellRef(broker(), handle(object<Module>()->GetCell(cell_index), 1129 broker()->isolate())); 1130 } 1131 1132 ObjectRef::ObjectRef(JSHeapBroker* broker, Handle<Object> object) { 1133 switch (broker->mode()) { 1134 case JSHeapBroker::kSerialized: 1135 data_ = FLAG_strict_heap_broker ? broker->GetData(object) 1136 : broker->GetOrCreateData(object); 1137 break; 1138 case JSHeapBroker::kSerializing: 1139 data_ = broker->GetOrCreateData(object); 1140 break; 1141 case JSHeapBroker::kDisabled: 1142 data_ = broker->GetData(object); 1143 if (data_ == nullptr) { 1144 AllowHandleDereference handle_dereference; 1145 data_ = 1146 new (broker->zone()) ObjectData(broker, object, object->IsSmi()); 1147 } 1148 break; 1149 } 1150 CHECK_NOT_NULL(data_); 1151 } 1152 1153 base::Optional<JSObjectRef> AllocationSiteRef::boilerplate() const { 1154 if (broker()->mode() == JSHeapBroker::kDisabled) { 1155 AllowHandleAllocation handle_allocation; 1156 AllowHandleDereference allow_handle_dereference; 1157 return JSObjectRef(broker(), handle(object<AllocationSite>()->boilerplate(), 1158 broker()->isolate())); 1159 } else { 1160 JSObjectData* boilerplate = data()->AsAllocationSite()->boilerplate; 1161 if (boilerplate) { 1162 return JSObjectRef(boilerplate); 1163 } else { 1164 return base::nullopt; 1165 } 1166 } 1167 } 1168 1169 ElementsKind JSObjectRef::GetElementsKind() const { 1170 return map().elements_kind(); 1171 } 1172 1173 Handle<Object> ObjectRef::object() const { return data_->object; } 1174 1175 JSHeapBroker* ObjectRef::broker() const { return data_->broker; } 1176 1177 ObjectData* ObjectRef::data() const { return data_; } 1178 1179 Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker, 1180 const char* function, int line) { 1181 if (FLAG_trace_heap_broker) { 1182 PrintF("[%p] Skipping optimization in %s at line %d due to missing data\n", 1183 broker, function, line); 1184 } 1185 return AdvancedReducer::NoChange(); 1186 } 1187 1188 #undef BIMODAL_ACCESSOR 1189 #undef BIMODAL_ACCESSOR_B 1190 #undef BIMODAL_ACCESSOR_C 1191 #undef GET_OR_CREATE 1192 #undef HANDLE_ACCESSOR 1193 #undef HANDLE_ACCESSOR_C 1194 #undef IF_BROKER_DISABLED_ACCESS_HANDLE_C 1195 1196 } // namespace compiler 1197 } // namespace internal 1198 } // namespace v8 1199