LCOV - code coverage report
Current view: top level - src/objects - code.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 256 306 83.7 %
Date: 2019-02-19 Functions: 45 53 84.9 %

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

Generated by: LCOV version 1.10