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