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