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/turbo-assembler.h" 6 7 #include "src/builtins/builtins.h" 8 #include "src/builtins/constants-table-builder.h" 9 #include "src/heap/heap-inl.h" 10 #include "src/lsan.h" 11 #include "src/snapshot/serializer-common.h" 12 13 namespace v8 { 14 namespace internal { 15 16 TurboAssemblerBase::TurboAssemblerBase(Isolate* isolate, 17 const AssemblerOptions& options, 18 void* buffer, int buffer_size, 19 CodeObjectRequired create_code_object) 20 : Assembler(options, buffer, buffer_size), isolate_(isolate) { 21 if (create_code_object == CodeObjectRequired::kYes) { 22 code_object_ = Handle<HeapObject>::New( 23 ReadOnlyRoots(isolate).self_reference_marker(), isolate); 24 } 25 } 26 27 void TurboAssemblerBase::IndirectLoadConstant(Register destination, 28 Handle<HeapObject> object) { 29 CHECK(root_array_available_); 30 31 // Before falling back to the (fairly slow) lookup from the constants table, 32 // check if any of the fast paths can be applied. 33 34 int builtin_index; 35 Heap::RootListIndex root_index; 36 if (isolate()->heap()->IsRootHandle(object, &root_index)) { 37 // Roots are loaded relative to the root register. 38 LoadRoot(destination, root_index); 39 } else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin_index)) { 40 // Similar to roots, builtins may be loaded from the builtins table. 41 LoadRootRelative(destination, 42 RootRegisterOffsetForBuiltinIndex(builtin_index)); 43 } else if (object.is_identical_to(code_object_) && 44 Builtins::IsBuiltinId(maybe_builtin_index_)) { 45 // The self-reference loaded through Codevalue() may also be a builtin 46 // and thus viable for a fast load. 47 LoadRootRelative(destination, 48 RootRegisterOffsetForBuiltinIndex(maybe_builtin_index_)); 49 } else { 50 CHECK(isolate()->ShouldLoadConstantsFromRootList()); 51 // Ensure the given object is in the builtins constants table and fetch its 52 // index. 53 BuiltinsConstantsTableBuilder* builder = 54 isolate()->builtins_constants_table_builder(); 55 uint32_t index = builder->AddObject(object); 56 57 // Slow load from the constants table. 58 LoadFromConstantsTable(destination, index); 59 } 60 } 61 62 void TurboAssemblerBase::IndirectLoadExternalReference( 63 Register destination, ExternalReference reference) { 64 CHECK(root_array_available_); 65 66 if (IsAddressableThroughRootRegister(isolate(), reference)) { 67 // Some external references can be efficiently loaded as an offset from 68 // kRootRegister. 69 intptr_t offset = 70 RootRegisterOffsetForExternalReference(isolate(), reference); 71 LoadRootRegisterOffset(destination, offset); 72 } else { 73 // Otherwise, do a memory load from the external reference table. 74 75 // Encode as an index into the external reference table stored on the 76 // isolate. 77 ExternalReferenceEncoder encoder(isolate()); 78 ExternalReferenceEncoder::Value v = encoder.Encode(reference.address()); 79 CHECK(!v.is_from_api()); 80 81 LoadRootRelative(destination, 82 RootRegisterOffsetForExternalReferenceIndex(v.index())); 83 } 84 } 85 86 // static 87 int32_t TurboAssemblerBase::RootRegisterOffset(Heap::RootListIndex root_index) { 88 return (root_index << kPointerSizeLog2) - kRootRegisterBias; 89 } 90 91 // static 92 int32_t TurboAssemblerBase::RootRegisterOffsetForExternalReferenceIndex( 93 int reference_index) { 94 return Heap::roots_to_external_reference_table_offset() - kRootRegisterBias + 95 ExternalReferenceTable::OffsetOfEntry(reference_index); 96 } 97 98 // static 99 intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference( 100 Isolate* isolate, const ExternalReference& reference) { 101 return static_cast<intptr_t>(reference.address()) - kRootRegisterBias - 102 reinterpret_cast<intptr_t>(isolate->heap()->roots_array_start()); 103 } 104 105 // static 106 bool TurboAssemblerBase::IsAddressableThroughRootRegister( 107 Isolate* isolate, const ExternalReference& reference) { 108 Address start = reinterpret_cast<Address>(isolate); 109 Address end = isolate->heap()->root_register_addressable_end(); 110 Address address = reference.address(); 111 return start <= address && address < end; 112 } 113 114 // static 115 int32_t TurboAssemblerBase::RootRegisterOffsetForBuiltinIndex( 116 int builtin_index) { 117 return Heap::roots_to_builtins_offset() - kRootRegisterBias + 118 builtin_index * kPointerSize; 119 } 120 121 void TurboAssemblerBase::RecordCommentForOffHeapTrampoline(int builtin_index) { 122 if (!FLAG_code_comments) return; 123 size_t len = strlen("-- Inlined Trampoline to --") + 124 strlen(Builtins::name(builtin_index)) + 1; 125 Vector<char> buffer = Vector<char>::New(static_cast<int>(len)); 126 char* buffer_start = buffer.start(); 127 LSAN_IGNORE_OBJECT(buffer_start); 128 SNPrintF(buffer, "-- Inlined Trampoline to %s --", 129 Builtins::name(builtin_index)); 130 RecordComment(buffer_start); 131 } 132 133 } // namespace internal 134 } // namespace v8 135