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
15 namespace v8 {
16 namespace internal {
17
TurboAssemblerBase(Isolate * isolate,const AssemblerOptions & options,CodeObjectRequired create_code_object,std::unique_ptr<AssemblerBuffer> buffer)18 TurboAssemblerBase::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
BuiltinEntry(Builtin builtin)29 Address 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
IndirectLoadConstant(Register destination,Handle<HeapObject> object)42 void 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
IndirectLoadExternalReference(Register destination,ExternalReference reference)75 void 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
RootRegisterOffsetForRootIndex(RootIndex root_index)94 int32_t TurboAssemblerBase::RootRegisterOffsetForRootIndex(
95 RootIndex root_index) {
96 return IsolateData::root_slot_offset(root_index);
97 }
98
99 // static
RootRegisterOffsetForBuiltin(Builtin builtin)100 int32_t TurboAssemblerBase::RootRegisterOffsetForBuiltin(Builtin builtin) {
101 return IsolateData::BuiltinSlotOffset(builtin);
102 }
103
104 // static
RootRegisterOffsetForExternalReference(Isolate * isolate,const ExternalReference & reference)105 intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference(
106 Isolate* isolate, const ExternalReference& reference) {
107 return static_cast<intptr_t>(reference.address() - isolate->isolate_root());
108 }
109
110 // static
RootRegisterOffsetForExternalReferenceTableEntry(Isolate * isolate,const ExternalReference & reference)111 int32_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
IsAddressableThroughRootRegister(Isolate * isolate,const ExternalReference & reference)124 bool 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