• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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