11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/builtins/constants-table-builder.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/execution/isolate.h" 81cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h" 91cb0ef41Sopenharmony_ci#include "src/objects/oddball-inl.h" 101cb0ef41Sopenharmony_ci#include "src/roots/roots-inl.h" 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cinamespace v8 { 131cb0ef41Sopenharmony_cinamespace internal { 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciBuiltinsConstantsTableBuilder::BuiltinsConstantsTableBuilder(Isolate* isolate) 161cb0ef41Sopenharmony_ci : isolate_(isolate), map_(isolate->heap()) { 171cb0ef41Sopenharmony_ci // Ensure this is only called once per Isolate. 181cb0ef41Sopenharmony_ci DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(), 191cb0ef41Sopenharmony_ci isolate_->heap()->builtins_constants_table()); 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci // And that the initial value of the builtins constants table can be treated 221cb0ef41Sopenharmony_ci // as a constant, which means that codegen will load it using the root 231cb0ef41Sopenharmony_ci // register. 241cb0ef41Sopenharmony_ci DCHECK(RootsTable::IsImmortalImmovable(RootIndex::kEmptyFixedArray)); 251cb0ef41Sopenharmony_ci} 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciuint32_t BuiltinsConstantsTableBuilder::AddObject(Handle<Object> object) { 281cb0ef41Sopenharmony_ci#ifdef DEBUG 291cb0ef41Sopenharmony_ci // Roots must not be inserted into the constants table as they are already 301cb0ef41Sopenharmony_ci // accessibly from the root list. 311cb0ef41Sopenharmony_ci RootIndex root_list_index; 321cb0ef41Sopenharmony_ci DCHECK(!isolate_->roots_table().IsRootHandle(object, &root_list_index)); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci // Not yet finalized. 351cb0ef41Sopenharmony_ci DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(), 361cb0ef41Sopenharmony_ci isolate_->heap()->builtins_constants_table()); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci // Must be on the main thread. 391cb0ef41Sopenharmony_ci DCHECK_EQ(ThreadId::Current(), isolate_->thread_id()); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci // Must be generating embedded builtin code. 421cb0ef41Sopenharmony_ci DCHECK(isolate_->IsGeneratingEmbeddedBuiltins()); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci // All code objects should be loaded through the root register or use 451cb0ef41Sopenharmony_ci // pc-relative addressing. 461cb0ef41Sopenharmony_ci DCHECK(!object->IsCode()); 471cb0ef41Sopenharmony_ci#endif 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci auto find_result = map_.FindOrInsert(object); 501cb0ef41Sopenharmony_ci if (!find_result.already_exists) { 511cb0ef41Sopenharmony_ci DCHECK(object->IsHeapObject()); 521cb0ef41Sopenharmony_ci *find_result.entry = map_.size() - 1; 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci return *find_result.entry; 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_cinamespace { 581cb0ef41Sopenharmony_civoid CheckPreconditionsForPatching(Isolate* isolate, 591cb0ef41Sopenharmony_ci Handle<Object> replacement_object) { 601cb0ef41Sopenharmony_ci // Roots must not be inserted into the constants table as they are already 611cb0ef41Sopenharmony_ci // accessible from the root list. 621cb0ef41Sopenharmony_ci RootIndex root_list_index; 631cb0ef41Sopenharmony_ci DCHECK(!isolate->roots_table().IsRootHandle(replacement_object, 641cb0ef41Sopenharmony_ci &root_list_index)); 651cb0ef41Sopenharmony_ci USE(root_list_index); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci // Not yet finalized. 681cb0ef41Sopenharmony_ci DCHECK_EQ(ReadOnlyRoots(isolate).empty_fixed_array(), 691cb0ef41Sopenharmony_ci isolate->heap()->builtins_constants_table()); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci DCHECK(isolate->IsGeneratingEmbeddedBuiltins()); 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci} // namespace 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_civoid BuiltinsConstantsTableBuilder::PatchSelfReference( 761cb0ef41Sopenharmony_ci Handle<Object> self_reference, Handle<Code> code_object) { 771cb0ef41Sopenharmony_ci CheckPreconditionsForPatching(isolate_, code_object); 781cb0ef41Sopenharmony_ci DCHECK(self_reference->IsOddball()); 791cb0ef41Sopenharmony_ci DCHECK(Oddball::cast(*self_reference).kind() == 801cb0ef41Sopenharmony_ci Oddball::kSelfReferenceMarker); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci uint32_t key; 831cb0ef41Sopenharmony_ci if (map_.Delete(self_reference, &key)) { 841cb0ef41Sopenharmony_ci DCHECK(code_object->IsCode()); 851cb0ef41Sopenharmony_ci map_.Insert(code_object, key); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_civoid BuiltinsConstantsTableBuilder::PatchBasicBlockCountersReference( 901cb0ef41Sopenharmony_ci Handle<ByteArray> counters) { 911cb0ef41Sopenharmony_ci CheckPreconditionsForPatching(isolate_, counters); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci uint32_t key; 941cb0ef41Sopenharmony_ci if (map_.Delete(ReadOnlyRoots(isolate_).basic_block_counters_marker(), 951cb0ef41Sopenharmony_ci &key)) { 961cb0ef41Sopenharmony_ci map_.Insert(counters, key); 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_civoid BuiltinsConstantsTableBuilder::Finalize() { 1011cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate_); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci DCHECK_EQ(ReadOnlyRoots(isolate_).empty_fixed_array(), 1041cb0ef41Sopenharmony_ci isolate_->heap()->builtins_constants_table()); 1051cb0ef41Sopenharmony_ci DCHECK(isolate_->IsGeneratingEmbeddedBuiltins()); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci // An empty map means there's nothing to do. 1081cb0ef41Sopenharmony_ci if (map_.size() == 0) return; 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci Handle<FixedArray> table = 1111cb0ef41Sopenharmony_ci isolate_->factory()->NewFixedArray(map_.size(), AllocationType::kOld); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci Builtins* builtins = isolate_->builtins(); 1141cb0ef41Sopenharmony_ci ConstantsMap::IteratableScope it_scope(&map_); 1151cb0ef41Sopenharmony_ci for (auto it = it_scope.begin(); it != it_scope.end(); ++it) { 1161cb0ef41Sopenharmony_ci uint32_t index = *it.entry(); 1171cb0ef41Sopenharmony_ci Object value = it.key(); 1181cb0ef41Sopenharmony_ci if (value.IsCode() && Code::cast(value).kind() == CodeKind::BUILTIN) { 1191cb0ef41Sopenharmony_ci // Replace placeholder code objects with the real builtin. 1201cb0ef41Sopenharmony_ci // See also: SetupIsolateDelegate::PopulateWithPlaceholders. 1211cb0ef41Sopenharmony_ci // TODO(jgruber): Deduplicate placeholders and their corresponding 1221cb0ef41Sopenharmony_ci // builtin. 1231cb0ef41Sopenharmony_ci value = builtins->code(Code::cast(value).builtin_id()); 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci DCHECK(value.IsHeapObject()); 1261cb0ef41Sopenharmony_ci table->set(index, value); 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci#ifdef DEBUG 1301cb0ef41Sopenharmony_ci for (int i = 0; i < map_.size(); i++) { 1311cb0ef41Sopenharmony_ci DCHECK(table->get(i).IsHeapObject()); 1321cb0ef41Sopenharmony_ci DCHECK_NE(ReadOnlyRoots(isolate_).undefined_value(), table->get(i)); 1331cb0ef41Sopenharmony_ci DCHECK_NE(ReadOnlyRoots(isolate_).self_reference_marker(), table->get(i)); 1341cb0ef41Sopenharmony_ci DCHECK_NE(ReadOnlyRoots(isolate_).basic_block_counters_marker(), 1351cb0ef41Sopenharmony_ci table->get(i)); 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci#endif 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci isolate_->heap()->SetBuiltinsConstantsTable(*table); 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci} // namespace internal 1431cb0ef41Sopenharmony_ci} // namespace v8 144