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/codegen/turbo-assembler.h" 6 7#include "src/builtins/builtins.h" 8#include "src/builtins/constants-table-builder.h" 9#include "src/codegen/external-reference-encoder.h" 10#include "src/common/globals.h" 11#include "src/execution/isolate-data.h" 12#include "src/execution/isolate-inl.h" 13#include "src/snapshot/embedded/embedded-data-inl.h" 14 15namespace v8 { 16namespace internal { 17 18TurboAssemblerBase::TurboAssemblerBase(Isolate* isolate, 19 const AssemblerOptions& options, 20 CodeObjectRequired create_code_object, 21 std::unique_ptr<AssemblerBuffer> buffer) 22 : Assembler(options, std::move(buffer)), isolate_(isolate) { 23 if (create_code_object == CodeObjectRequired::kYes) { 24 code_object_ = Handle<HeapObject>::New( 25 ReadOnlyRoots(isolate).self_reference_marker(), isolate); 26 } 27} 28 29Address TurboAssemblerBase::BuiltinEntry(Builtin builtin) { 30 DCHECK(Builtins::IsBuiltinId(builtin)); 31 if (isolate_ != nullptr) { 32 Address entry = 33 isolate_->builtin_entry_table()[static_cast<int32_t>(builtin)]; 34 DCHECK_EQ(entry, EmbeddedData::FromBlob(isolate_).InstructionStartOfBuiltin( 35 builtin)); 36 return entry; 37 } 38 EmbeddedData d = EmbeddedData::FromBlob(); 39 return d.InstructionStartOfBuiltin(builtin); 40} 41 42void TurboAssemblerBase::IndirectLoadConstant(Register destination, 43 Handle<HeapObject> object) { 44 CHECK(root_array_available_); 45 46 // Before falling back to the (fairly slow) lookup from the constants table, 47 // check if any of the fast paths can be applied. 48 49 Builtin builtin; 50 RootIndex root_index; 51 if (isolate()->roots_table().IsRootHandle(object, &root_index)) { 52 // Roots are loaded relative to the root register. 53 LoadRoot(destination, root_index); 54 } else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin)) { 55 // Similar to roots, builtins may be loaded from the builtins table. 56 LoadRootRelative(destination, RootRegisterOffsetForBuiltin(builtin)); 57 } else if (object.is_identical_to(code_object_) && 58 Builtins::IsBuiltinId(maybe_builtin_)) { 59 // The self-reference loaded through Codevalue() may also be a builtin 60 // and thus viable for a fast load. 61 LoadRootRelative(destination, RootRegisterOffsetForBuiltin(maybe_builtin_)); 62 } else { 63 CHECK(isolate()->IsGeneratingEmbeddedBuiltins()); 64 // Ensure the given object is in the builtins constants table and fetch its 65 // index. 66 BuiltinsConstantsTableBuilder* builder = 67 isolate()->builtins_constants_table_builder(); 68 uint32_t index = builder->AddObject(object); 69 70 // Slow load from the constants table. 71 LoadFromConstantsTable(destination, index); 72 } 73} 74 75void TurboAssemblerBase::IndirectLoadExternalReference( 76 Register destination, ExternalReference reference) { 77 CHECK(root_array_available_); 78 79 if (IsAddressableThroughRootRegister(isolate(), reference)) { 80 // Some external references can be efficiently loaded as an offset from 81 // kRootRegister. 82 intptr_t offset = 83 RootRegisterOffsetForExternalReference(isolate(), reference); 84 LoadRootRegisterOffset(destination, offset); 85 } else { 86 // Otherwise, do a memory load from the external reference table. 87 LoadRootRelative( 88 destination, 89 RootRegisterOffsetForExternalReferenceTableEntry(isolate(), reference)); 90 } 91} 92 93// static 94int32_t TurboAssemblerBase::RootRegisterOffsetForRootIndex( 95 RootIndex root_index) { 96 return IsolateData::root_slot_offset(root_index); 97} 98 99// static 100int32_t TurboAssemblerBase::RootRegisterOffsetForBuiltin(Builtin builtin) { 101 return IsolateData::BuiltinSlotOffset(builtin); 102} 103 104// static 105intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference( 106 Isolate* isolate, const ExternalReference& reference) { 107 return static_cast<intptr_t>(reference.address() - isolate->isolate_root()); 108} 109 110// static 111int32_t TurboAssemblerBase::RootRegisterOffsetForExternalReferenceTableEntry( 112 Isolate* isolate, const ExternalReference& reference) { 113 // Encode as an index into the external reference table stored on the 114 // isolate. 115 ExternalReferenceEncoder encoder(isolate); 116 ExternalReferenceEncoder::Value v = encoder.Encode(reference.address()); 117 CHECK(!v.is_from_api()); 118 119 return IsolateData::external_reference_table_offset() + 120 ExternalReferenceTable::OffsetOfEntry(v.index()); 121} 122 123// static 124bool TurboAssemblerBase::IsAddressableThroughRootRegister( 125 Isolate* isolate, const ExternalReference& reference) { 126 Address address = reference.address(); 127 return isolate->root_register_addressable_region().contains(address); 128} 129 130} // namespace internal 131} // namespace v8 132