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 40544 : 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_EQ(ThreadId::Current(), isolate_->thread_id());
40 :
41 : // Must be generating embedded builtin code.
42 : DCHECK(isolate_->IsGeneratingEmbeddedBuiltins());
43 :
44 : // All code objects should be loaded through the root register or use
45 : // pc-relative addressing.
46 : DCHECK(!object->IsCode());
47 : #endif
48 :
49 : uint32_t* maybe_key = map_.Find(object);
50 40544 : if (maybe_key == nullptr) {
51 : DCHECK(object->IsHeapObject());
52 12992 : uint32_t index = map_.size();
53 : map_.Set(object, index);
54 12992 : return index;
55 : } else {
56 27552 : return *maybe_key;
57 : }
58 : }
59 :
60 104664 : void BuiltinsConstantsTableBuilder::PatchSelfReference(
61 : Handle<Object> self_reference, Handle<Code> code_object) {
62 : #ifdef DEBUG
63 : // Roots must not be inserted into the constants table as they are already
64 : // accessibly from the root list.
65 : RootIndex root_list_index;
66 : DCHECK(!isolate_->roots_table().IsRootHandle(code_object, &root_list_index));
67 :
68 : // Not yet finalized.
69 : DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(),
70 : isolate_->heap()->builtins_constants_table());
71 :
72 : DCHECK(isolate_->IsGeneratingEmbeddedBuiltins());
73 :
74 : DCHECK(self_reference->IsOddball());
75 : DCHECK(Oddball::cast(*self_reference)->kind() ==
76 : Oddball::kSelfReferenceMarker);
77 : #endif
78 :
79 : uint32_t key;
80 104664 : if (map_.Delete(self_reference, &key)) {
81 : DCHECK(code_object->IsCode());
82 : map_.Set(code_object, key);
83 : }
84 104664 : }
85 :
86 56 : void BuiltinsConstantsTableBuilder::Finalize() {
87 56 : HandleScope handle_scope(isolate_);
88 :
89 : DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(),
90 : isolate_->heap()->builtins_constants_table());
91 : DCHECK(isolate_->IsGeneratingEmbeddedBuiltins());
92 :
93 : // An empty map means there's nothing to do.
94 56 : if (map_.size() == 0) return;
95 :
96 : Handle<FixedArray> table =
97 56 : isolate_->factory()->NewFixedArray(map_.size(), AllocationType::kOld);
98 :
99 56 : Builtins* builtins = isolate_->builtins();
100 112 : ConstantsMap::IteratableScope it_scope(&map_);
101 13048 : for (auto it = it_scope.begin(); it != it_scope.end(); ++it) {
102 12992 : uint32_t index = *it.entry();
103 : Object value = it.key();
104 12992 : if (value->IsCode() && Code::cast(value)->kind() == Code::BUILTIN) {
105 : // Replace placeholder code objects with the real builtin.
106 : // See also: SetupIsolateDelegate::PopulateWithPlaceholders.
107 : // TODO(jgruber): Deduplicate placeholders and their corresponding
108 : // builtin.
109 0 : value = builtins->builtin(Code::cast(value)->builtin_index());
110 : }
111 : DCHECK(value->IsHeapObject());
112 25984 : table->set(index, value);
113 : }
114 :
115 : #ifdef DEBUG
116 : for (int i = 0; i < map_.size(); i++) {
117 : DCHECK(table->get(i)->IsHeapObject());
118 : DCHECK_NE(ReadOnlyRoots(isolate_).undefined_value(), table->get(i));
119 : DCHECK_NE(ReadOnlyRoots(isolate_).self_reference_marker(), table->get(i));
120 : }
121 : #endif
122 :
123 112 : isolate_->heap()->SetBuiltinsConstantsTable(*table);
124 : }
125 :
126 : } // namespace internal
127 121996 : } // namespace v8
|