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/isolate-data.h"
10#include "src/isolate-inl.h"
11#include "src/snapshot/serializer-common.h"
12
13namespace v8 {
14namespace internal {
15
16TurboAssemblerBase::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
27void 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
62void 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
81int32_t TurboAssemblerBase::RootRegisterOffsetForRootIndex(
82 RootIndex root_index) {
83 return IsolateData::root_slot_offset(root_index);
84}
85
86// static
87int32_t TurboAssemblerBase::RootRegisterOffsetForBuiltinIndex(
88 int builtin_index) {
89 return IsolateData::builtin_slot_offset(builtin_index);
90}
91
92// static
93intptr_t TurboAssemblerBase::RootRegisterOffsetForExternalReference(
94 Isolate* isolate, const ExternalReference& reference) {
95 return static_cast<intptr_t>(reference.address() - isolate->isolate_root());
96}
97
98// static
99int32_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
112bool TurboAssemblerBase::IsAddressableThroughRootRegister(
113 Isolate* isolate, const ExternalReference& reference) {
114 Address address = reference.address();
115 return isolate->root_register_addressable_region().contains(address);
116}
117
118void 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