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/execution/isolate.h" 8#include "src/heap/heap-inl.h" 9#include "src/objects/oddball-inl.h" 10#include "src/roots/roots-inl.h" 11 12namespace v8 { 13namespace internal { 14 15BuiltinsConstantsTableBuilder::BuiltinsConstantsTableBuilder(Isolate* isolate) 16 : 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} 26 27uint32_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 auto find_result = map_.FindOrInsert(object); 50 if (!find_result.already_exists) { 51 DCHECK(object->IsHeapObject()); 52 *find_result.entry = map_.size() - 1; 53 } 54 return *find_result.entry; 55} 56 57namespace { 58void CheckPreconditionsForPatching(Isolate* isolate, 59 Handle<Object> replacement_object) { 60 // Roots must not be inserted into the constants table as they are already 61 // accessible from the root list. 62 RootIndex root_list_index; 63 DCHECK(!isolate->roots_table().IsRootHandle(replacement_object, 64 &root_list_index)); 65 USE(root_list_index); 66 67 // Not yet finalized. 68 DCHECK_EQ(ReadOnlyRoots(isolate).empty_fixed_array(), 69 isolate->heap()->builtins_constants_table()); 70 71 DCHECK(isolate->IsGeneratingEmbeddedBuiltins()); 72} 73} // namespace 74 75void BuiltinsConstantsTableBuilder::PatchSelfReference( 76 Handle<Object> self_reference, Handle<Code> code_object) { 77 CheckPreconditionsForPatching(isolate_, code_object); 78 DCHECK(self_reference->IsOddball()); 79 DCHECK(Oddball::cast(*self_reference).kind() == 80 Oddball::kSelfReferenceMarker); 81 82 uint32_t key; 83 if (map_.Delete(self_reference, &key)) { 84 DCHECK(code_object->IsCode()); 85 map_.Insert(code_object, key); 86 } 87} 88 89void BuiltinsConstantsTableBuilder::PatchBasicBlockCountersReference( 90 Handle<ByteArray> counters) { 91 CheckPreconditionsForPatching(isolate_, counters); 92 93 uint32_t key; 94 if (map_.Delete(ReadOnlyRoots(isolate_).basic_block_counters_marker(), 95 &key)) { 96 map_.Insert(counters, key); 97 } 98} 99 100void BuiltinsConstantsTableBuilder::Finalize() { 101 HandleScope handle_scope(isolate_); 102 103 DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(), 104 isolate_->heap()->builtins_constants_table()); 105 DCHECK(isolate_->IsGeneratingEmbeddedBuiltins()); 106 107 // An empty map means there's nothing to do. 108 if (map_.size() == 0) return; 109 110 Handle<FixedArray> table = 111 isolate_->factory()->NewFixedArray(map_.size(), AllocationType::kOld); 112 113 Builtins* builtins = isolate_->builtins(); 114 ConstantsMap::IteratableScope it_scope(&map_); 115 for (auto it = it_scope.begin(); it != it_scope.end(); ++it) { 116 uint32_t index = *it.entry(); 117 Object value = it.key(); 118 if (value.IsCode() && Code::cast(value).kind() == CodeKind::BUILTIN) { 119 // Replace placeholder code objects with the real builtin. 120 // See also: SetupIsolateDelegate::PopulateWithPlaceholders. 121 // TODO(jgruber): Deduplicate placeholders and their corresponding 122 // builtin. 123 value = builtins->code(Code::cast(value).builtin_id()); 124 } 125 DCHECK(value.IsHeapObject()); 126 table->set(index, value); 127 } 128 129#ifdef DEBUG 130 for (int i = 0; i < map_.size(); i++) { 131 DCHECK(table->get(i).IsHeapObject()); 132 DCHECK_NE(ReadOnlyRoots(isolate_).undefined_value(), table->get(i)); 133 DCHECK_NE(ReadOnlyRoots(isolate_).self_reference_marker(), table->get(i)); 134 DCHECK_NE(ReadOnlyRoots(isolate_).basic_block_counters_marker(), 135 table->get(i)); 136 } 137#endif 138 139 isolate_->heap()->SetBuiltinsConstantsTable(*table); 140} 141 142} // namespace internal 143} // namespace v8 144