1 // Copyright 2016 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 #ifndef V8_IC_ACCESSOR_ASSEMBLER_H_ 6 #define V8_IC_ACCESSOR_ASSEMBLER_H_ 7 8 #include "src/base/optional.h" 9 #include "src/codegen/code-stub-assembler.h" 10 #include "src/compiler/code-assembler.h" 11 12 namespace v8 { 13 namespace internal { 14 15 namespace compiler { 16 class CodeAssemblerState; 17 } // namespace compiler 18 19 class ExitPoint; 20 21 class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { 22 public: AccessorAssembler(compiler::CodeAssemblerState * state)23 explicit AccessorAssembler(compiler::CodeAssemblerState* state) 24 : CodeStubAssembler(state) {} 25 26 void GenerateLoadIC(); 27 void GenerateLoadIC_Megamorphic(); 28 void GenerateLoadIC_Noninlined(); 29 void GenerateLoadIC_NoFeedback(); 30 void GenerateLoadGlobalIC_NoFeedback(); 31 void GenerateLoadICTrampoline(); 32 void GenerateLoadICBaseline(); 33 void GenerateLoadICTrampoline_Megamorphic(); 34 void GenerateLoadSuperIC(); 35 void GenerateLoadSuperICBaseline(); 36 void GenerateKeyedLoadIC(); 37 void GenerateKeyedLoadIC_Megamorphic(); 38 void GenerateKeyedLoadIC_PolymorphicName(); 39 void GenerateKeyedLoadICTrampoline(); 40 void GenerateKeyedLoadICBaseline(); 41 void GenerateKeyedLoadICTrampoline_Megamorphic(); 42 void GenerateStoreIC(); 43 void GenerateStoreICTrampoline(); 44 void GenerateStoreICBaseline(); 45 void GenerateDefineNamedOwnIC(); 46 void GenerateDefineNamedOwnICTrampoline(); 47 void GenerateDefineNamedOwnICBaseline(); 48 void GenerateStoreGlobalIC(); 49 void GenerateStoreGlobalICTrampoline(); 50 void GenerateStoreGlobalICBaseline(); 51 void GenerateCloneObjectIC(); 52 void GenerateCloneObjectICBaseline(); 53 void GenerateCloneObjectIC_Slow(); 54 void GenerateKeyedHasIC(); 55 void GenerateKeyedHasICBaseline(); 56 void GenerateKeyedHasIC_Megamorphic(); 57 void GenerateKeyedHasIC_PolymorphicName(); 58 59 void GenerateLoadGlobalIC(TypeofMode typeof_mode); 60 void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode); 61 void GenerateLoadGlobalICBaseline(TypeofMode typeof_mode); 62 void GenerateLookupGlobalICBaseline(TypeofMode typeof_mode); 63 void GenerateLookupContextBaseline(TypeofMode typeof_mode); 64 65 void GenerateKeyedStoreIC(); 66 void GenerateKeyedStoreICTrampoline(); 67 void GenerateKeyedStoreICBaseline(); 68 69 void GenerateDefineKeyedOwnIC(); 70 void GenerateDefineKeyedOwnICTrampoline(); 71 void GenerateDefineKeyedOwnICBaseline(); 72 73 void GenerateStoreInArrayLiteralIC(); 74 void GenerateStoreInArrayLiteralICBaseline(); 75 76 void TryProbeStubCache(StubCache* stub_cache, 77 TNode<Object> lookup_start_object, TNode<Name> name, 78 Label* if_handler, TVariable<MaybeObject>* var_handler, 79 Label* if_miss); 80 StubCachePrimaryOffsetForTesting(TNode<Name> name,TNode<Map> map)81 TNode<IntPtrT> StubCachePrimaryOffsetForTesting(TNode<Name> name, 82 TNode<Map> map) { 83 return StubCachePrimaryOffset(name, map); 84 } StubCacheSecondaryOffsetForTesting(TNode<Name> name,TNode<Map> map)85 TNode<IntPtrT> StubCacheSecondaryOffsetForTesting(TNode<Name> name, 86 TNode<Map> map) { 87 return StubCacheSecondaryOffset(name, map); 88 } 89 90 struct LoadICParameters { 91 LoadICParameters( 92 TNode<Context> context, TNode<Object> receiver, TNode<Object> name, 93 TNode<TaggedIndex> slot, TNode<HeapObject> vector, 94 base::Optional<TNode<Object>> lookup_start_object = base::nullopt) context_LoadICParameters95 : context_(context), 96 receiver_(receiver), 97 name_(name), 98 slot_(slot), 99 vector_(vector), 100 lookup_start_object_(lookup_start_object ? lookup_start_object.value() 101 : receiver) {} 102 LoadICParametersLoadICParameters103 LoadICParameters(const LoadICParameters* p, TNode<Object> unique_name) 104 : context_(p->context_), 105 receiver_(p->receiver_), 106 name_(unique_name), 107 slot_(p->slot_), 108 vector_(p->vector_), 109 lookup_start_object_(p->lookup_start_object_) {} 110 contextLoadICParameters111 TNode<Context> context() const { return context_; } receiverLoadICParameters112 TNode<Object> receiver() const { return receiver_; } nameLoadICParameters113 TNode<Object> name() const { return name_; } slotLoadICParameters114 TNode<TaggedIndex> slot() const { return slot_; } vectorLoadICParameters115 TNode<HeapObject> vector() const { return vector_; } lookup_start_objectLoadICParameters116 TNode<Object> lookup_start_object() const { 117 return lookup_start_object_.value(); 118 } 119 120 // Usable in cases where the receiver and the lookup start object are 121 // expected to be the same, i.e., when "receiver != lookup_start_object" 122 // case is not supported or not expected by the surrounding code. receiver_and_lookup_start_objectLoadICParameters123 TNode<Object> receiver_and_lookup_start_object() const { 124 DCHECK_EQ(receiver_, lookup_start_object_); 125 return receiver_; 126 } 127 128 private: 129 TNode<Context> context_; 130 TNode<Object> receiver_; 131 TNode<Object> name_; 132 TNode<TaggedIndex> slot_; 133 TNode<HeapObject> vector_; 134 base::Optional<TNode<Object>> lookup_start_object_; 135 }; 136 137 struct LazyLoadICParameters { 138 LazyLoadICParameters( 139 LazyNode<Context> context, TNode<Object> receiver, 140 LazyNode<Object> name, LazyNode<TaggedIndex> slot, 141 TNode<HeapObject> vector, 142 base::Optional<TNode<Object>> lookup_start_object = base::nullopt) context_LazyLoadICParameters143 : context_(context), 144 receiver_(receiver), 145 name_(name), 146 slot_(slot), 147 vector_(vector), 148 lookup_start_object_(lookup_start_object ? lookup_start_object.value() 149 : receiver) {} 150 LazyLoadICParametersLazyLoadICParameters151 explicit LazyLoadICParameters(const LoadICParameters* p) 152 : receiver_(p->receiver()), 153 vector_(p->vector()), 154 lookup_start_object_(p->lookup_start_object()) { 155 slot_ = [=] { return p->slot(); }; 156 context_ = [=] { return p->context(); }; 157 name_ = [=] { return p->name(); }; 158 } 159 contextLazyLoadICParameters160 TNode<Context> context() const { return context_(); } receiverLazyLoadICParameters161 TNode<Object> receiver() const { return receiver_; } nameLazyLoadICParameters162 TNode<Object> name() const { return name_(); } slotLazyLoadICParameters163 TNode<TaggedIndex> slot() const { return slot_(); } vectorLazyLoadICParameters164 TNode<HeapObject> vector() const { return vector_; } lookup_start_objectLazyLoadICParameters165 TNode<Object> lookup_start_object() const { return lookup_start_object_; } 166 167 // Usable in cases where the receiver and the lookup start object are 168 // expected to be the same, i.e., when "receiver != lookup_start_object" 169 // case is not supported or not expected by the surrounding code. receiver_and_lookup_start_objectLazyLoadICParameters170 TNode<Object> receiver_and_lookup_start_object() const { 171 DCHECK_EQ(receiver_, lookup_start_object_); 172 return receiver_; 173 } 174 175 private: 176 LazyNode<Context> context_; 177 TNode<Object> receiver_; 178 LazyNode<Object> name_; 179 LazyNode<TaggedIndex> slot_; 180 TNode<HeapObject> vector_; 181 TNode<Object> lookup_start_object_; 182 }; 183 184 void LoadGlobalIC(TNode<HeapObject> maybe_feedback_vector, 185 const LazyNode<TaggedIndex>& lazy_slot, 186 const LazyNode<Context>& lazy_context, 187 const LazyNode<Name>& lazy_name, TypeofMode typeof_mode, 188 ExitPoint* exit_point); 189 190 // Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame 191 // construction on common paths. 192 void LoadIC_BytecodeHandler(const LazyLoadICParameters* p, 193 ExitPoint* exit_point); 194 195 // Loads dataX field from the DataHandler object. 196 TNode<MaybeObject> LoadHandlerDataField(TNode<DataHandler> handler, 197 int data_index); 198 199 protected: 200 enum class StoreICMode { 201 // TODO(v8:12548): rename to kDefineKeyedOwnInLiteral 202 kDefault, 203 kDefineNamedOwn, 204 kDefineKeyedOwn, 205 }; 206 struct StoreICParameters { StoreICParametersStoreICParameters207 StoreICParameters(TNode<Context> context, 208 base::Optional<TNode<Object>> receiver, 209 TNode<Object> name, TNode<Object> value, 210 TNode<TaggedIndex> slot, TNode<HeapObject> vector, 211 StoreICMode mode) 212 : context_(context), 213 receiver_(receiver), 214 name_(name), 215 value_(value), 216 slot_(slot), 217 vector_(vector), 218 mode_(mode) {} 219 contextStoreICParameters220 TNode<Context> context() const { return context_; } receiverStoreICParameters221 TNode<Object> receiver() const { return receiver_.value(); } nameStoreICParameters222 TNode<Object> name() const { return name_; } valueStoreICParameters223 TNode<Object> value() const { return value_; } slotStoreICParameters224 TNode<TaggedIndex> slot() const { return slot_; } vectorStoreICParameters225 TNode<HeapObject> vector() const { return vector_; } 226 lookup_start_objectStoreICParameters227 TNode<Object> lookup_start_object() const { return receiver(); } 228 receiver_is_nullStoreICParameters229 bool receiver_is_null() const { return !receiver_.has_value(); } 230 IsDefineNamedOwnStoreICParameters231 bool IsDefineNamedOwn() const { 232 return mode_ == StoreICMode::kDefineNamedOwn; 233 } IsDefineKeyedOwnStoreICParameters234 bool IsDefineKeyedOwn() const { 235 return mode_ == StoreICMode::kDefineKeyedOwn; 236 } IsAnyDefineOwnStoreICParameters237 bool IsAnyDefineOwn() const { 238 return IsDefineNamedOwn() || IsDefineKeyedOwn(); 239 } 240 241 private: 242 TNode<Context> context_; 243 base::Optional<TNode<Object>> receiver_; 244 TNode<Object> name_; 245 TNode<Object> value_; 246 TNode<TaggedIndex> slot_; 247 TNode<HeapObject> vector_; 248 StoreICMode mode_; 249 }; 250 251 enum class LoadAccessMode { kLoad, kHas }; 252 enum class ICMode { kNonGlobalIC, kGlobalIC }; 253 enum ElementSupport { kOnlyProperties, kSupportElements }; 254 void HandleStoreICHandlerCase( 255 const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss, 256 ICMode ic_mode, ElementSupport support_elements = kOnlyProperties); 257 enum StoreTransitionMapFlags { 258 kDontCheckPrototypeValidity = 0, 259 kCheckPrototypeValidity = 1 << 0, 260 kValidateTransitionHandler = 1 << 1, 261 kStoreTransitionMapFlagsMask = 262 kCheckPrototypeValidity | kValidateTransitionHandler, 263 }; 264 void HandleStoreICTransitionMapHandlerCase(const StoreICParameters* p, 265 TNode<Map> transition_map, 266 Label* miss, 267 StoreTransitionMapFlags flags); 268 269 void JumpIfDataProperty(TNode<Uint32T> details, Label* writable, 270 Label* readonly); 271 272 void InvalidateValidityCellIfPrototype( 273 TNode<Map> map, base::Optional<TNode<Uint32T>> bitfield3 = base::nullopt); 274 275 void OverwriteExistingFastDataProperty(TNode<HeapObject> object, 276 TNode<Map> object_map, 277 TNode<DescriptorArray> descriptors, 278 TNode<IntPtrT> descriptor_name_index, 279 TNode<Uint32T> details, 280 TNode<Object> value, Label* slow, 281 bool do_transitioning_store); 282 283 void StoreJSSharedStructField(TNode<Context> context, 284 TNode<HeapObject> shared_struct, 285 TNode<Map> shared_struct_map, 286 TNode<DescriptorArray> descriptors, 287 TNode<IntPtrT> descriptor_name_index, 288 TNode<Uint32T> details, TNode<Object> value); 289 290 TNode<BoolT> IsPropertyDetailsConst(TNode<Uint32T> details); 291 292 void CheckFieldType(TNode<DescriptorArray> descriptors, 293 TNode<IntPtrT> name_index, TNode<Word32T> representation, 294 TNode<Object> value, Label* bailout); 295 296 private: 297 // Stub generation entry points. 298 299 // LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains 300 // logic not inlined into Ignition bytecode handlers. 301 void LoadIC(const LoadICParameters* p); 302 303 // Can be used in the receiver != lookup_start_object case. 304 void LoadIC_Noninlined(const LoadICParameters* p, 305 TNode<Map> lookup_start_object_map, 306 TNode<HeapObject> feedback, 307 TVariable<MaybeObject>* var_handler, Label* if_handler, 308 Label* miss, ExitPoint* exit_point); 309 310 void LoadSuperIC(const LoadICParameters* p); 311 312 TNode<Object> LoadDescriptorValue(TNode<Map> map, 313 TNode<IntPtrT> descriptor_entry); 314 TNode<MaybeObject> LoadDescriptorValueOrFieldType( 315 TNode<Map> map, TNode<IntPtrT> descriptor_entry); 316 317 void LoadIC_NoFeedback(const LoadICParameters* p, TNode<Smi> smi_typeof_mode); 318 void LoadSuperIC_NoFeedback(const LoadICParameters* p); 319 void LoadGlobalIC_NoFeedback(TNode<Context> context, TNode<Object> name, 320 TNode<Smi> smi_typeof_mode); 321 322 void KeyedLoadIC(const LoadICParameters* p, LoadAccessMode access_mode); 323 void KeyedLoadICGeneric(const LoadICParameters* p); 324 void KeyedLoadICPolymorphicName(const LoadICParameters* p, 325 LoadAccessMode access_mode); 326 327 void StoreIC(const StoreICParameters* p); 328 void StoreGlobalIC(const StoreICParameters* p); 329 void StoreGlobalIC_PropertyCellCase(TNode<PropertyCell> property_cell, 330 TNode<Object> value, 331 ExitPoint* exit_point, Label* miss); 332 void KeyedStoreIC(const StoreICParameters* p); 333 void DefineKeyedOwnIC(const StoreICParameters* p); 334 void StoreInArrayLiteralIC(const StoreICParameters* p); 335 336 // IC dispatcher behavior. 337 338 // Checks monomorphic case. Returns {feedback} entry of the vector. 339 TNode<MaybeObject> TryMonomorphicCase(TNode<TaggedIndex> slot, 340 TNode<FeedbackVector> vector, 341 TNode<Map> lookup_start_object_map, 342 Label* if_handler, 343 TVariable<MaybeObject>* var_handler, 344 Label* if_miss); 345 void HandlePolymorphicCase(TNode<Map> lookup_start_object_map, 346 TNode<WeakFixedArray> feedback, Label* if_handler, 347 TVariable<MaybeObject>* var_handler, 348 Label* if_miss); 349 350 void TryMegaDOMCase(TNode<Object> lookup_start_object, 351 TNode<Map> lookup_start_object_map, 352 TVariable<MaybeObject>* var_handler, TNode<Object> vector, 353 TNode<TaggedIndex> slot, Label* miss, 354 ExitPoint* exit_point); 355 356 // LoadIC implementation. 357 void HandleLoadICHandlerCase( 358 const LazyLoadICParameters* p, TNode<Object> handler, Label* miss, 359 ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC, 360 OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined, 361 ElementSupport support_elements = kOnlyProperties, 362 LoadAccessMode access_mode = LoadAccessMode::kLoad); 363 364 void HandleLoadICSmiHandlerCase(const LazyLoadICParameters* p, 365 TNode<Object> holder, TNode<Smi> smi_handler, 366 TNode<Object> handler, Label* miss, 367 ExitPoint* exit_point, ICMode ic_mode, 368 OnNonExistent on_nonexistent, 369 ElementSupport support_elements, 370 LoadAccessMode access_mode); 371 372 void HandleLoadICProtoHandler(const LazyLoadICParameters* p, 373 TNode<DataHandler> handler, 374 TVariable<Object>* var_holder, 375 TVariable<Object>* var_smi_handler, 376 Label* if_smi_handler, Label* miss, 377 ExitPoint* exit_point, ICMode ic_mode, 378 LoadAccessMode access_mode); 379 380 void HandleLoadCallbackProperty(const LazyLoadICParameters* p, 381 TNode<JSObject> holder, 382 TNode<WordT> handler_word, 383 ExitPoint* exit_point); 384 385 void HandleLoadAccessor(const LazyLoadICParameters* p, 386 TNode<CallHandlerInfo> call_handler_info, 387 TNode<WordT> handler_word, TNode<DataHandler> handler, 388 TNode<IntPtrT> handler_kind, ExitPoint* exit_point); 389 390 void HandleLoadField(TNode<JSObject> holder, TNode<WordT> handler_word, 391 TVariable<Float64T>* var_double_value, 392 Label* rebox_double, Label* miss, ExitPoint* exit_point); 393 394 #if V8_ENABLE_WEBASSEMBLY 395 void HandleLoadWasmField(TNode<WasmObject> holder, 396 TNode<Int32T> wasm_value_type, 397 TNode<IntPtrT> field_offset, 398 TVariable<Float64T>* var_double_value, 399 Label* rebox_double, ExitPoint* exit_point); 400 401 void HandleLoadWasmField(TNode<WasmObject> holder, TNode<WordT> handler_word, 402 TVariable<Float64T>* var_double_value, 403 Label* rebox_double, ExitPoint* exit_point); 404 #endif // V8_ENABLE_WEBASSEMBLY 405 406 void EmitAccessCheck(TNode<Context> expected_native_context, 407 TNode<Context> context, TNode<Object> receiver, 408 Label* can_access, Label* miss); 409 410 void HandleLoadICSmiHandlerLoadNamedCase( 411 const LazyLoadICParameters* p, TNode<Object> holder, 412 TNode<IntPtrT> handler_kind, TNode<WordT> handler_word, 413 Label* rebox_double, TVariable<Float64T>* var_double_value, 414 TNode<Object> handler, Label* miss, ExitPoint* exit_point, ICMode ic_mode, 415 OnNonExistent on_nonexistent, ElementSupport support_elements); 416 417 void HandleLoadICSmiHandlerHasNamedCase(const LazyLoadICParameters* p, 418 TNode<Object> holder, 419 TNode<IntPtrT> handler_kind, 420 Label* miss, ExitPoint* exit_point, 421 ICMode ic_mode); 422 423 // LoadGlobalIC implementation. 424 425 void LoadGlobalIC_TryPropertyCellCase(TNode<FeedbackVector> vector, 426 TNode<TaggedIndex> slot, 427 const LazyNode<Context>& lazy_context, 428 ExitPoint* exit_point, 429 Label* try_handler, Label* miss); 430 431 void LoadGlobalIC_TryHandlerCase(TNode<FeedbackVector> vector, 432 TNode<TaggedIndex> slot, 433 const LazyNode<Context>& lazy_context, 434 const LazyNode<Name>& lazy_name, 435 TypeofMode typeof_mode, 436 ExitPoint* exit_point, Label* miss); 437 438 // This is a copy of ScriptContextTable::Lookup. They should be kept in sync. 439 void ScriptContextTableLookup(TNode<Name> name, 440 TNode<NativeContext> native_context, 441 Label* found_hole, Label* not_found); 442 443 // StoreIC implementation. 444 445 void HandleStoreICProtoHandler(const StoreICParameters* p, 446 TNode<StoreHandler> handler, Label* miss, 447 ICMode ic_mode, 448 ElementSupport support_elements); 449 void HandleStoreICSmiHandlerCase(TNode<Word32T> handler_word, 450 TNode<JSObject> holder, TNode<Object> value, 451 Label* miss); 452 void HandleStoreICSmiHandlerJSSharedStructFieldCase( 453 TNode<Context> context, TNode<Word32T> handler_word, 454 TNode<JSObject> holder, TNode<Object> value); 455 void HandleStoreFieldAndReturn(TNode<Word32T> handler_word, 456 TNode<JSObject> holder, TNode<Object> value, 457 base::Optional<TNode<Float64T>> double_value, 458 Representation representation, Label* miss); 459 460 void CheckPrototypeValidityCell(TNode<Object> maybe_validity_cell, 461 Label* miss); 462 void HandleStoreICNativeDataProperty(const StoreICParameters* p, 463 TNode<HeapObject> holder, 464 TNode<Word32T> handler_word); 465 466 void HandleStoreToProxy(const StoreICParameters* p, TNode<JSProxy> proxy, 467 Label* miss, ElementSupport support_elements); 468 469 void HandleStoreAccessor(const StoreICParameters* p, TNode<HeapObject> holder, 470 TNode<Word32T> handler_word); 471 472 // KeyedLoadIC_Generic implementation. 473 474 void GenericElementLoad(TNode<HeapObject> lookup_start_object, 475 TNode<Map> lookup_start_object_map, 476 TNode<Int32T> lookup_start_object_instance_type, 477 TNode<IntPtrT> index, Label* slow); 478 479 enum UseStubCache { kUseStubCache, kDontUseStubCache }; 480 void GenericPropertyLoad(TNode<HeapObject> lookup_start_object, 481 TNode<Map> lookup_start_object_map, 482 TNode<Int32T> lookup_start_object_instance_type, 483 const LoadICParameters* p, Label* slow, 484 UseStubCache use_stub_cache = kUseStubCache); 485 486 // Low-level helpers. 487 488 using OnCodeHandler = std::function<void(TNode<CodeT> code_handler)>; 489 using OnFoundOnLookupStartObject = std::function<void( 490 TNode<PropertyDictionary> properties, TNode<IntPtrT> name_index)>; 491 492 template <typename ICHandler, typename ICParameters> 493 TNode<Object> HandleProtoHandler( 494 const ICParameters* p, TNode<DataHandler> handler, 495 const OnCodeHandler& on_code_handler, 496 const OnFoundOnLookupStartObject& on_found_on_lookup_start_object, 497 Label* miss, ICMode ic_mode); 498 499 void CheckHeapObjectTypeMatchesDescriptor(TNode<Word32T> handler_word, 500 TNode<JSObject> holder, 501 TNode<Object> value, 502 Label* bailout); 503 // Double fields store double values in a mutable box, where stores are 504 // writes into this box rather than HeapNumber assignment. 505 void CheckDescriptorConsidersNumbersMutable(TNode<Word32T> handler_word, 506 TNode<JSObject> holder, 507 Label* bailout); 508 509 // Extends properties backing store by JSObject::kFieldsAdded elements, 510 // returns updated properties backing store. 511 TNode<PropertyArray> ExtendPropertiesBackingStore(TNode<HeapObject> object, 512 TNode<IntPtrT> index); 513 514 void EmitFastElementsBoundsCheck(TNode<JSObject> object, 515 TNode<FixedArrayBase> elements, 516 TNode<IntPtrT> intptr_index, 517 TNode<BoolT> is_jsarray_condition, 518 Label* miss); 519 void EmitElementLoad(TNode<HeapObject> object, TNode<Word32T> elements_kind, 520 TNode<IntPtrT> key, TNode<BoolT> is_jsarray_condition, 521 Label* if_hole, Label* rebox_double, 522 TVariable<Float64T>* var_double_value, 523 Label* unimplemented_elements_kind, Label* out_of_bounds, 524 Label* miss, ExitPoint* exit_point, 525 LoadAccessMode access_mode = LoadAccessMode::kLoad); 526 527 // Stub cache access helpers. 528 529 // This enum is used here as a replacement for StubCache::Table to avoid 530 // including stub cache header. 531 enum StubCacheTable : int; 532 533 TNode<IntPtrT> StubCachePrimaryOffset(TNode<Name> name, TNode<Map> map); 534 TNode<IntPtrT> StubCacheSecondaryOffset(TNode<Name> name, TNode<Map> map); 535 536 void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id, 537 TNode<IntPtrT> entry_offset, TNode<Object> name, 538 TNode<Map> map, Label* if_handler, 539 TVariable<MaybeObject>* var_handler, 540 Label* if_miss); 541 542 void BranchIfPrototypesHaveNoElements(TNode<Map> receiver_map, 543 Label* definitely_no_elements, 544 Label* possibly_elements); 545 }; 546 547 // Abstraction over direct and indirect exit points. Direct exits correspond to 548 // tailcalls and Return, while indirect exits store the result in a variable 549 // and then jump to an exit label. 550 class ExitPoint { 551 private: 552 using CodeAssemblerLabel = compiler::CodeAssemblerLabel; 553 554 public: 555 using IndirectReturnHandler = std::function<void(TNode<Object> result)>; 556 ExitPoint(CodeStubAssembler * assembler)557 explicit ExitPoint(CodeStubAssembler* assembler) 558 : ExitPoint(assembler, nullptr) {} 559 ExitPoint(CodeStubAssembler * assembler,const IndirectReturnHandler & indirect_return_handler)560 ExitPoint(CodeStubAssembler* assembler, 561 const IndirectReturnHandler& indirect_return_handler) 562 : asm_(assembler), indirect_return_handler_(indirect_return_handler) {} 563 ExitPoint(CodeStubAssembler * assembler,CodeAssemblerLabel * out,compiler::CodeAssembler::TVariable<Object> * var_result)564 ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out, 565 compiler::CodeAssembler::TVariable<Object>* var_result) 566 : ExitPoint(assembler, [=](TNode<Object> result) { 567 *var_result = result; 568 assembler->Goto(out); 569 }) { 570 DCHECK_EQ(out != nullptr, var_result != nullptr); 571 } 572 573 template <class... TArgs> ReturnCallRuntime(Runtime::FunctionId function,TNode<Context> context,TArgs...args)574 void ReturnCallRuntime(Runtime::FunctionId function, TNode<Context> context, 575 TArgs... args) { 576 if (IsDirect()) { 577 asm_->TailCallRuntime(function, context, args...); 578 } else { 579 indirect_return_handler_(asm_->CallRuntime(function, context, args...)); 580 } 581 } 582 583 template <class... TArgs> ReturnCallStub(Callable const & callable,TNode<Context> context,TArgs...args)584 void ReturnCallStub(Callable const& callable, TNode<Context> context, 585 TArgs... args) { 586 if (IsDirect()) { 587 asm_->TailCallStub(callable, context, args...); 588 } else { 589 indirect_return_handler_(asm_->CallStub(callable, context, args...)); 590 } 591 } 592 593 template <class... TArgs> ReturnCallStub(const CallInterfaceDescriptor & descriptor,TNode<CodeT> target,TNode<Context> context,TArgs...args)594 void ReturnCallStub(const CallInterfaceDescriptor& descriptor, 595 TNode<CodeT> target, TNode<Context> context, 596 TArgs... args) { 597 if (IsDirect()) { 598 asm_->TailCallStub(descriptor, target, context, args...); 599 } else { 600 indirect_return_handler_( 601 asm_->CallStub(descriptor, target, context, args...)); 602 } 603 } 604 Return(const TNode<Object> result)605 void Return(const TNode<Object> result) { 606 if (IsDirect()) { 607 asm_->Return(result); 608 } else { 609 indirect_return_handler_(result); 610 } 611 } 612 IsDirect()613 bool IsDirect() const { return !indirect_return_handler_; } 614 615 private: 616 CodeStubAssembler* const asm_; 617 IndirectReturnHandler indirect_return_handler_; 618 }; 619 620 } // namespace internal 621 } // namespace v8 622 623 #endif // V8_IC_ACCESSOR_ASSEMBLER_H_ 624