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
13 namespace v8 {
14 namespace internal {
15
TurboAssemblerBase(Isolate * isolate,const AssemblerOptions & options,CodeObjectRequired create_code_object,std::unique_ptr<AssemblerBuffer> buffer)16 TurboAssemblerBase::TurboAssemblerBase(Isolate* isolate,
17 const AssemblerOptions& options,
18 CodeObjectRequired create_code_object,
19 std::unique_ptr<AssemblerBuffer> buffer)
20 : Assembler(options, std::move(buffer)), 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
IndirectLoadConstant(Register destination,Handle<HeapObject> object)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 RootIndex root_index;
36 if (isolate()->roots_table().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()->IsGeneratingEmbeddedBuiltins());
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
IndirectLoadExternalReference(Register destination,ExternalReference reference)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 LoadRootRelative(
75 destination,
76 RootRegisterOffsetForExternalReferenceTableEntry(isolate(), reference));
77 }
78 }
79
80 // static
RootRegisterOffsetForRootIndex(RootIndex root_index)81 int32_t TurboAssemblerBase::RootRegisterOffsetForRootIndex(
82 RootIndex root_index) {
83 return IsolateData::root_slot_offset(root_index);
84 }
85
86 // static
RootRegisterOffsetForBuiltinIndex(int builtin_index)87 int32_t TurboAssemblerBase::RootRegisterOffsetForBuiltinIndex(
88 int builtin_index) {
89 return IsolateData::builtin_slot_offset(builtin_index);
90 }
91
92 // static
RootRegisterOffsetForExternalReference(Isolate * isolate,const ExternalReference & reference)93 intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference(
94 Isolate* isolate, const ExternalReference& reference) {
95 return static_cast<intptr_t>(reference.address() - isolate->isolate_root());
96 }
97
98 // static
RootRegisterOffsetForExternalReferenceTableEntry(Isolate * isolate,const ExternalReference & reference)99 int32_t TurboAssemblerBase::RootRegisterOffsetForExternalReferenceTableEntry(
100 Isolate* isolate, const ExternalReference& reference) {
101 // Encode as an index into the external reference table stored on the
102 // isolate.
103 ExternalReferenceEncoder encoder(isolate);
104 ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
105 CHECK(!v.is_from_api());
106
107 return IsolateData::external_reference_table_offset() +
108 ExternalReferenceTable::OffsetOfEntry(v.index());
109 }
110
111 // static
IsAddressableThroughRootRegister(Isolate * isolate,const ExternalReference & reference)112 bool TurboAssemblerBase::IsAddressableThroughRootRegister(
113 Isolate* isolate, const ExternalReference& reference) {
114 Address address = reference.address();
115 return isolate->root_register_addressable_region().contains(address);
116 }
117
RecordCommentForOffHeapTrampoline(int builtin_index)118 void TurboAssemblerBase::RecordCommentForOffHeapTrampoline(int builtin_index) {
119 if (!FLAG_code_comments) return;
120 std::ostringstream str;
121 str << "-- Inlined Trampoline to " << Builtins::name(builtin_index) << " --";
122 RecordComment(str.str().c_str());
123 }
124
125 } // namespace internal
126 } // namespace v8
127