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