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
TurboAssemblerBase(Isolate * isolate,const AssemblerOptions & options,void * buffer,int buffer_size,CodeObjectRequired create_code_object)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
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 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
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
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
RootRegisterOffset(Heap::RootListIndex root_index)87 int32_t TurboAssemblerBase::RootRegisterOffset(Heap::RootListIndex root_index) {
88 return (root_index << kPointerSizeLog2) - kRootRegisterBias;
89 }
90
91 // static
RootRegisterOffsetForExternalReferenceIndex(int reference_index)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
RootRegisterOffsetForExternalReference(Isolate * isolate,const ExternalReference & reference)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
IsAddressableThroughRootRegister(Isolate * isolate,const ExternalReference & reference)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
RootRegisterOffsetForBuiltinIndex(int builtin_index)115 int32_t TurboAssemblerBase::RootRegisterOffsetForBuiltinIndex(
116 int builtin_index) {
117 return Heap::roots_to_builtins_offset() - kRootRegisterBias +
118 builtin_index * kPointerSize;
119 }
120
RecordCommentForOffHeapTrampoline(int builtin_index)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