1// Copyright 2020 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/codegen/external-reference-encoder.h" 6 7#include "src/codegen/external-reference-table.h" 8#include "src/execution/isolate.h" 9 10namespace v8 { 11namespace internal { 12 13ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) { 14#ifdef DEBUG 15 api_references_ = isolate->api_external_references(); 16 if (api_references_ != nullptr) { 17 for (uint32_t i = 0; api_references_[i] != 0; ++i) count_.push_back(0); 18 } 19#endif // DEBUG 20 map_ = isolate->external_reference_map(); 21 if (map_ != nullptr) return; 22 map_ = new AddressToIndexHashMap(); 23 isolate->set_external_reference_map(map_); 24 // Add V8's external references. 25 ExternalReferenceTable* table = isolate->external_reference_table(); 26 for (uint32_t i = 0; i < ExternalReferenceTable::kSize; ++i) { 27 Address addr = table->address(i); 28 // Ignore duplicate references. 29 // This can happen due to ICF. See http://crbug.com/726896. 30 if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, false)); 31 DCHECK(map_->Get(addr).IsJust()); 32 } 33 // Add external references provided by the embedder. 34 const intptr_t* api_references = isolate->api_external_references(); 35 if (api_references == nullptr) return; 36 for (uint32_t i = 0; api_references[i] != 0; ++i) { 37 Address addr = static_cast<Address>(api_references[i]); 38 // Ignore duplicate references. 39 // This can happen due to ICF. See http://crbug.com/726896. 40 if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, true)); 41 DCHECK(map_->Get(addr).IsJust()); 42 } 43} 44 45#ifdef DEBUG 46ExternalReferenceEncoder::~ExternalReferenceEncoder() { 47 if (!i::FLAG_external_reference_stats) return; 48 if (api_references_ == nullptr) return; 49 for (uint32_t i = 0; api_references_[i] != 0; ++i) { 50 Address addr = static_cast<Address>(api_references_[i]); 51 DCHECK(map_->Get(addr).IsJust()); 52 v8::base::OS::Print( 53 "index=%5d count=%5d %-60s\n", i, count_[i], 54 ExternalReferenceTable::ResolveSymbol(reinterpret_cast<void*>(addr))); 55 } 56} 57#endif // DEBUG 58 59Maybe<ExternalReferenceEncoder::Value> ExternalReferenceEncoder::TryEncode( 60 Address address) { 61 Maybe<uint32_t> maybe_index = map_->Get(address); 62 if (maybe_index.IsNothing()) return Nothing<Value>(); 63 Value result(maybe_index.FromJust()); 64#ifdef DEBUG 65 if (result.is_from_api()) count_[result.index()]++; 66#endif // DEBUG 67 return Just<Value>(result); 68} 69 70ExternalReferenceEncoder::Value ExternalReferenceEncoder::Encode( 71 Address address) { 72 Maybe<uint32_t> maybe_index = map_->Get(address); 73 if (maybe_index.IsNothing()) { 74 void* addr = reinterpret_cast<void*>(address); 75 v8::base::OS::PrintError("Unknown external reference %p.\n", addr); 76 v8::base::OS::PrintError("%s\n", 77 ExternalReferenceTable::ResolveSymbol(addr)); 78 v8::base::OS::Abort(); 79 } 80 Value result(maybe_index.FromJust()); 81#ifdef DEBUG 82 if (result.is_from_api()) count_[result.index()]++; 83#endif // DEBUG 84 return result; 85} 86 87const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate, 88 Address address) const { 89 Maybe<uint32_t> maybe_index = map_->Get(address); 90 if (maybe_index.IsNothing()) return "<unknown>"; 91 Value value(maybe_index.FromJust()); 92 if (value.is_from_api()) return "<from api>"; 93 return isolate->external_reference_table()->name(value.index()); 94} 95 96} // namespace internal 97} // namespace v8 98