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/builtins/constants-table-builder.h"
6
7 #include "src/heap/heap-inl.h"
8
9 namespace v8 {
10 namespace internal {
11
BuiltinsConstantsTableBuilder(Isolate * isolate)12 BuiltinsConstantsTableBuilder::BuiltinsConstantsTableBuilder(Isolate* isolate)
13 : isolate_(isolate), map_(isolate->heap()) {
14 // Ensure this is only called once per Isolate.
15 DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(),
16 isolate_->heap()->builtins_constants_table());
17
18 // And that the initial value of the builtins constants table can be treated
19 // as a constant, which means that codegen will load it using the root
20 // register.
21 DCHECK(isolate_->heap()->RootCanBeTreatedAsConstant(
22 Heap::kEmptyFixedArrayRootIndex));
23 }
24
AddObject(Handle<Object> object)25 uint32_t BuiltinsConstantsTableBuilder::AddObject(Handle<Object> object) {
26 #ifdef DEBUG
27 // Roots must not be inserted into the constants table as they are already
28 // accessibly from the root list.
29 Heap::RootListIndex root_list_index;
30 DCHECK(!isolate_->heap()->IsRootHandle(object, &root_list_index));
31
32 // Not yet finalized.
33 DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(),
34 isolate_->heap()->builtins_constants_table());
35
36 // Must be on the main thread.
37 DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
38
39 // Must be serializing.
40 DCHECK(isolate_->serializer_enabled());
41 #endif
42
43 uint32_t* maybe_key = map_.Find(object);
44 if (maybe_key == nullptr) {
45 DCHECK(object->IsHeapObject());
46 uint32_t index = map_.size();
47 map_.Set(object, index);
48 return index;
49 } else {
50 return *maybe_key;
51 }
52 }
53
PatchSelfReference(Handle<Object> self_reference,Handle<Code> code_object)54 void BuiltinsConstantsTableBuilder::PatchSelfReference(
55 Handle<Object> self_reference, Handle<Code> code_object) {
56 #ifdef DEBUG
57 // Roots must not be inserted into the constants table as they are already
58 // accessibly from the root list.
59 Heap::RootListIndex root_list_index;
60 DCHECK(!isolate_->heap()->IsRootHandle(code_object, &root_list_index));
61
62 // Not yet finalized.
63 DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(),
64 isolate_->heap()->builtins_constants_table());
65
66 DCHECK(isolate_->serializer_enabled());
67
68 DCHECK(self_reference->IsOddball());
69 DCHECK(Oddball::cast(*self_reference)->kind() ==
70 Oddball::kSelfReferenceMarker);
71
72 // During indirection generation, we always create a distinct marker for each
73 // macro assembler. The canonical marker is only used when not generating a
74 // snapshot.
75 DCHECK(*self_reference != ReadOnlyRoots(isolate_).self_reference_marker());
76 #endif
77
78 uint32_t key;
79 if (map_.Delete(self_reference, &key)) {
80 DCHECK(code_object->IsCode());
81 map_.Set(code_object, key);
82 }
83 }
84
Finalize()85 void BuiltinsConstantsTableBuilder::Finalize() {
86 HandleScope handle_scope(isolate_);
87
88 DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(),
89 isolate_->heap()->builtins_constants_table());
90 DCHECK(isolate_->serializer_enabled());
91
92 // An empty map means there's nothing to do.
93 if (map_.size() == 0) return;
94
95 Handle<FixedArray> table =
96 isolate_->factory()->NewFixedArray(map_.size(), TENURED);
97
98 Builtins* builtins = isolate_->builtins();
99 ConstantsMap::IteratableScope it_scope(&map_);
100 for (auto it = it_scope.begin(); it != it_scope.end(); ++it) {
101 uint32_t index = *it.entry();
102 Object* value = it.key();
103 if (value->IsCode() && Code::cast(value)->kind() == Code::BUILTIN) {
104 // Replace placeholder code objects with the real builtin.
105 // See also: SetupIsolateDelegate::PopulateWithPlaceholders.
106 // TODO(jgruber): Deduplicate placeholders and their corresponding
107 // builtin.
108 value = builtins->builtin(Code::cast(value)->builtin_index());
109 }
110 DCHECK(value->IsHeapObject());
111 table->set(index, value);
112 }
113
114 #ifdef DEBUG
115 for (int i = 0; i < map_.size(); i++) {
116 DCHECK(table->get(i)->IsHeapObject());
117 DCHECK_NE(ReadOnlyRoots(isolate_).undefined_value(), table->get(i));
118 DCHECK_NE(ReadOnlyRoots(isolate_).self_reference_marker(), table->get(i));
119 }
120 #endif
121
122 isolate_->heap()->SetBuiltinsConstantsTable(*table);
123 }
124
125 } // namespace internal
126 } // namespace v8
127