11cb0ef41Sopenharmony_ci// Copyright 2020 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/codegen/external-reference-encoder.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/codegen/external-reference-table.h"
81cb0ef41Sopenharmony_ci#include "src/execution/isolate.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_cinamespace internal {
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) {
141cb0ef41Sopenharmony_ci#ifdef DEBUG
151cb0ef41Sopenharmony_ci  api_references_ = isolate->api_external_references();
161cb0ef41Sopenharmony_ci  if (api_references_ != nullptr) {
171cb0ef41Sopenharmony_ci    for (uint32_t i = 0; api_references_[i] != 0; ++i) count_.push_back(0);
181cb0ef41Sopenharmony_ci  }
191cb0ef41Sopenharmony_ci#endif  // DEBUG
201cb0ef41Sopenharmony_ci  map_ = isolate->external_reference_map();
211cb0ef41Sopenharmony_ci  if (map_ != nullptr) return;
221cb0ef41Sopenharmony_ci  map_ = new AddressToIndexHashMap();
231cb0ef41Sopenharmony_ci  isolate->set_external_reference_map(map_);
241cb0ef41Sopenharmony_ci  // Add V8's external references.
251cb0ef41Sopenharmony_ci  ExternalReferenceTable* table = isolate->external_reference_table();
261cb0ef41Sopenharmony_ci  for (uint32_t i = 0; i < ExternalReferenceTable::kSize; ++i) {
271cb0ef41Sopenharmony_ci    Address addr = table->address(i);
281cb0ef41Sopenharmony_ci    // Ignore duplicate references.
291cb0ef41Sopenharmony_ci    // This can happen due to ICF. See http://crbug.com/726896.
301cb0ef41Sopenharmony_ci    if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, false));
311cb0ef41Sopenharmony_ci    DCHECK(map_->Get(addr).IsJust());
321cb0ef41Sopenharmony_ci  }
331cb0ef41Sopenharmony_ci  // Add external references provided by the embedder.
341cb0ef41Sopenharmony_ci  const intptr_t* api_references = isolate->api_external_references();
351cb0ef41Sopenharmony_ci  if (api_references == nullptr) return;
361cb0ef41Sopenharmony_ci  for (uint32_t i = 0; api_references[i] != 0; ++i) {
371cb0ef41Sopenharmony_ci    Address addr = static_cast<Address>(api_references[i]);
381cb0ef41Sopenharmony_ci    // Ignore duplicate references.
391cb0ef41Sopenharmony_ci    // This can happen due to ICF. See http://crbug.com/726896.
401cb0ef41Sopenharmony_ci    if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, true));
411cb0ef41Sopenharmony_ci    DCHECK(map_->Get(addr).IsJust());
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci}
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci#ifdef DEBUG
461cb0ef41Sopenharmony_ciExternalReferenceEncoder::~ExternalReferenceEncoder() {
471cb0ef41Sopenharmony_ci  if (!i::FLAG_external_reference_stats) return;
481cb0ef41Sopenharmony_ci  if (api_references_ == nullptr) return;
491cb0ef41Sopenharmony_ci  for (uint32_t i = 0; api_references_[i] != 0; ++i) {
501cb0ef41Sopenharmony_ci    Address addr = static_cast<Address>(api_references_[i]);
511cb0ef41Sopenharmony_ci    DCHECK(map_->Get(addr).IsJust());
521cb0ef41Sopenharmony_ci    v8::base::OS::Print(
531cb0ef41Sopenharmony_ci        "index=%5d count=%5d  %-60s\n", i, count_[i],
541cb0ef41Sopenharmony_ci        ExternalReferenceTable::ResolveSymbol(reinterpret_cast<void*>(addr)));
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci}
571cb0ef41Sopenharmony_ci#endif  // DEBUG
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ciMaybe<ExternalReferenceEncoder::Value> ExternalReferenceEncoder::TryEncode(
601cb0ef41Sopenharmony_ci    Address address) {
611cb0ef41Sopenharmony_ci  Maybe<uint32_t> maybe_index = map_->Get(address);
621cb0ef41Sopenharmony_ci  if (maybe_index.IsNothing()) return Nothing<Value>();
631cb0ef41Sopenharmony_ci  Value result(maybe_index.FromJust());
641cb0ef41Sopenharmony_ci#ifdef DEBUG
651cb0ef41Sopenharmony_ci  if (result.is_from_api()) count_[result.index()]++;
661cb0ef41Sopenharmony_ci#endif  // DEBUG
671cb0ef41Sopenharmony_ci  return Just<Value>(result);
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciExternalReferenceEncoder::Value ExternalReferenceEncoder::Encode(
711cb0ef41Sopenharmony_ci    Address address) {
721cb0ef41Sopenharmony_ci  Maybe<uint32_t> maybe_index = map_->Get(address);
731cb0ef41Sopenharmony_ci  if (maybe_index.IsNothing()) {
741cb0ef41Sopenharmony_ci    void* addr = reinterpret_cast<void*>(address);
751cb0ef41Sopenharmony_ci    v8::base::OS::PrintError("Unknown external reference %p.\n", addr);
761cb0ef41Sopenharmony_ci    v8::base::OS::PrintError("%s\n",
771cb0ef41Sopenharmony_ci                             ExternalReferenceTable::ResolveSymbol(addr));
781cb0ef41Sopenharmony_ci    v8::base::OS::Abort();
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci  Value result(maybe_index.FromJust());
811cb0ef41Sopenharmony_ci#ifdef DEBUG
821cb0ef41Sopenharmony_ci  if (result.is_from_api()) count_[result.index()]++;
831cb0ef41Sopenharmony_ci#endif  // DEBUG
841cb0ef41Sopenharmony_ci  return result;
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ciconst char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
881cb0ef41Sopenharmony_ci                                                    Address address) const {
891cb0ef41Sopenharmony_ci  Maybe<uint32_t> maybe_index = map_->Get(address);
901cb0ef41Sopenharmony_ci  if (maybe_index.IsNothing()) return "<unknown>";
911cb0ef41Sopenharmony_ci  Value value(maybe_index.FromJust());
921cb0ef41Sopenharmony_ci  if (value.is_from_api()) return "<from api>";
931cb0ef41Sopenharmony_ci  return isolate->external_reference_table()->name(value.index());
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci}  // namespace internal
971cb0ef41Sopenharmony_ci}  // namespace v8
98