LCOV - code coverage report
Current view: top level - src/objects - code.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 235 285 82.5 %
Date: 2019-04-18 Functions: 45 52 86.5 %

          Line data    Source code
       1             : // Copyright 2019 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 <iomanip>
       6             : 
       7             : #include "src/objects/code.h"
       8             : 
       9             : #include "src/assembler-inl.h"
      10             : #include "src/cpu-features.h"
      11             : #include "src/deoptimizer.h"
      12             : #include "src/interpreter/bytecode-array-iterator.h"
      13             : #include "src/interpreter/bytecode-decoder.h"
      14             : #include "src/interpreter/interpreter.h"
      15             : #include "src/objects/allocation-site-inl.h"
      16             : #include "src/ostreams.h"
      17             : #include "src/reloc-info.h"
      18             : #include "src/roots-inl.h"
      19             : #include "src/safepoint-table.h"
      20             : #include "src/snapshot/embedded-data.h"
      21             : 
      22             : #ifdef ENABLE_DISASSEMBLER
      23             : #include "src/code-comments.h"
      24             : #include "src/disasm.h"
      25             : #include "src/disassembler.h"
      26             : #include "src/eh-frame.h"
      27             : #endif
      28             : 
      29             : namespace v8 {
      30             : namespace internal {
      31             : 
      32           0 : int Code::safepoint_table_size() const {
      33             :   DCHECK_GE(handler_table_offset() - safepoint_table_offset(), 0);
      34         753 :   return handler_table_offset() - safepoint_table_offset();
      35             : }
      36             : 
      37        1506 : bool Code::has_safepoint_table() const { return safepoint_table_size() > 0; }
      38             : 
      39     3573270 : int Code::handler_table_size() const {
      40             :   DCHECK_GE(constant_pool_offset() - handler_table_offset(), 0);
      41     4025794 :   return constant_pool_offset() - handler_table_offset();
      42             : }
      43             : 
      44      905048 : bool Code::has_handler_table() const { return handler_table_size() > 0; }
      45             : 
      46           0 : int Code::constant_pool_size() const {
      47             :   const int size = code_comments_offset() - constant_pool_offset();
      48             :   DCHECK_IMPLIES(!FLAG_enable_embedded_constant_pool, size == 0);
      49             :   DCHECK_GE(size, 0);
      50           0 :   return size;
      51             : }
      52             : 
      53   208193990 : bool Code::has_constant_pool() const { return constant_pool_size() > 0; }
      54             : 
      55           4 : int Code::code_comments_size() const {
      56             :   DCHECK_GE(InstructionSize() - code_comments_offset(), 0);
      57           4 :   return InstructionSize() - code_comments_offset();
      58             : }
      59             : 
      60           0 : bool Code::has_code_comments() const { return code_comments_size() > 0; }
      61             : 
      62           0 : int Code::ExecutableInstructionSize() const { return safepoint_table_offset(); }
      63             : 
      64         242 : void Code::ClearEmbeddedObjects(Heap* heap) {
      65             :   HeapObject undefined = ReadOnlyRoots(heap).undefined_value();
      66             :   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
      67        3579 :   for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
      68             :     RelocInfo::Mode mode = it.rinfo()->rmode();
      69        3337 :     if (mode == RelocInfo::EMBEDDED_OBJECT) {
      70             :       it.rinfo()->set_target_object(heap, undefined, SKIP_WRITE_BARRIER);
      71             :     }
      72             :   }
      73         242 :   set_embedded_objects_cleared(true);
      74         242 : }
      75             : 
      76        1807 : void Code::Relocate(intptr_t delta) {
      77       41349 :   for (RelocIterator it(*this, RelocInfo::kApplyMask); !it.done(); it.next()) {
      78             :     it.rinfo()->apply(delta);
      79             :   }
      80             :   FlushICache();
      81        1807 : }
      82             : 
      83     1906418 : void Code::FlushICache() const {
      84     1908225 :   FlushInstructionCache(raw_instruction_start(), raw_instruction_size());
      85     1906418 : }
      86             : 
      87     1906418 : void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
      88             :   // Copy code.
      89     3812836 :   CopyBytes(reinterpret_cast<byte*>(raw_instruction_start()), desc.buffer,
      90     1906418 :             static_cast<size_t>(desc.instr_size));
      91             : 
      92             :   // Copy unwinding info, if any.
      93     1906416 :   if (desc.unwinding_info) {
      94             :     DCHECK_GT(desc.unwinding_info_size, 0);
      95          27 :     set_unwinding_info_size(desc.unwinding_info_size);
      96          54 :     CopyBytes(reinterpret_cast<byte*>(unwinding_info_start()),
      97          27 :               desc.unwinding_info,
      98          27 :               static_cast<size_t>(desc.unwinding_info_size));
      99             :   }
     100             : 
     101             :   // Copy reloc info.
     102             :   CopyRelocInfoToByteArray(unchecked_relocation_info(), desc);
     103             : 
     104             :   // Unbox handles and relocate.
     105     1906418 :   Assembler* origin = desc.origin;
     106             :   AllowDeferredHandleDereference embedding_raw_address;
     107             :   const int mode_mask = RelocInfo::PostCodegenRelocationMask();
     108    12057462 :   for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
     109             :     RelocInfo::Mode mode = it.rinfo()->rmode();
     110    10151045 :     if (mode == RelocInfo::EMBEDDED_OBJECT) {
     111             :       Handle<HeapObject> p = it.rinfo()->target_object_handle(origin);
     112             :       it.rinfo()->set_target_object(heap, *p, UPDATE_WRITE_BARRIER,
     113             :                                     SKIP_ICACHE_FLUSH);
     114     3862646 :     } else if (RelocInfo::IsCodeTargetMode(mode)) {
     115             :       // Rewrite code handles to direct pointers to the first instruction in the
     116             :       // code object.
     117             :       Handle<Object> p = it.rinfo()->target_object_handle(origin);
     118             :       Code code = Code::cast(*p);
     119             :       it.rinfo()->set_target_address(code->raw_instruction_start(),
     120      528408 :                                      UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     121     3334239 :     } else if (RelocInfo::IsRuntimeEntry(mode)) {
     122             :       Address p = it.rinfo()->target_runtime_entry(origin);
     123             :       it.rinfo()->set_target_runtime_entry(p, UPDATE_WRITE_BARRIER,
     124             :                                            SKIP_ICACHE_FLUSH);
     125             :     } else {
     126             :       intptr_t delta =
     127        6512 :           raw_instruction_start() - reinterpret_cast<Address>(desc.buffer);
     128             :       it.rinfo()->apply(delta);
     129             :     }
     130             :   }
     131     1906420 : }
     132             : 
     133     2852639 : SafepointEntry Code::GetSafepointEntry(Address pc) {
     134     2852639 :   SafepointTable table(*this);
     135     2852639 :   return table.FindEntry(pc);
     136             : }
     137             : 
     138       64996 : int Code::OffHeapInstructionSize() const {
     139             :   DCHECK(is_off_heap_trampoline());
     140       64996 :   if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_size();
     141       64996 :   EmbeddedData d = EmbeddedData::FromBlob();
     142       64996 :   return d.InstructionSizeOfBuiltin(builtin_index());
     143             : }
     144             : 
     145   155419519 : Address Code::OffHeapInstructionStart() const {
     146             :   DCHECK(is_off_heap_trampoline());
     147   155419519 :   if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_start();
     148   155419751 :   EmbeddedData d = EmbeddedData::FromBlob();
     149   155419751 :   return d.InstructionStartOfBuiltin(builtin_index());
     150             : }
     151             : 
     152      366586 : Address Code::OffHeapInstructionEnd() const {
     153             :   DCHECK(is_off_heap_trampoline());
     154      366586 :   if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_end();
     155      366586 :   EmbeddedData d = EmbeddedData::FromBlob();
     156      733172 :   return d.InstructionStartOfBuiltin(builtin_index()) +
     157      733172 :          d.InstructionSizeOfBuiltin(builtin_index());
     158             : }
     159             : 
     160             : namespace {
     161             : template <typename Code>
     162        8543 : void SetStackFrameCacheCommon(Isolate* isolate, Handle<Code> code,
     163             :                               Handle<SimpleNumberDictionary> cache) {
     164             :   Handle<Object> maybe_table(code->source_position_table(), isolate);
     165       17435 :   if (maybe_table->IsException(isolate) || maybe_table->IsUndefined()) return;
     166        8543 :   if (maybe_table->IsSourcePositionTableWithFrameCache()) {
     167         349 :     Handle<SourcePositionTableWithFrameCache>::cast(maybe_table)
     168         698 :         ->set_stack_frame_cache(*cache);
     169         349 :     return;
     170             :   }
     171             :   DCHECK(maybe_table->IsByteArray());
     172        8194 :   Handle<ByteArray> table(Handle<ByteArray>::cast(maybe_table));
     173             :   Handle<SourcePositionTableWithFrameCache> table_with_cache =
     174        8194 :       isolate->factory()->NewSourcePositionTableWithFrameCache(table, cache);
     175       16388 :   code->set_source_position_table(*table_with_cache);
     176             : }
     177             : }  // namespace
     178             : 
     179             : // static
     180        8543 : void AbstractCode::SetStackFrameCache(Handle<AbstractCode> abstract_code,
     181             :                                       Handle<SimpleNumberDictionary> cache) {
     182        8543 :   if (abstract_code->IsCode()) {
     183             :     SetStackFrameCacheCommon(
     184             :         abstract_code->GetIsolate(),
     185           0 :         handle(abstract_code->GetCode(), abstract_code->GetIsolate()), cache);
     186             :   } else {
     187             :     SetStackFrameCacheCommon(
     188             :         abstract_code->GetIsolate(),
     189             :         handle(abstract_code->GetBytecodeArray(), abstract_code->GetIsolate()),
     190        8543 :         cache);
     191             :   }
     192        8543 : }
     193             : 
     194             : namespace {
     195             : template <typename Code>
     196      792059 : void DropStackFrameCacheCommon(Code code) {
     197             :   i::Object maybe_table = code->source_position_table();
     198     1584118 :   if (maybe_table->IsUndefined() || maybe_table->IsByteArray()) return;
     199             :   DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
     200          28 :   code->set_source_position_table(
     201             :       i::SourcePositionTableWithFrameCache::cast(maybe_table)
     202             :           ->source_position_table());
     203             : }
     204             : }  // namespace
     205             : 
     206      792059 : void AbstractCode::DropStackFrameCache() {
     207      792059 :   if (IsCode()) {
     208      791668 :     DropStackFrameCacheCommon(GetCode());
     209             :   } else {
     210         391 :     DropStackFrameCacheCommon(GetBytecodeArray());
     211             :   }
     212      792059 : }
     213             : 
     214     1431367 : int AbstractCode::SourcePosition(int offset) {
     215     1431367 :   Object maybe_table = source_position_table();
     216     1431367 :   if (maybe_table->IsException()) return kNoSourcePosition;
     217             : 
     218     1431367 :   ByteArray source_position_table = ByteArray::cast(maybe_table);
     219             :   int position = 0;
     220             :   // Subtract one because the current PC is one instruction after the call site.
     221     2862734 :   if (IsCode()) offset--;
     222    73362902 :   for (SourcePositionTableIterator iterator(source_position_table);
     223    36681451 :        !iterator.done() && iterator.code_offset() <= offset;
     224    35250084 :        iterator.Advance()) {
     225             :     position = iterator.source_position().ScriptOffset();
     226             :   }
     227     1431367 :   return position;
     228             : }
     229             : 
     230      107662 : int AbstractCode::SourceStatementPosition(int offset) {
     231             :   // First find the closest position.
     232      107662 :   int position = SourcePosition(offset);
     233             :   // Now find the closest statement position before the position.
     234             :   int statement_position = 0;
     235    11178979 :   for (SourcePositionTableIterator it(source_position_table()); !it.done();
     236    11071317 :        it.Advance()) {
     237    11071317 :     if (it.is_statement()) {
     238             :       int p = it.source_position().ScriptOffset();
     239     7015009 :       if (statement_position < p && p <= position) {
     240             :         statement_position = p;
     241             :       }
     242             :     }
     243             :   }
     244      107662 :   return statement_position;
     245             : }
     246             : 
     247         240 : void Code::PrintDeoptLocation(FILE* out, const char* str, Address pc) {
     248         240 :   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(*this, pc);
     249         240 :   class SourcePosition pos = info.position;
     250         240 :   if (info.deopt_reason != DeoptimizeReason::kUnknown || pos.IsKnown()) {
     251         240 :     PrintF(out, "%s", str);
     252         480 :     OFStream outstr(out);
     253         240 :     pos.Print(outstr, *this);
     254         240 :     PrintF(out, ", %s\n", DeoptimizeReasonToString(info.deopt_reason));
     255             :   }
     256         240 : }
     257             : 
     258        7717 : bool Code::CanDeoptAt(Address pc) {
     259             :   DeoptimizationData deopt_data =
     260        7717 :       DeoptimizationData::cast(deoptimization_data());
     261             :   Address code_start_address = InstructionStart();
     262      164603 :   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
     263       84758 :     if (deopt_data->Pc(i)->value() == -1) continue;
     264       58805 :     Address address = code_start_address + deopt_data->Pc(i)->value();
     265       65120 :     if (address == pc && deopt_data->BytecodeOffset(i) != BailoutId::None()) {
     266             :       return true;
     267             :     }
     268             :   }
     269             :   return false;
     270             : }
     271             : 
     272             : // Identify kind of code.
     273       19661 : const char* Code::Kind2String(Kind kind) {
     274       19661 :   switch (kind) {
     275             : #define CASE(name) \
     276             :   case name:       \
     277             :     return #name;
     278           0 :     CODE_KIND_LIST(CASE)
     279             : #undef CASE
     280             :     case NUMBER_OF_KINDS:
     281             :       break;
     282             :   }
     283           0 :   UNREACHABLE();
     284             : }
     285             : 
     286             : // Identify kind of code.
     287           0 : const char* AbstractCode::Kind2String(Kind kind) {
     288           0 :   if (kind < AbstractCode::INTERPRETED_FUNCTION)
     289           0 :     return Code::Kind2String(static_cast<Code::Kind>(kind));
     290           0 :   if (kind == AbstractCode::INTERPRETED_FUNCTION) return "INTERPRETED_FUNCTION";
     291           0 :   UNREACHABLE();
     292             : }
     293             : 
     294       85232 : bool Code::IsIsolateIndependent(Isolate* isolate) {
     295             :   constexpr int all_real_modes_mask =
     296             :       (1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - 1;
     297             :   constexpr int mode_mask = all_real_modes_mask &
     298             :                             ~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
     299             :                             ~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
     300             :                             ~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
     301             :   STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);
     302             :   STATIC_ASSERT(mode_mask ==
     303             :                 (RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
     304             :                  RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
     305             :                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
     306             :                  RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
     307             :                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
     308             :                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
     309             :                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
     310             :                  RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
     311             :                  RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL)));
     312             : 
     313             :   bool is_process_independent = true;
     314      482720 :   for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
     315             : #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \
     316             :     defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) ||  \
     317             :     defined(V8_TARGET_ARCH_S390) || defined(V8_TARGET_ARCH_IA32)
     318             :     // On these platforms we emit relative builtin-to-builtin
     319             :     // jumps for isolate independent builtins in the snapshot. They are later
     320             :     // rewritten as pc-relative jumps to the off-heap instruction stream and are
     321             :     // thus process-independent. See also: FinalizeEmbeddedCodeTargets.
     322      397488 :     if (RelocInfo::IsCodeTargetMode(it.rinfo()->rmode())) {
     323             :       Address target_address = it.rinfo()->target_address();
     324      794976 :       if (InstructionStream::PcIsOffHeap(isolate, target_address)) continue;
     325             : 
     326      397488 :       Code target = Code::GetCodeFromTargetAddress(target_address);
     327      397488 :       CHECK(target->IsCode());
     328      397488 :       if (Builtins::IsIsolateIndependentBuiltin(target)) continue;
     329             :     }
     330             : #endif
     331             :     is_process_independent = false;
     332             :   }
     333             : 
     334       85232 :   return is_process_independent;
     335             : }
     336             : 
     337       17304 : bool Code::Inlines(SharedFunctionInfo sfi) {
     338             :   // We can only check for inlining for optimized code.
     339             :   DCHECK(is_optimized_code());
     340             :   DisallowHeapAllocation no_gc;
     341             :   DeoptimizationData const data =
     342             :       DeoptimizationData::cast(deoptimization_data());
     343       17304 :   if (data->length() == 0) return false;
     344       17304 :   if (data->SharedFunctionInfo() == sfi) return true;
     345             :   FixedArray const literals = data->LiteralArray();
     346             :   int const inlined_count = data->InlinedFunctionCount()->value();
     347       17181 :   for (int i = 0; i < inlined_count; ++i) {
     348         129 :     if (SharedFunctionInfo::cast(literals->get(i)) == sfi) return true;
     349             :   }
     350             :   return false;
     351             : }
     352             : 
     353       12420 : Code::OptimizedCodeIterator::OptimizedCodeIterator(Isolate* isolate) {
     354       12420 :   isolate_ = isolate;
     355             :   Object list = isolate->heap()->native_contexts_list();
     356       12420 :   next_context_ = list->IsUndefined(isolate_) ? Context() : Context::cast(list);
     357       12420 : }
     358             : 
     359       29724 : Code Code::OptimizedCodeIterator::Next() {
     360       30515 :   do {
     361             :     Object next;
     362       42935 :     if (!current_code_.is_null()) {
     363             :       // Get next code in the linked list.
     364             :       next = current_code_->next_code_link();
     365       25631 :     } else if (!next_context_.is_null()) {
     366             :       // Linked list of code exhausted. Get list of next context.
     367       13211 :       next = next_context_->OptimizedCodeListHead();
     368       13211 :       Object next_context = next_context_->next_context_link();
     369       13211 :       next_context_ = next_context->IsUndefined(isolate_)
     370             :                           ? Context()
     371       13211 :                           : Context::cast(next_context);
     372             :     } else {
     373             :       // Exhausted contexts.
     374       12420 :       return Code();
     375             :     }
     376       61030 :     current_code_ = next->IsUndefined(isolate_) ? Code() : Code::cast(next);
     377             :   } while (current_code_.is_null());
     378             :   DCHECK_EQ(Code::OPTIMIZED_FUNCTION, current_code_->kind());
     379       17304 :   return current_code_;
     380             : }
     381             : 
     382      463745 : Handle<DeoptimizationData> DeoptimizationData::New(Isolate* isolate,
     383             :                                                    int deopt_entry_count,
     384             :                                                    AllocationType allocation) {
     385             :   return Handle<DeoptimizationData>::cast(isolate->factory()->NewFixedArray(
     386      463745 :       LengthFor(deopt_entry_count), allocation));
     387             : }
     388             : 
     389     1442670 : Handle<DeoptimizationData> DeoptimizationData::Empty(Isolate* isolate) {
     390             :   return Handle<DeoptimizationData>::cast(
     391     1442670 :       isolate->factory()->empty_fixed_array());
     392             : }
     393             : 
     394         104 : SharedFunctionInfo DeoptimizationData::GetInlinedFunction(int index) {
     395         104 :   if (index == -1) {
     396             :     return SharedFunctionInfo::cast(SharedFunctionInfo());
     397             :   } else {
     398             :     return SharedFunctionInfo::cast(LiteralArray()->get(index));
     399             :   }
     400             : }
     401             : 
     402             : #ifdef ENABLE_DISASSEMBLER
     403             : 
     404             : const char* Code::GetName(Isolate* isolate) const {
     405             :   if (kind() == BYTECODE_HANDLER) {
     406             :     return isolate->interpreter()->LookupNameOfBytecodeHandler(*this);
     407             :   } else {
     408             :     // There are some handlers and ICs that we can also find names for with
     409             :     // Builtins::Lookup.
     410             :     return isolate->builtins()->Lookup(raw_instruction_start());
     411             :   }
     412             : }
     413             : 
     414             : namespace {
     415             : void print_pc(std::ostream& os, int pc) {
     416             :   if (pc == -1) {
     417             :     os << "NA";
     418             :   } else {
     419             :     os << std::hex << pc << std::dec;
     420             :   }
     421             : }
     422             : }  // anonymous namespace
     423             : 
     424             : void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) {  // NOLINT
     425             :   if (length() == 0) {
     426             :     os << "Deoptimization Input Data invalidated by lazy deoptimization\n";
     427             :     return;
     428             :   }
     429             : 
     430             :   disasm::NameConverter converter;
     431             :   int const inlined_function_count = InlinedFunctionCount()->value();
     432             :   os << "Inlined functions (count = " << inlined_function_count << ")\n";
     433             :   for (int id = 0; id < inlined_function_count; ++id) {
     434             :     Object info = LiteralArray()->get(id);
     435             :     os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
     436             :   }
     437             :   os << "\n";
     438             :   int deopt_count = DeoptCount();
     439             :   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
     440             :   if (0 != deopt_count) {
     441             :     os << " index  bytecode-offset    pc";
     442             :     if (FLAG_print_code_verbose) os << "  commands";
     443             :     os << "\n";
     444             :   }
     445             :   for (int i = 0; i < deopt_count; i++) {
     446             :     os << std::setw(6) << i << "  " << std::setw(15)
     447             :        << BytecodeOffset(i).ToInt() << "  " << std::setw(4);
     448             :     print_pc(os, Pc(i)->value());
     449             :     os << std::setw(2);
     450             : 
     451             :     if (!FLAG_print_code_verbose) {
     452             :       os << "\n";
     453             :       continue;
     454             :     }
     455             : 
     456             :     // Print details of the frame translation.
     457             :     int translation_index = TranslationIndex(i)->value();
     458             :     TranslationIterator iterator(TranslationByteArray(), translation_index);
     459             :     Translation::Opcode opcode =
     460             :         static_cast<Translation::Opcode>(iterator.Next());
     461             :     DCHECK(Translation::BEGIN == opcode);
     462             :     int frame_count = iterator.Next();
     463             :     int jsframe_count = iterator.Next();
     464             :     int update_feedback_count = iterator.Next();
     465             :     os << "  " << Translation::StringFor(opcode)
     466             :        << " {frame count=" << frame_count
     467             :        << ", js frame count=" << jsframe_count
     468             :        << ", update_feedback_count=" << update_feedback_count << "}\n";
     469             : 
     470             :     while (iterator.HasNext() &&
     471             :            Translation::BEGIN !=
     472             :                (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
     473             :       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
     474             : 
     475             :       switch (opcode) {
     476             :         case Translation::BEGIN:
     477             :           UNREACHABLE();
     478             :           break;
     479             : 
     480             :         case Translation::INTERPRETED_FRAME: {
     481             :           int bytecode_offset = iterator.Next();
     482             :           int shared_info_id = iterator.Next();
     483             :           unsigned height = iterator.Next();
     484             :           int return_value_offset = iterator.Next();
     485             :           int return_value_count = iterator.Next();
     486             :           Object shared_info = LiteralArray()->get(shared_info_id);
     487             :           os << "{bytecode_offset=" << bytecode_offset << ", function="
     488             :              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
     489             :              << ", height=" << height << ", retval=@" << return_value_offset
     490             :              << "(#" << return_value_count << ")}";
     491             :           break;
     492             :         }
     493             : 
     494             :         case Translation::CONSTRUCT_STUB_FRAME: {
     495             :           int bailout_id = iterator.Next();
     496             :           int shared_info_id = iterator.Next();
     497             :           Object shared_info = LiteralArray()->get(shared_info_id);
     498             :           unsigned height = iterator.Next();
     499             :           os << "{bailout_id=" << bailout_id << ", function="
     500             :              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
     501             :              << ", height=" << height << "}";
     502             :           break;
     503             :         }
     504             : 
     505             :         case Translation::BUILTIN_CONTINUATION_FRAME:
     506             :         case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
     507             :         case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
     508             :           int bailout_id = iterator.Next();
     509             :           int shared_info_id = iterator.Next();
     510             :           Object shared_info = LiteralArray()->get(shared_info_id);
     511             :           unsigned height = iterator.Next();
     512             :           os << "{bailout_id=" << bailout_id << ", function="
     513             :              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
     514             :              << ", height=" << height << "}";
     515             :           break;
     516             :         }
     517             : 
     518             :         case Translation::ARGUMENTS_ADAPTOR_FRAME: {
     519             :           int shared_info_id = iterator.Next();
     520             :           Object shared_info = LiteralArray()->get(shared_info_id);
     521             :           unsigned height = iterator.Next();
     522             :           os << "{function="
     523             :              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
     524             :              << ", height=" << height << "}";
     525             :           break;
     526             :         }
     527             : 
     528             :         case Translation::REGISTER: {
     529             :           int reg_code = iterator.Next();
     530             :           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
     531             :           break;
     532             :         }
     533             : 
     534             :         case Translation::INT32_REGISTER: {
     535             :           int reg_code = iterator.Next();
     536             :           os << "{input=" << converter.NameOfCPURegister(reg_code)
     537             :              << " (int32)}";
     538             :           break;
     539             :         }
     540             : 
     541             :         case Translation::INT64_REGISTER: {
     542             :           int reg_code = iterator.Next();
     543             :           os << "{input=" << converter.NameOfCPURegister(reg_code)
     544             :              << " (int64)}";
     545             :           break;
     546             :         }
     547             : 
     548             :         case Translation::UINT32_REGISTER: {
     549             :           int reg_code = iterator.Next();
     550             :           os << "{input=" << converter.NameOfCPURegister(reg_code)
     551             :              << " (uint32)}";
     552             :           break;
     553             :         }
     554             : 
     555             :         case Translation::BOOL_REGISTER: {
     556             :           int reg_code = iterator.Next();
     557             :           os << "{input=" << converter.NameOfCPURegister(reg_code)
     558             :              << " (bool)}";
     559             :           break;
     560             :         }
     561             : 
     562             :         case Translation::FLOAT_REGISTER: {
     563             :           int reg_code = iterator.Next();
     564             :           os << "{input=" << FloatRegister::from_code(reg_code) << "}";
     565             :           break;
     566             :         }
     567             : 
     568             :         case Translation::DOUBLE_REGISTER: {
     569             :           int reg_code = iterator.Next();
     570             :           os << "{input=" << DoubleRegister::from_code(reg_code) << "}";
     571             :           break;
     572             :         }
     573             : 
     574             :         case Translation::STACK_SLOT: {
     575             :           int input_slot_index = iterator.Next();
     576             :           os << "{input=" << input_slot_index << "}";
     577             :           break;
     578             :         }
     579             : 
     580             :         case Translation::INT32_STACK_SLOT: {
     581             :           int input_slot_index = iterator.Next();
     582             :           os << "{input=" << input_slot_index << " (int32)}";
     583             :           break;
     584             :         }
     585             : 
     586             :         case Translation::INT64_STACK_SLOT: {
     587             :           int input_slot_index = iterator.Next();
     588             :           os << "{input=" << input_slot_index << " (int64)}";
     589             :           break;
     590             :         }
     591             : 
     592             :         case Translation::UINT32_STACK_SLOT: {
     593             :           int input_slot_index = iterator.Next();
     594             :           os << "{input=" << input_slot_index << " (uint32)}";
     595             :           break;
     596             :         }
     597             : 
     598             :         case Translation::BOOL_STACK_SLOT: {
     599             :           int input_slot_index = iterator.Next();
     600             :           os << "{input=" << input_slot_index << " (bool)}";
     601             :           break;
     602             :         }
     603             : 
     604             :         case Translation::FLOAT_STACK_SLOT:
     605             :         case Translation::DOUBLE_STACK_SLOT: {
     606             :           int input_slot_index = iterator.Next();
     607             :           os << "{input=" << input_slot_index << "}";
     608             :           break;
     609             :         }
     610             : 
     611             :         case Translation::LITERAL: {
     612             :           int literal_index = iterator.Next();
     613             :           Object literal_value = LiteralArray()->get(literal_index);
     614             :           os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
     615             :              << ")}";
     616             :           break;
     617             :         }
     618             : 
     619             :         case Translation::DUPLICATED_OBJECT: {
     620             :           int object_index = iterator.Next();
     621             :           os << "{object_index=" << object_index << "}";
     622             :           break;
     623             :         }
     624             : 
     625             :         case Translation::ARGUMENTS_ELEMENTS:
     626             :         case Translation::ARGUMENTS_LENGTH: {
     627             :           CreateArgumentsType arguments_type =
     628             :               static_cast<CreateArgumentsType>(iterator.Next());
     629             :           os << "{arguments_type=" << arguments_type << "}";
     630             :           break;
     631             :         }
     632             : 
     633             :         case Translation::CAPTURED_OBJECT: {
     634             :           int args_length = iterator.Next();
     635             :           os << "{length=" << args_length << "}";
     636             :           break;
     637             :         }
     638             : 
     639             :         case Translation::UPDATE_FEEDBACK: {
     640             :           int literal_index = iterator.Next();
     641             :           FeedbackSlot slot(iterator.Next());
     642             :           os << "{feedback={vector_index=" << literal_index << ", slot=" << slot
     643             :              << "}}";
     644             :           break;
     645             :         }
     646             :       }
     647             :       os << "\n";
     648             :     }
     649             :   }
     650             : }
     651             : 
     652             : namespace {
     653             : 
     654             : inline void DisassembleCodeRange(Isolate* isolate, std::ostream& os, Code code,
     655             :                                  Address begin, size_t size,
     656             :                                  Address current_pc) {
     657             :   Address end = begin + size;
     658             :   // TODO(mstarzinger): Refactor CodeReference to avoid the
     659             :   // unhandlified->handlified transition.
     660             :   AllowHandleAllocation allow_handles;
     661             :   DisallowHeapAllocation no_gc;
     662             :   HandleScope handle_scope(isolate);
     663             :   Disassembler::Decode(isolate, &os, reinterpret_cast<byte*>(begin),
     664             :                        reinterpret_cast<byte*>(end),
     665             :                        CodeReference(handle(code, isolate)), current_pc);
     666             : }
     667             : 
     668             : }  // namespace
     669             : 
     670             : void Code::Disassemble(const char* name, std::ostream& os, Address current_pc) {
     671             :   Isolate* isolate = GetIsolate();
     672             :   os << "kind = " << Kind2String(kind()) << "\n";
     673             :   if (name == nullptr) {
     674             :     name = GetName(isolate);
     675             :   }
     676             :   if ((name != nullptr) && (name[0] != '\0')) {
     677             :     os << "name = " << name << "\n";
     678             :   }
     679             :   if (kind() == OPTIMIZED_FUNCTION) {
     680             :     os << "stack_slots = " << stack_slots() << "\n";
     681             :   }
     682             :   os << "compiler = " << (is_turbofanned() ? "turbofan" : "unknown") << "\n";
     683             :   os << "address = " << static_cast<const void*>(this) << "\n\n";
     684             : 
     685             :   if (is_off_heap_trampoline()) {
     686             :     int trampoline_size = raw_instruction_size();
     687             :     os << "Trampoline (size = " << trampoline_size << ")\n";
     688             :     DisassembleCodeRange(isolate, os, *this, raw_instruction_start(),
     689             :                          trampoline_size, current_pc);
     690             :     os << "\n";
     691             :   }
     692             : 
     693             :   {
     694             :     // Stop before reaching any embedded tables
     695             :     int code_size = ExecutableInstructionSize();
     696             :     os << "Instructions (size = " << code_size << ")\n";
     697             :     DisassembleCodeRange(isolate, os, *this, InstructionStart(), code_size,
     698             :                          current_pc);
     699             : 
     700             :     if (int pool_size = constant_pool_size()) {
     701             :       DCHECK_EQ(pool_size & kPointerAlignmentMask, 0);
     702             :       os << "\nConstant Pool (size = " << pool_size << ")\n";
     703             :       Vector<char> buf = Vector<char>::New(50);
     704             :       intptr_t* ptr = reinterpret_cast<intptr_t*>(InstructionStart() +
     705             :                                                   constant_pool_offset());
     706             :       for (int i = 0; i < pool_size; i += kSystemPointerSize, ptr++) {
     707             :         SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
     708             :         os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
     709             :       }
     710             :     }
     711             :   }
     712             :   os << "\n";
     713             : 
     714             :   {
     715             :     SourcePositionTableIterator it(
     716             :         SourcePositionTableIfCollected(),
     717             :         SourcePositionTableIterator::kJavaScriptOnly);
     718             :     if (!it.done()) {
     719             :       os << "Source positions:\n pc offset  position\n";
     720             :       for (; !it.done(); it.Advance()) {
     721             :         os << std::setw(10) << std::hex << it.code_offset() << std::dec
     722             :            << std::setw(10) << it.source_position().ScriptOffset()
     723             :            << (it.is_statement() ? "  statement" : "") << "\n";
     724             :       }
     725             :       os << "\n";
     726             :     }
     727             :   }
     728             : 
     729             :   {
     730             :     SourcePositionTableIterator it(SourcePositionTableIfCollected(),
     731             :                                    SourcePositionTableIterator::kExternalOnly);
     732             :     if (!it.done()) {
     733             :       os << "External Source positions:\n pc offset  fileid  line\n";
     734             :       for (; !it.done(); it.Advance()) {
     735             :         DCHECK(it.source_position().IsExternal());
     736             :         os << std::setw(10) << std::hex << it.code_offset() << std::dec
     737             :            << std::setw(10) << it.source_position().ExternalFileId()
     738             :            << std::setw(10) << it.source_position().ExternalLine() << "\n";
     739             :       }
     740             :       os << "\n";
     741             :     }
     742             :   }
     743             : 
     744             :   if (kind() == OPTIMIZED_FUNCTION) {
     745             :     DeoptimizationData data =
     746             :         DeoptimizationData::cast(this->deoptimization_data());
     747             :     data->DeoptimizationDataPrint(os);
     748             :   }
     749             :   os << "\n";
     750             : 
     751             :   if (has_safepoint_info()) {
     752             :     SafepointTable table(*this);
     753             :     os << "Safepoints (size = " << table.size() << ")\n";
     754             :     for (unsigned i = 0; i < table.length(); i++) {
     755             :       unsigned pc_offset = table.GetPcOffset(i);
     756             :       os << reinterpret_cast<const void*>(InstructionStart() + pc_offset)
     757             :          << "  ";
     758             :       os << std::setw(6) << std::hex << pc_offset << "  " << std::setw(4);
     759             :       int trampoline_pc = table.GetTrampolinePcOffset(i);
     760             :       print_pc(os, trampoline_pc);
     761             :       os << std::dec << "  ";
     762             :       table.PrintEntry(i, os);
     763             :       os << " (sp -> fp)  ";
     764             :       SafepointEntry entry = table.GetEntry(i);
     765             :       if (entry.has_deoptimization_index()) {
     766             :         os << std::setw(6) << entry.deoptimization_index();
     767             :       } else {
     768             :         os << "<none>";
     769             :       }
     770             :       os << "\n";
     771             :     }
     772             :     os << "\n";
     773             :   }
     774             : 
     775             :   if (has_handler_table()) {
     776             :     HandlerTable table(*this);
     777             :     os << "Handler Table (size = " << table.NumberOfReturnEntries() << ")\n";
     778             :     if (kind() == OPTIMIZED_FUNCTION) {
     779             :       table.HandlerTableReturnPrint(os);
     780             :     }
     781             :     os << "\n";
     782             :   }
     783             : 
     784             :   os << "RelocInfo (size = " << relocation_size() << ")\n";
     785             :   for (RelocIterator it(*this); !it.done(); it.next()) {
     786             :     it.rinfo()->Print(isolate, os);
     787             :   }
     788             :   os << "\n";
     789             : 
     790             :   if (has_unwinding_info()) {
     791             :     os << "UnwindingInfo (size = " << unwinding_info_size() << ")\n";
     792             :     EhFrameDisassembler eh_frame_disassembler(
     793             :         reinterpret_cast<byte*>(unwinding_info_start()),
     794             :         reinterpret_cast<byte*>(unwinding_info_end()));
     795             :     eh_frame_disassembler.DisassembleToStream(os);
     796             :     os << "\n";
     797             :   }
     798             : 
     799             :   if (has_code_comments()) {
     800             :     PrintCodeCommentsSection(os, code_comments(), code_comments_size());
     801             :   }
     802             : }
     803             : #endif  // ENABLE_DISASSEMBLER
     804             : 
     805           0 : void BytecodeArray::Disassemble(std::ostream& os) {
     806             :   DisallowHeapAllocation no_gc;
     807             : 
     808           0 :   os << "Parameter count " << parameter_count() << "\n";
     809           0 :   os << "Register count " << register_count() << "\n";
     810           0 :   os << "Frame size " << frame_size() << "\n";
     811             : 
     812             :   Address base_address = GetFirstBytecodeAddress();
     813             :   SourcePositionTableIterator source_positions(
     814           0 :       SourcePositionTableIfCollected());
     815             : 
     816             :   // Storage for backing the handle passed to the iterator. This handle won't be
     817             :   // updated by the gc, but that's ok because we've disallowed GCs anyway.
     818           0 :   BytecodeArray handle_storage = *this;
     819             :   Handle<BytecodeArray> handle(reinterpret_cast<Address*>(&handle_storage));
     820           0 :   interpreter::BytecodeArrayIterator iterator(handle);
     821           0 :   while (!iterator.done()) {
     822           0 :     if (!source_positions.done() &&
     823             :         iterator.current_offset() == source_positions.code_offset()) {
     824           0 :       os << std::setw(5) << source_positions.source_position().ScriptOffset();
     825           0 :       os << (source_positions.is_statement() ? " S> " : " E> ");
     826           0 :       source_positions.Advance();
     827             :     } else {
     828           0 :       os << "         ";
     829             :     }
     830           0 :     Address current_address = base_address + iterator.current_offset();
     831           0 :     os << reinterpret_cast<const void*>(current_address) << " @ "
     832           0 :        << std::setw(4) << iterator.current_offset() << " : ";
     833             :     interpreter::BytecodeDecoder::Decode(
     834           0 :         os, reinterpret_cast<byte*>(current_address), parameter_count());
     835           0 :     if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
     836           0 :       Address jump_target = base_address + iterator.GetJumpTargetOffset();
     837           0 :       os << " (" << reinterpret_cast<void*>(jump_target) << " @ "
     838           0 :          << iterator.GetJumpTargetOffset() << ")";
     839             :     }
     840           0 :     if (interpreter::Bytecodes::IsSwitch(iterator.current_bytecode())) {
     841           0 :       os << " {";
     842             :       bool first_entry = true;
     843           0 :       for (const auto& entry : iterator.GetJumpTableTargetOffsets()) {
     844           0 :         if (first_entry) {
     845             :           first_entry = false;
     846             :         } else {
     847           0 :           os << ",";
     848             :         }
     849           0 :         os << " " << entry.case_value << ": @" << entry.target_offset;
     850             :       }
     851           0 :       os << " }";
     852             :     }
     853             :     os << std::endl;
     854           0 :     iterator.Advance();
     855             :   }
     856             : 
     857           0 :   os << "Constant pool (size = " << constant_pool()->length() << ")\n";
     858             : #ifdef OBJECT_PRINT
     859             :   if (constant_pool()->length() > 0) {
     860             :     constant_pool()->Print();
     861             :   }
     862             : #endif
     863             : 
     864           0 :   os << "Handler Table (size = " << handler_table()->length() << ")\n";
     865             : #ifdef ENABLE_DISASSEMBLER
     866             :   if (handler_table()->length() > 0) {
     867             :     HandlerTable table(*this);
     868             :     table.HandlerTableRangePrint(os);
     869             :   }
     870             : #endif
     871           0 : }
     872             : 
     873       10601 : void BytecodeArray::CopyBytecodesTo(BytecodeArray to) {
     874       10601 :   BytecodeArray from = *this;
     875             :   DCHECK_EQ(from->length(), to->length());
     876       31803 :   CopyBytes(reinterpret_cast<byte*>(to->GetFirstBytecodeAddress()),
     877             :             reinterpret_cast<byte*>(from->GetFirstBytecodeAddress()),
     878             :             from->length());
     879       10601 : }
     880             : 
     881     1521772 : void BytecodeArray::MakeOlder() {
     882             :   // BytecodeArray is aged in concurrent marker.
     883             :   // The word must be completely within the byte code array.
     884     1521772 :   Address age_addr = address() + kBytecodeAgeOffset;
     885             :   DCHECK_LE(RoundDown(age_addr, kSystemPointerSize) + kSystemPointerSize,
     886             :             address() + Size());
     887             :   Age age = bytecode_age();
     888     1521772 :   if (age < kLastBytecodeAge) {
     889     1196364 :     base::AsAtomic8::Release_CompareAndSwap(reinterpret_cast<byte*>(age_addr),
     890             :                                             age, age + 1);
     891             :   }
     892             : 
     893             :   DCHECK_GE(bytecode_age(), kFirstBytecodeAge);
     894             :   DCHECK_LE(bytecode_age(), kLastBytecodeAge);
     895     1521772 : }
     896             : 
     897     2344242 : bool BytecodeArray::IsOld() const {
     898     2344242 :   return bytecode_age() >= kIsOldBytecodeAge;
     899             : }
     900             : 
     901      587170 : DependentCode DependentCode::GetDependentCode(Handle<HeapObject> object) {
     902      587170 :   if (object->IsMap()) {
     903             :     return Handle<Map>::cast(object)->dependent_code();
     904      214606 :   } else if (object->IsPropertyCell()) {
     905             :     return Handle<PropertyCell>::cast(object)->dependent_code();
     906       10378 :   } else if (object->IsAllocationSite()) {
     907             :     return Handle<AllocationSite>::cast(object)->dependent_code();
     908             :   }
     909           0 :   UNREACHABLE();
     910             : }
     911             : 
     912      136731 : void DependentCode::SetDependentCode(Handle<HeapObject> object,
     913             :                                      Handle<DependentCode> dep) {
     914      136731 :   if (object->IsMap()) {
     915       80442 :     Handle<Map>::cast(object)->set_dependent_code(*dep);
     916       56289 :   } else if (object->IsPropertyCell()) {
     917       46547 :     Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
     918        9742 :   } else if (object->IsAllocationSite()) {
     919        9742 :     Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
     920             :   } else {
     921           0 :     UNREACHABLE();
     922             :   }
     923      136731 : }
     924             : 
     925      587170 : void DependentCode::InstallDependency(Isolate* isolate,
     926             :                                       const MaybeObjectHandle& code,
     927             :                                       Handle<HeapObject> object,
     928             :                                       DependencyGroup group) {
     929             :   Handle<DependentCode> old_deps(DependentCode::GetDependentCode(object),
     930      587170 :                                  isolate);
     931             :   Handle<DependentCode> new_deps =
     932      587170 :       InsertWeakCode(isolate, old_deps, group, code);
     933             :   // Update the list head if necessary.
     934      587170 :   if (!new_deps.is_identical_to(old_deps))
     935      136731 :     DependentCode::SetDependentCode(object, new_deps);
     936      587170 : }
     937             : 
     938      746932 : Handle<DependentCode> DependentCode::InsertWeakCode(
     939             :     Isolate* isolate, Handle<DependentCode> entries, DependencyGroup group,
     940             :     const MaybeObjectHandle& code) {
     941     1395986 :   if (entries->length() == 0 || entries->group() > group) {
     942             :     // There is no such group.
     943      107271 :     return DependentCode::New(isolate, group, code, entries);
     944             :   }
     945      639661 :   if (entries->group() < group) {
     946             :     // The group comes later in the list.
     947             :     Handle<DependentCode> old_next(entries->next_link(), isolate);
     948             :     Handle<DependentCode> new_next =
     949      159762 :         InsertWeakCode(isolate, old_next, group, code);
     950      159762 :     if (!old_next.is_identical_to(new_next)) {
     951       61044 :       entries->set_next_link(*new_next);
     952             :     }
     953      159762 :     return entries;
     954             :   }
     955             :   DCHECK_EQ(group, entries->group());
     956             :   int count = entries->count();
     957             :   // Check for existing entry to avoid duplicates.
     958   118487829 :   for (int i = 0; i < count; i++) {
     959   118561618 :     if (entries->object_at(i) == *code) return entries;
     960             :   }
     961      406110 :   if (entries->length() < kCodesStartIndex + count + 1) {
     962       61724 :     entries = EnsureSpace(isolate, entries);
     963             :     // Count could have changed, reload it.
     964             :     count = entries->count();
     965             :   }
     966      609165 :   entries->set_object_at(count, *code);
     967      406110 :   entries->set_count(count + 1);
     968      203055 :   return entries;
     969             : }
     970             : 
     971      107271 : Handle<DependentCode> DependentCode::New(Isolate* isolate,
     972             :                                          DependencyGroup group,
     973             :                                          const MaybeObjectHandle& object,
     974             :                                          Handle<DependentCode> next) {
     975             :   Handle<DependentCode> result =
     976             :       Handle<DependentCode>::cast(isolate->factory()->NewWeakFixedArray(
     977      107271 :           kCodesStartIndex + 1, AllocationType::kOld));
     978      214542 :   result->set_next_link(*next);
     979      321813 :   result->set_flags(GroupField::encode(group) | CountField::encode(1));
     980      321813 :   result->set_object_at(0, *object);
     981      107271 :   return result;
     982             : }
     983             : 
     984       61724 : Handle<DependentCode> DependentCode::EnsureSpace(
     985             :     Isolate* isolate, Handle<DependentCode> entries) {
     986       61724 :   if (entries->Compact()) return entries;
     987       59982 :   int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
     988       59982 :   int grow_by = capacity - entries->length();
     989             :   return Handle<DependentCode>::cast(
     990             :       isolate->factory()->CopyWeakFixedArrayAndGrow(entries, grow_by,
     991       59982 :                                                     AllocationType::kOld));
     992             : }
     993             : 
     994       61724 : bool DependentCode::Compact() {
     995             :   int old_count = count();
     996             :   int new_count = 0;
     997     1768062 :   for (int i = 0; i < old_count; i++) {
     998             :     MaybeObject obj = object_at(i);
     999      853169 :     if (!obj->IsCleared()) {
    1000      841855 :       if (i != new_count) {
    1001        1800 :         copy(i, new_count);
    1002             :       }
    1003      841855 :       new_count++;
    1004             :     }
    1005             :   }
    1006       61724 :   set_count(new_count);
    1007       84352 :   for (int i = new_count; i < old_count; i++) {
    1008       11314 :     clear_at(i);
    1009             :   }
    1010       61724 :   return new_count < old_count;
    1011             : }
    1012             : 
    1013    20917746 : bool DependentCode::MarkCodeForDeoptimization(
    1014             :     Isolate* isolate, DependentCode::DependencyGroup group) {
    1015    20920844 :   if (this->length() == 0 || this->group() > group) {
    1016             :     // There is no such group.
    1017             :     return false;
    1018             :   }
    1019        2625 :   if (this->group() < group) {
    1020             :     // The group comes later in the list.
    1021         384 :     return next_link()->MarkCodeForDeoptimization(isolate, group);
    1022             :   }
    1023             :   DCHECK_EQ(group, this->group());
    1024             :   DisallowHeapAllocation no_allocation_scope;
    1025             :   // Mark all the code that needs to be deoptimized.
    1026             :   bool marked = false;
    1027             :   int count = this->count();
    1028        8663 :   for (int i = 0; i < count; i++) {
    1029             :     MaybeObject obj = object_at(i);
    1030        3216 :     if (obj->IsCleared()) continue;
    1031        3206 :     Code code = Code::cast(obj->GetHeapObjectAssumeWeak());
    1032        3206 :     if (!code->marked_for_deoptimization()) {
    1033        2226 :       code->SetMarkedForDeoptimization(DependencyGroupName(group));
    1034             :       marked = true;
    1035             :     }
    1036             :   }
    1037        8663 :   for (int i = 0; i < count; i++) {
    1038        3211 :     clear_at(i);
    1039             :   }
    1040        2241 :   set_count(0);
    1041        2241 :   return marked;
    1042             : }
    1043             : 
    1044    20917314 : void DependentCode::DeoptimizeDependentCodeGroup(
    1045             :     Isolate* isolate, DependentCode::DependencyGroup group) {
    1046             :   DisallowHeapAllocation no_allocation_scope;
    1047    20917314 :   bool marked = MarkCodeForDeoptimization(isolate, group);
    1048    20917316 :   if (marked) {
    1049             :     DCHECK(AllowCodeDependencyChange::IsAllowed());
    1050        1704 :     Deoptimizer::DeoptimizeMarkedCode(isolate);
    1051             :   }
    1052    20917316 : }
    1053             : 
    1054        2305 : void Code::SetMarkedForDeoptimization(const char* reason) {
    1055        2305 :   set_marked_for_deoptimization(true);
    1056        2305 :   if (FLAG_trace_deopt &&
    1057             :       (deoptimization_data() != GetReadOnlyRoots().empty_fixed_array())) {
    1058             :     DeoptimizationData deopt_data =
    1059             :         DeoptimizationData::cast(deoptimization_data());
    1060           0 :     CodeTracer::Scope scope(GetIsolate()->GetCodeTracer());
    1061             :     PrintF(scope.file(),
    1062             :            "[marking dependent code " V8PRIxPTR_FMT
    1063             :            " (opt #%d) for deoptimization, reason: %s]\n",
    1064           0 :            ptr(), deopt_data->OptimizationId()->value(), reason);
    1065             :   }
    1066        2305 : }
    1067             : 
    1068        2226 : const char* DependentCode::DependencyGroupName(DependencyGroup group) {
    1069        2226 :   switch (group) {
    1070             :     case kTransitionGroup:
    1071             :       return "transition";
    1072             :     case kPrototypeCheckGroup:
    1073         845 :       return "prototype-check";
    1074             :     case kPropertyCellChangedGroup:
    1075         835 :       return "property-cell-changed";
    1076             :     case kFieldOwnerGroup:
    1077         396 :       return "field-owner";
    1078             :     case kInitialMapChangedGroup:
    1079         129 :       return "initial-map-changed";
    1080             :     case kAllocationSiteTenuringChangedGroup:
    1081           1 :       return "allocation-site-tenuring-changed";
    1082             :     case kAllocationSiteTransitionChangedGroup:
    1083           5 :       return "allocation-site-transition-changed";
    1084             :   }
    1085           0 :   UNREACHABLE();
    1086             : }
    1087             : 
    1088             : }  // namespace internal
    1089      122036 : }  // namespace v8

Generated by: LCOV version 1.10