From 229d793602c8fe04a16ac2b25b989f082ce5cfc8 Mon Sep 17 00:00:00 2001 From: Vyacheslav Egorov Date: Fri, 14 Sep 2018 17:39:12 +0000 Subject: [PATCH] [vm/compiler] Support materializing unboxed variables when entering catch. Previously we tried to rely on the assumption that all variables would be boxed - so the machinery for setting correct catch-entry state only supported tagged values and constants. However this both leads to worse code and is not entirely correct assumption. This also: - renames various confusingly named classes: we move away from talking about "catch entry state" to "catch entry moves" - because we only record a subset of moves that needs to be performed and that does not describe the whole state; - refactors a bunch of associated code to be more readable and maintainable; - adds documentation about catch implementation in optimized code to runtime/docs/compiler; Fixes https://github.com/flutter/flutter/issues/21685. Change-Id: I03ae361a1bb7710acbd9f661ae014e663a163c59 Reviewed-on: https://dart-review.googlesource.com/74860 Commit-Queue: Vyacheslav Egorov Reviewed-by: Martin Kustermann Reviewed-by: Alexander Markov --- runtime/docs/compiler/exceptions.md | 92 ++++++++ .../compiler/images/catch-block-entry-0.png | Bin 0 -> 34902 bytes .../compiler/images/catch-block-entry-1.png | Bin 0 -> 83540 bytes .../tests/vm/dart/catch_entry_state_test.dart | 53 +++++ runtime/tests/vm/vm.status | 3 + runtime/vm/clustered_snapshot.cc | 6 +- runtime/vm/code_descriptors.cc | 47 ++-- runtime/vm/code_descriptors.h | 44 +--- runtime/vm/compiler/aot/precompiler.cc | 2 +- runtime/vm/compiler/backend/flow_graph.cc | 20 -- runtime/vm/compiler/backend/flow_graph.h | 1 - .../compiler/backend/flow_graph_compiler.cc | 170 +++++++++----- .../vm/compiler/backend/flow_graph_compiler.h | 7 +- .../backend/flow_graph_compiler_arm.cc | 2 +- .../backend/flow_graph_compiler_arm64.cc | 2 +- .../backend/flow_graph_compiler_ia32.cc | 2 +- .../backend/flow_graph_compiler_x64.cc | 2 +- runtime/vm/compiler/backend/il.cc | 15 +- runtime/vm/compiler/backend/il_arm.cc | 2 +- runtime/vm/compiler/backend/il_arm64.cc | 2 +- runtime/vm/compiler/backend/il_x64.cc | 2 +- runtime/vm/compiler/jit/compiler.cc | 2 +- runtime/vm/deopt_instructions.cc | 92 ++++++-- runtime/vm/deopt_instructions.h | 13 +- runtime/vm/exceptions.cc | 220 ++++++++++++------ runtime/vm/exceptions.h | 193 ++++++++++++--- runtime/vm/heap/heap.cc | 2 +- runtime/vm/isolate.cc | 2 +- runtime/vm/isolate.h | 8 +- runtime/vm/object.cc | 4 +- runtime/vm/object.h | 6 +- runtime/vm/program_visitor.cc | 46 ++-- runtime/vm/program_visitor.h | 2 +- runtime/vm/raw_object.h | 2 +- 34 files changed, 721 insertions(+), 345 deletions(-) create mode 100644 runtime/docs/compiler/exceptions.md create mode 100644 runtime/docs/compiler/images/catch-block-entry-0.png create mode 100644 runtime/docs/compiler/images/catch-block-entry-1.png create mode 100644 runtime/tests/vm/dart/catch_entry_state_test.dart diff --git a/runtime/docs/compiler/exceptions.md b/runtime/docs/compiler/exceptions.md new file mode 100644 index 00000000000..222e5f8be64 --- /dev/null +++ b/runtime/docs/compiler/exceptions.md @@ -0,0 +1,92 @@ +# Exceptions Implementation + +This page describes how exceptions throwing and catching is implemented in the +VM. + +## Intermediate Language + +Dart VM's IL **does not** explicitly represent exceptional control flow in its +flow graph, there are **no** explicit exceptional edges connecting potentially +throwing instructions (e.g. calls) with corresponding catch blocks. Instead this +connection is defined at the block level: all exceptions that occur in any block +with the given `try_index` will be caught by `CatchBlockEntry` with the equal +`catch_try_index`. + +![Catch Block Entry](images/catch-block-entry-0.png) + +For optimized code this means that data flow associated with exceptional control +flow is also represented implicitly: due to the absence of explicit exceptional +edges the data flow can't be represented using explicit phi-functions. Instead +in optimized code each `CatchBlockEntry` is treated almost as if it was an +independent entry into the function: for each variable `v` `CatchBlockEntry` +will contain a `Parameter(...)` instruction restoring variable state at catch +entry from a fixed location on the stack. When an exception is thrown runtime +system takes care of populating these stack slots with right values - current +state of corresponding local variables. It's easy to see a parallel between +these `Parameter(...)` instructions and `Phi(...)` instructions that would be +used if exception control flow would be explicit. + +![Catch Block Entry](images/catch-block-entry-1.png) + +How does runtime system populate stack slots corresponding to these +`Parameter(...)` instructions? During compilation necessary information is +available in _deoptimization environment_ attached to the instruction. This +environment encodes the state of local variables in terms of SSA values i.e. if +we need to reconstruct unoptimized frame which SSA value should be stored into +the given local variable (see [Optimized +IL](compiler-pipeline-overview.md#optimized-il) for +an overview). However the way we use these information for exception handling is +slightly different in JIT and AOT modes. + +### AOT mode + +AOT mode does not support deoptimization and thus AOT compiler does not +associate any deoptimization metadata with generated code. Instead +deoptimization environments associated with instructions that can throw are +converted into `CatchEntryMoves` metadata during code generation and resulting +metadata is stored `RawCode::catch_entry_moves_maps_` in a compressed form. + +`CatchEntryMoves` is essentially a sequence of moves which runtime needs to +perform to create the state that catch entry expects. There are three types of +moves: + +* `*(FP + Dst) <- ObjectPool[PoolIndex]` - a move of a constant from an object +pool; +* `*(FP + Dst) <- *(FP + Src)` - a move of a tagged value; +* `*(FP + Dst) <- Box(*(FP + Src))` - a boxing operation for an untagged +value; + +When an exception is caught runtime decompresses the metadata associated with the +call site which has thrown an exception and uses it to prepare the state of the +stack for the catch block entry. See +`ExceptionHandlerFinder::{ReadCompressedCatchEntryMoves, ExecuteCatchEntryMoves}`. + +NOTE: See [this +design/motivation](https://docs.google.com/a/google.com/document/d/1_vX8VkvHVA1Om7jjONiWLA325k_JmSZuvVClet-x-xM/edit?usp=sharing) +document for `CatchEntryMoves` metadata + +### JIT mode + +JIT mode heavily relies on deoptimization and all call instructions have (lazy) +deoptimization environments associated with them. These environments are +converted to [deoptimization +instructions](deoptimization.md#in-optimized-code) +during code generation and stored on the `Code` object. + +When an exception is caught the runtime system converts deoptimization +environment associated with the call site that threw an exception into +`CatchEntryMoves` and then uses it to prepare the state of the stack for the +catch block entry. See `ExceptionHandlerFinder::{GetCatchEntryMovesFromDeopt, ExecuteCatchEntryMoves}`. + +Constructing `CatchEntryMoves` dynamically from deoptimization instructions +allows to avoid unnecessary duplication of the metadata and save memory: as +deoptimization environments contain all information necessary for constructing +correct stack state. + +IMPORTANT: There is a subtle difference between DBC and other architectures with +respect to catch block entry state. On normal architectures `Parameter(i)` at +catch entry would be associated with the same stack space that would be used to +store variable with index `i`. On DBC however at catch entry `Parameter(i)` +would be allocated to a separate scratch space at the very top of the register +space. See `FlowGraphAllocator::ProcessInitialDefinition` and +`FlowGraphCompiler::CatchEntryRegForVariable`. diff --git a/runtime/docs/compiler/images/catch-block-entry-0.png b/runtime/docs/compiler/images/catch-block-entry-0.png new file mode 100644 index 0000000000000000000000000000000000000000..b6013de5ed74d7921c07835d8d48220864393d05 GIT binary patch literal 34902 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ÎZf{ye8j(e$Dg@Y`b0Teh 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 literal 0 HcmV?d00001 diff --git a/runtime/docs/compiler/images/catch-block-entry-1.png b/runtime/docs/compiler/images/catch-block-entry-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c41adb439b7b6c205f54cf5e8c8be5b0b46824f2 GIT binary patch literal 83540 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 p?^iPush(code->ptr()->exception_handlers_); s->Push(code->ptr()->pc_descriptors_); #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) - s->Push(code->ptr()->catch_entry_.catch_entry_state_maps_); + s->Push(code->ptr()->catch_entry_.catch_entry_moves_maps_); #else s->Push(code->ptr()->catch_entry_.variables_); #endif @@ -1727,7 +1727,7 @@ class CodeSerializationCluster : public SerializationCluster { s->WriteRef(code->ptr()->exception_handlers_); s->WriteRef(code->ptr()->pc_descriptors_); #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) - s->WriteRef(code->ptr()->catch_entry_.catch_entry_state_maps_); + s->WriteRef(code->ptr()->catch_entry_.catch_entry_moves_maps_); #else s->WriteRef(code->ptr()->catch_entry_.variables_); #endif @@ -1810,7 +1810,7 @@ class CodeDeserializationCluster : public DeserializationCluster { code->ptr()->pc_descriptors_ = reinterpret_cast(d->ReadRef()); #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) - code->ptr()->catch_entry_.catch_entry_state_maps_ = + code->ptr()->catch_entry_.catch_entry_moves_maps_ = reinterpret_cast(d->ReadRef()); #else code->ptr()->catch_entry_.variables_ = diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc index da771141cd5..84d98825e35 100644 --- a/runtime/vm/code_descriptors.cc +++ b/runtime/vm/code_descriptors.cc @@ -112,18 +112,19 @@ RawExceptionHandlers* ExceptionHandlerList::FinalizeExceptionHandlers( return handlers.raw(); } -static uint8_t* zone_allocator(uint8_t* ptr, - intptr_t old_size, - intptr_t new_size) { +static uint8_t* ZoneAllocator(uint8_t* ptr, + intptr_t old_size, + intptr_t new_size) { Zone* zone = Thread::Current()->zone(); return zone->Realloc(ptr, old_size, new_size); } -class CatchEntryStateMapBuilder::TrieNode : public ZoneAllocated { +#if !defined(DART_PRECOMPILED_RUNTIME) +class CatchEntryMovesMapBuilder::TrieNode : public ZoneAllocated { public: - TrieNode() : pair_(), entry_state_offset_(-1) {} - TrieNode(CatchEntryStatePair pair, intptr_t index) - : pair_(pair), entry_state_offset_(index) {} + TrieNode() : move_(), entry_state_offset_(-1) {} + TrieNode(CatchEntryMove move, intptr_t index) + : move_(move), entry_state_offset_(index) {} intptr_t Offset() { return entry_state_offset_; } @@ -132,42 +133,36 @@ class CatchEntryStateMapBuilder::TrieNode : public ZoneAllocated { return node; } - TrieNode* Follow(CatchEntryStatePair next) { + TrieNode* Follow(CatchEntryMove next) { for (intptr_t i = 0; i < children_.length(); i++) { - if (children_[i]->pair_ == next) return children_[i]; + if (children_[i]->move_ == next) return children_[i]; } return NULL; } private: - CatchEntryStatePair pair_; + CatchEntryMove move_; const intptr_t entry_state_offset_; GrowableArray children_; }; -CatchEntryStateMapBuilder::CatchEntryStateMapBuilder() +CatchEntryMovesMapBuilder::CatchEntryMovesMapBuilder() : zone_(Thread::Current()->zone()), root_(new TrieNode()), current_pc_offset_(0), buffer_(NULL), - stream_(&buffer_, zone_allocator, 64) {} + stream_(&buffer_, ZoneAllocator, 64) {} -void CatchEntryStateMapBuilder::AppendMove(intptr_t src_slot, - intptr_t dest_slot) { - moves_.Add(CatchEntryStatePair::FromMove(src_slot, dest_slot)); +void CatchEntryMovesMapBuilder::Append(const CatchEntryMove& move) { + moves_.Add(move); } -void CatchEntryStateMapBuilder::AppendConstant(intptr_t pool_id, - intptr_t dest_slot) { - moves_.Add(CatchEntryStatePair::FromConstant(pool_id, dest_slot)); -} - -void CatchEntryStateMapBuilder::NewMapping(intptr_t pc_offset) { +void CatchEntryMovesMapBuilder::NewMapping(intptr_t pc_offset) { moves_.Clear(); current_pc_offset_ = pc_offset; } -void CatchEntryStateMapBuilder::EndMapping() { +void CatchEntryMovesMapBuilder::EndMapping() { intptr_t suffix_length = 0; TrieNode* suffix = root_; // Find the largest common suffix, get the last node of the path. @@ -189,8 +184,7 @@ void CatchEntryStateMapBuilder::EndMapping() { // Write the unshared part, adding it to the trie. TrieNode* node = suffix; for (intptr_t i = length - 1; i >= 0; i--) { - Writer::Write(&stream_, moves_[i].src); - Writer::Write(&stream_, moves_[i].dest); + moves_[i].WriteTo(&stream_); TrieNode* child = new (zone_) TrieNode(moves_[i], current_offset); node->Insert(child); @@ -198,7 +192,7 @@ void CatchEntryStateMapBuilder::EndMapping() { } } -RawTypedData* CatchEntryStateMapBuilder::FinalizeCatchEntryStateMap() { +RawTypedData* CatchEntryMovesMapBuilder::FinalizeCatchEntryMovesMap() { TypedData& td = TypedData::Handle(TypedData::New( kTypedDataInt8ArrayCid, stream_.bytes_written(), Heap::kOld)); NoSafepointScope no_safepoint; @@ -209,6 +203,7 @@ RawTypedData* CatchEntryStateMapBuilder::FinalizeCatchEntryStateMap() { } return td.raw(); } +#endif // !defined(DART_PRECOMPILED_RUNTIME) const TokenPosition CodeSourceMapBuilder::kInitialPosition = TokenPosition(TokenPosition::kDartCodeProloguePos); @@ -230,7 +225,7 @@ CodeSourceMapBuilder::CodeSourceMapBuilder( inlined_functions_( GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld))), buffer_(NULL), - stream_(&buffer_, zone_allocator, 64), + stream_(&buffer_, ZoneAllocator, 64), stack_traces_only_(stack_traces_only) { buffered_inline_id_stack_.Add(0); buffered_token_pos_stack_.Add(kInitialPosition); diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h index 6c0daab9c3e..dfec824eaee 100644 --- a/runtime/vm/code_descriptors.h +++ b/runtime/vm/code_descriptors.h @@ -144,43 +144,16 @@ class ExceptionHandlerList : public ZoneAllocated { DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerList); }; -// An encoded move from stack/constant to stack performed -struct CatchEntryStatePair { - enum { kCatchEntryStateIsMove = 1, kCatchEntryStateDestShift = 1 }; - - intptr_t src, dest; - - static CatchEntryStatePair FromConstant(intptr_t pool_id, - intptr_t dest_slot) { - CatchEntryStatePair pair; - pair.src = pool_id; - pair.dest = (dest_slot << kCatchEntryStateDestShift); - return pair; - } - - static CatchEntryStatePair FromMove(intptr_t src_slot, intptr_t dest_slot) { - CatchEntryStatePair pair; - pair.src = src_slot; - pair.dest = - (dest_slot << kCatchEntryStateDestShift) | kCatchEntryStateIsMove; - return pair; - } - - bool operator==(const CatchEntryStatePair& rhs) { - return src == rhs.src && dest == rhs.dest; - } -}; - -// Used to construct CatchEntryState metadata for AoT mode of compilation. -class CatchEntryStateMapBuilder : public ZoneAllocated { +#if !defined(DART_PRECOMPILED_RUNTIME) +// Used to construct CatchEntryMoves for the AOT mode of compilation. +class CatchEntryMovesMapBuilder : public ZoneAllocated { public: - CatchEntryStateMapBuilder(); + CatchEntryMovesMapBuilder(); void NewMapping(intptr_t pc_offset); - void AppendMove(intptr_t src_slot, intptr_t dest_slot); - void AppendConstant(intptr_t pool_id, intptr_t dest_slot); + void Append(const CatchEntryMove& move); void EndMapping(); - RawTypedData* FinalizeCatchEntryStateMap(); + RawTypedData* FinalizeCatchEntryMovesMap(); private: class TrieNode; @@ -188,12 +161,13 @@ class CatchEntryStateMapBuilder : public ZoneAllocated { Zone* zone_; TrieNode* root_; intptr_t current_pc_offset_; - GrowableArray moves_; + GrowableArray moves_; uint8_t* buffer_; WriteStream stream_; - DISALLOW_COPY_AND_ASSIGN(CatchEntryStateMapBuilder); + DISALLOW_COPY_AND_ASSIGN(CatchEntryMovesMapBuilder); }; +#endif // !defined(DART_PRECOMPILED_RUNTIME) // A CodeSourceMap maps from pc offsets to a stack of inlined functions and // their positions. This is encoded as a little bytecode that pushes and pops diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc index 3448fea416c..d2fdd609bb4 100644 --- a/runtime/vm/compiler/aot/precompiler.cc +++ b/runtime/vm/compiler/aot/precompiler.cc @@ -2709,7 +2709,7 @@ void PrecompileParsedFunctionHelper::FinalizeCompilation( graph_compiler->FinalizeStackMaps(code); graph_compiler->FinalizeVarDescriptors(code); graph_compiler->FinalizeExceptionHandlers(code); - graph_compiler->FinalizeCatchEntryStateMap(code); + graph_compiler->FinalizeCatchEntryMovesMap(code); graph_compiler->FinalizeStaticCallTargetsTable(code); graph_compiler->FinalizeCodeSourceMap(code); diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc index 3c9e52413c9..161889fbb0d 100644 --- a/runtime/vm/compiler/backend/flow_graph.cc +++ b/runtime/vm/compiler/backend/flow_graph.cc @@ -1702,32 +1702,12 @@ void FlowGraph::InsertConversion(Representation from, } } -void FlowGraph::ConvertEnvironmentUse(Value* use, Representation from_rep) { - const Representation to_rep = kTagged; - if (from_rep == to_rep) { - return; - } - InsertConversion(from_rep, to_rep, use, /*is_environment_use=*/true); -} - void FlowGraph::InsertConversionsFor(Definition* def) { const Representation from_rep = def->representation(); for (Value::Iterator it(def->input_use_list()); !it.Done(); it.Advance()) { ConvertUse(it.Current(), from_rep); } - - if (!graph_entry()->catch_entries().is_empty()) { - for (Value::Iterator it(def->env_use_list()); !it.Done(); it.Advance()) { - Value* use = it.Current(); - if (use->instruction()->MayThrow() && - use->instruction()->GetBlock()->InsideTryBlock()) { - // Environment uses at calls inside try-blocks must be converted to - // tagged representation. - ConvertEnvironmentUse(it.Current(), from_rep); - } - } - } } static void UnboxPhi(PhiInstr* phi) { diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h index a3b4ef00c9e..ba3e046ab8c 100644 --- a/runtime/vm/compiler/backend/flow_graph.h +++ b/runtime/vm/compiler/backend/flow_graph.h @@ -438,7 +438,6 @@ class FlowGraph : public ZoneAllocated { void InsertConversionsFor(Definition* def); void ConvertUse(Value* use, Representation from); - void ConvertEnvironmentUse(Value* use, Representation from); void InsertConversion(Representation from, Representation to, Value* use, diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc index ad396ce8e01..0dcc98fb8ed 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -119,7 +119,7 @@ FlowGraphCompiler::FlowGraphCompiler( pc_descriptors_list_(NULL), stackmap_table_builder_(NULL), code_source_map_builder_(NULL), - catch_entry_state_maps_builder_(NULL), + catch_entry_moves_maps_builder_(NULL), block_info_(block_order_.length()), deopt_infos_(), static_calls_target_table_(), @@ -183,7 +183,9 @@ bool FlowGraphCompiler::IsPotentialUnboxedField(const Field& field) { void FlowGraphCompiler::InitCompiler() { pc_descriptors_list_ = new (zone()) DescriptorList(64); exception_handlers_list_ = new (zone()) ExceptionHandlerList(); - catch_entry_state_maps_builder_ = new (zone()) CatchEntryStateMapBuilder(); +#if defined(DART_PRECOMPILER) + catch_entry_moves_maps_builder_ = new (zone()) CatchEntryMovesMapBuilder(); +#endif block_info_.Clear(); // Initialize block info and search optimized (non-OSR) code for calls // indicating a non-leaf routine and calls without IC data indicating @@ -340,80 +342,122 @@ intptr_t FlowGraphCompiler::UncheckedEntryOffset() const { return 0; } -void FlowGraphCompiler::EmitCatchEntryState(Environment* env, - intptr_t try_index) { -#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) +#if defined(DART_PRECOMPILER) +static intptr_t LocationToStackIndex(const Location& src) { + ASSERT(src.HasStackIndex()); + return -compiler_frame_layout.VariableIndexForFrameSlot(src.stack_index()); +} + +static CatchEntryMove CatchEntryMoveFor(Assembler* assembler, + Representation src_rep, + const Location& src, + intptr_t dst_index) { + if (src.IsConstant()) { + // Skip dead locations. + if (src.constant().raw() == Symbols::OptimizedOut().raw()) { + return CatchEntryMove(); + } + const intptr_t pool_index = + assembler->object_pool_wrapper().FindObject(src.constant()); + return CatchEntryMove::FromSlot(CatchEntryMove::SourceKind::kConstant, + pool_index, dst_index); + } + + if (src.IsPairLocation()) { + const auto lo_loc = src.AsPairLocation()->At(0); + const auto hi_loc = src.AsPairLocation()->At(1); + ASSERT(lo_loc.IsStackSlot() && hi_loc.IsStackSlot()); + return CatchEntryMove::FromSlot( + CatchEntryMove::SourceKind::kInt64PairSlot, + CatchEntryMove::EncodePairSource(LocationToStackIndex(lo_loc), + LocationToStackIndex(hi_loc)), + dst_index); + } + + CatchEntryMove::SourceKind src_kind; + switch (src_rep) { + case kTagged: + src_kind = CatchEntryMove::SourceKind::kTaggedSlot; + break; + case kUnboxedInt64: + src_kind = CatchEntryMove::SourceKind::kInt64Slot; + break; + case kUnboxedInt32: + src_kind = CatchEntryMove::SourceKind::kInt32Slot; + break; + case kUnboxedUint32: + src_kind = CatchEntryMove::SourceKind::kUint32Slot; + break; + case kUnboxedDouble: + src_kind = CatchEntryMove::SourceKind::kDoubleSlot; + break; + case kUnboxedFloat32x4: + src_kind = CatchEntryMove::SourceKind::kFloat32x4Slot; + break; + case kUnboxedFloat64x2: + src_kind = CatchEntryMove::SourceKind::kFloat64x2Slot; + break; + case kUnboxedInt32x4: + src_kind = CatchEntryMove::SourceKind::kInt32x4Slot; + break; + default: + UNREACHABLE(); + break; + } + + return CatchEntryMove::FromSlot(src_kind, LocationToStackIndex(src), + dst_index); +} +#endif + +void FlowGraphCompiler::RecordCatchEntryMoves(Environment* env, + intptr_t try_index) { +#if defined(DART_PRECOMPILER) env = env ? env : pending_deoptimization_env_; try_index = try_index != CatchClauseNode::kInvalidTryIndex ? try_index : CurrentTryIndex(); - if (is_optimizing() && env != NULL && + if (is_optimizing() && env != nullptr && (try_index != CatchClauseNode::kInvalidTryIndex)) { env = env->Outermost(); CatchBlockEntryInstr* catch_block = flow_graph().graph_entry()->GetCatchEntry(try_index); const GrowableArray* idefs = catch_block->initial_definitions(); - catch_entry_state_maps_builder_->NewMapping(assembler()->CodeSize()); - // Parameters first. - intptr_t i = 0; + catch_entry_moves_maps_builder_->NewMapping(assembler()->CodeSize()); const intptr_t num_direct_parameters = flow_graph().num_direct_parameters(); - for (; i < num_direct_parameters; ++i) { + const intptr_t ex_idx = + catch_block->raw_exception_var() != nullptr + ? flow_graph().EnvIndex(catch_block->raw_exception_var()) + : -1; + const intptr_t st_idx = + catch_block->raw_stacktrace_var() != nullptr + ? flow_graph().EnvIndex(catch_block->raw_stacktrace_var()) + : -1; + for (intptr_t i = 0; i < flow_graph().variable_count(); ++i) { // Don't sync captured parameters. They are not in the environment. if (flow_graph().captured_parameters()->Contains(i)) continue; - if ((*idefs)[i]->IsConstant()) continue; // Common constants. + // Don't sync exception or stack trace variables. + if (i == ex_idx || i == st_idx) continue; + // Don't sync values that have been replaced with constants. + if ((*idefs)[i]->IsConstant()) continue; + Location src = env->LocationAt(i); + // Can only occur if AllocationSinking is enabled - and it is disabled + // in functions with try. + ASSERT(!src.IsInvalid()); + const Representation src_rep = + env->ValueAt(i)->definition()->representation(); intptr_t dest_index = i - num_direct_parameters; - if (!src.IsStackSlot()) { - ASSERT(src.IsConstant()); - // Skip dead locations. - if (src.constant().raw() == Symbols::OptimizedOut().raw()) { - continue; - } - intptr_t id = - assembler()->object_pool_wrapper().FindObject(src.constant()); - catch_entry_state_maps_builder_->AppendConstant(id, dest_index); - continue; - } - const intptr_t src_index = - -compiler_frame_layout.VariableIndexForFrameSlot(src.stack_index()); - if (src_index != dest_index) { - catch_entry_state_maps_builder_->AppendMove(src_index, dest_index); + const auto move = + CatchEntryMoveFor(assembler(), src_rep, src, dest_index); + if (!move.IsRedundant()) { + catch_entry_moves_maps_builder_->Append(move); } } - // Process locals. Skip exception_var and stacktrace_var. - intptr_t local_base = num_direct_parameters; - intptr_t ex_idx = local_base - catch_block->exception_var().index().value(); - intptr_t st_idx = - local_base - catch_block->stacktrace_var().index().value(); - for (; i < flow_graph().variable_count(); ++i) { - // Don't sync captured parameters. They are not in the environment. - if (flow_graph().captured_parameters()->Contains(i)) continue; - if (i == ex_idx || i == st_idx) continue; - if ((*idefs)[i]->IsConstant()) continue; // Common constants. - Location src = env->LocationAt(i); - if (src.IsInvalid()) continue; - intptr_t dest_index = i - num_direct_parameters; - if (!src.IsStackSlot()) { - ASSERT(src.IsConstant()); - // Skip dead locations. - if (src.constant().raw() == Symbols::OptimizedOut().raw()) { - continue; - } - intptr_t id = - assembler()->object_pool_wrapper().FindObject(src.constant()); - catch_entry_state_maps_builder_->AppendConstant(id, dest_index); - continue; - } - const intptr_t src_index = - -compiler_frame_layout.VariableIndexForFrameSlot(src.stack_index()); - if (src_index != dest_index) { - catch_entry_state_maps_builder_->AppendMove(src_index, dest_index); - } - } - catch_entry_state_maps_builder_->EndMapping(); + catch_entry_moves_maps_builder_->EndMapping(); } #endif // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME) } @@ -424,7 +468,7 @@ void FlowGraphCompiler::EmitCallsiteMetadata(TokenPosition token_pos, LocationSummary* locs) { AddCurrentDescriptor(kind, deopt_id, token_pos); RecordSafepoint(locs); - EmitCatchEntryState(); + RecordCatchEntryMoves(); if (deopt_id != DeoptId::kNone) { // Marks either the continuation point in unoptimized code or the // deoptimization point in optimized code, after call. @@ -1019,11 +1063,11 @@ void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { code.set_var_descriptors(var_descs); } -void FlowGraphCompiler::FinalizeCatchEntryStateMap(const Code& code) { -#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) +void FlowGraphCompiler::FinalizeCatchEntryMovesMap(const Code& code) { +#if defined(DART_PRECOMPILER) TypedData& maps = TypedData::Handle( - catch_entry_state_maps_builder_->FinalizeCatchEntryStateMap()); - code.set_catch_entry_state_maps(maps); + catch_entry_moves_maps_builder_->FinalizeCatchEntryMovesMap()); + code.set_catch_entry_moves_maps(maps); #else code.set_variables(Smi::Handle(Smi::New(flow_graph().variable_count()))); #endif @@ -2223,7 +2267,7 @@ void ThrowErrorSlowPathCode::EmitNativeCode(FlowGraphCompiler* compiler) { (compiler->CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) { Environment* env = compiler->SlowPathEnvironmentFor(instruction(), num_args_); - compiler->EmitCatchEntryState(env, try_index_); + compiler->RecordCatchEntryMoves(env, try_index_); } if (!use_shared_stub) { __ Breakpoint(); diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h index 7baed3cf190..1df8a26849d 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.h +++ b/runtime/vm/compiler/backend/flow_graph_compiler.h @@ -15,6 +15,7 @@ namespace dart { // Forward declarations. +class CatchEntryMovesMapBuilder; class Code; class DeoptInfoBuilder; class FlowGraph; @@ -592,7 +593,7 @@ class FlowGraphCompiler : public ValueObject { void EmitEdgeCounter(intptr_t edge_id); #endif // !defined(TARGET_ARCH_DBC) - void EmitCatchEntryState( + void RecordCatchEntryMoves( Environment* env = NULL, intptr_t try_index = CatchClauseNode::kInvalidTryIndex); @@ -665,7 +666,7 @@ class FlowGraphCompiler : public ValueObject { RawArray* CreateDeoptInfo(Assembler* assembler); void FinalizeStackMaps(const Code& code); void FinalizeVarDescriptors(const Code& code); - void FinalizeCatchEntryStateMap(const Code& code); + void FinalizeCatchEntryMovesMap(const Code& code); void FinalizeStaticCallTargetsTable(const Code& code); void FinalizeCodeSourceMap(const Code& code); @@ -953,7 +954,7 @@ class FlowGraphCompiler : public ValueObject { DescriptorList* pc_descriptors_list_; StackMapTableBuilder* stackmap_table_builder_; CodeSourceMapBuilder* code_source_map_builder_; - CatchEntryStateMapBuilder* catch_entry_state_maps_builder_; + CatchEntryMovesMapBuilder* catch_entry_moves_maps_builder_; GrowableArray block_info_; GrowableArray deopt_infos_; GrowableArray slow_path_code_; diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc index a6ff28b02a7..f53c4387aaf 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc @@ -1070,7 +1070,7 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall( // arguments are removed. AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); } - EmitCatchEntryState(pending_deoptimization_env_, try_index); + RecordCatchEntryMoves(pending_deoptimization_env_, try_index); __ Drop(args_desc.CountWithTypeArgs()); } diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc index 2dc1a303da9..998842ad1db 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc @@ -1039,7 +1039,7 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall( // arguments are removed. AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); } - EmitCatchEntryState(pending_deoptimization_env_, try_index); + RecordCatchEntryMoves(pending_deoptimization_env_, try_index); __ Drop(args_desc.CountWithTypeArgs()); } diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc index 93dde40e221..bfc712ad8da 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc @@ -979,7 +979,7 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall( // arguments are removed. AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); } - EmitCatchEntryState(pending_deoptimization_env_, try_index); + RecordCatchEntryMoves(pending_deoptimization_env_, try_index); __ Drop(args_desc.CountWithTypeArgs()); } diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc index 5c1329a133c..ae17719e4e7 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc @@ -1062,7 +1062,7 @@ void FlowGraphCompiler::EmitMegamorphicInstanceCall( // arguments are removed. AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); } - EmitCatchEntryState(pending_deoptimization_env_, try_index); + RecordCatchEntryMoves(pending_deoptimization_env_, try_index); __ Drop(args_desc.CountWithTypeArgs(), RCX); } diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index fb9dcdbd27a..3e94025b9d3 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -2824,19 +2824,8 @@ Instruction* DebugStepCheckInstr::Canonicalize(FlowGraph* flow_graph) { return NULL; } -static bool HasTryBlockUse(Value* use_list) { - for (Value::Iterator it(use_list); !it.Done(); it.Advance()) { - Value* use = it.Current(); - if (use->instruction()->MayThrow() && - use->instruction()->GetBlock()->InsideTryBlock()) { - return true; - } - } - return false; -} - Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) { - if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { + if (input_use_list() == nullptr) { // Environments can accommodate any representation. No need to box. return value()->definition(); } @@ -2859,7 +2848,7 @@ bool BoxIntegerInstr::ValueFitsSmi() const { } Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { - if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { + if (input_use_list() == nullptr) { // Environments can accommodate any representation. No need to box. return value()->definition(); } diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index 6474df0ae9f..99b85adf3df 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -3068,7 +3068,7 @@ class CheckStackOverflowSlowPath __ ldr(LR, Address(THR, entry_point_offset)); __ blx(LR); compiler->RecordSafepoint(instruction()->locs(), kNumSlowPathArgs); - compiler->EmitCatchEntryState(); + compiler->RecordCatchEntryMoves(); compiler->AddDescriptor( RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), instruction()->deopt_id(), instruction()->token_pos(), diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index ed0f4002aef..61b4766153d 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -2752,7 +2752,7 @@ class CheckStackOverflowSlowPath __ ldr(LR, Address(THR, entry_point_offset)); __ blr(LR); compiler->RecordSafepoint(instruction()->locs(), kNumSlowPathArgs); - compiler->EmitCatchEntryState(); + compiler->RecordCatchEntryMoves(); compiler->AddDescriptor( RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), instruction()->deopt_id(), instruction()->token_pos(), diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index a5e521b0d33..f0cfb7b04ae 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -2752,7 +2752,7 @@ class CheckStackOverflowSlowPath stack_overflow_shared_without_fpu_regs_entry_point_offset(); __ call(Address(THR, entry_point_offset)); compiler->RecordSafepoint(instruction()->locs(), kNumSlowPathArgs); - compiler->EmitCatchEntryState(); + compiler->RecordCatchEntryMoves(); compiler->AddDescriptor( RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), instruction()->deopt_id(), instruction()->token_pos(), diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc index 14670ceb588..e84b28db347 100644 --- a/runtime/vm/compiler/jit/compiler.cc +++ b/runtime/vm/compiler/jit/compiler.cc @@ -630,7 +630,7 @@ RawCode* CompileParsedFunctionHelper::FinalizeCompilation( graph_compiler->FinalizeStackMaps(code); graph_compiler->FinalizeVarDescriptors(code); graph_compiler->FinalizeExceptionHandlers(code); - graph_compiler->FinalizeCatchEntryStateMap(code); + graph_compiler->FinalizeCatchEntryMovesMap(code); graph_compiler->FinalizeStaticCallTargetsTable(code); graph_compiler->FinalizeCodeSourceMap(code); diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc index ec6fa743e84..ec35ebc8565 100644 --- a/runtime/vm/deopt_instructions.cc +++ b/runtime/vm/deopt_instructions.cc @@ -335,7 +335,7 @@ void DeoptContext::FillDestFrame() { } } -intptr_t* DeoptContext::CatchEntryState(intptr_t num_vars) { +const CatchEntryMoves* DeoptContext::ToCatchEntryMoves(intptr_t num_vars) { const Code& code = Code::Handle(code_); const TypedData& deopt_info = TypedData::Handle(deopt_info_); GrowableArray deopt_instructions; @@ -343,8 +343,7 @@ intptr_t* DeoptContext::CatchEntryState(intptr_t num_vars) { ASSERT(!deopt_table.IsNull()); DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions); - intptr_t* state = new intptr_t[2 * num_vars + 1]; - state[0] = num_vars; + CatchEntryMoves* moves = CatchEntryMoves::Allocate(num_vars); Function& function = Function::Handle(zone(), code.function()); intptr_t params = @@ -363,12 +362,10 @@ intptr_t* DeoptContext::CatchEntryState(intptr_t num_vars) { DeoptInstr* instr = deopt_instructions[len - 1 - slot]; intptr_t dest_index = i - params; #endif - CatchEntryStatePair p = instr->ToCatchEntryStatePair(this, dest_index); - state[1 + 2 * i] = p.src; - state[2 + 2 * i] = p.dest; + moves->At(i) = instr->ToCatchEntryMove(this, dest_index); } - return state; + return moves; } static void FillDeferredSlots(DeoptContext* deopt_context, @@ -508,9 +505,9 @@ class DeoptConstantInstr : public DeoptInstr { *reinterpret_cast(dest_addr) = obj.raw(); } - CatchEntryStatePair ToCatchEntryStatePair(DeoptContext* deopt_context, - intptr_t dest_slot) { - return CatchEntryStatePair::FromConstant(object_table_index_, dest_slot); + CatchEntryMove ToCatchEntryMove(DeoptContext* deopt_context, + intptr_t dest_slot) { + return CatchEntryMove::FromConstant(object_table_index_, dest_slot); } private: @@ -540,10 +537,11 @@ class DeoptWordInstr : public DeoptInstr { *dest_addr = source_.Value(deopt_context); } - CatchEntryStatePair ToCatchEntryStatePair(DeoptContext* deopt_context, - intptr_t dest_slot) { - return CatchEntryStatePair::FromMove(source_.StackSlot(deopt_context), - dest_slot); + CatchEntryMove ToCatchEntryMove(DeoptContext* deopt_context, + intptr_t dest_slot) { + return CatchEntryMove::FromSlot(CatchEntryMove::SourceKind::kTaggedSlot, + source_.StackSlot(deopt_context), + dest_slot); } private: @@ -599,6 +597,15 @@ class DeoptMintPairInstr : public DeoptIntegerInstrBase { hi_.Value(deopt_context)); } + CatchEntryMove ToCatchEntryMove(DeoptContext* deopt_context, + intptr_t dest_slot) { + return CatchEntryMove::FromSlot( + CatchEntryMove::SourceKind::kInt64PairSlot, + CatchEntryMove::EncodePairSource(lo_.StackSlot(deopt_context), + hi_.StackSlot(deopt_context)), + dest_slot); + } + private: static const intptr_t kFieldWidth = kBitsPerWord / 2; class LoRegister : public BitField {}; @@ -611,7 +618,7 @@ class DeoptMintPairInstr : public DeoptIntegerInstrBase { DISALLOW_COPY_AND_ASSIGN(DeoptMintPairInstr); }; -template +template class DeoptIntInstr : public DeoptIntegerInstrBase { public: explicit DeoptIntInstr(intptr_t source_index) @@ -629,17 +636,35 @@ class DeoptIntInstr : public DeoptIntegerInstrBase { return static_cast(source_.Value(deopt_context)); } + CatchEntryMove ToCatchEntryMove(DeoptContext* deopt_context, + intptr_t dest_slot) { + return CatchEntryMove::FromSlot(slot_kind, source_.StackSlot(deopt_context), + dest_slot); + } + private: const CpuRegisterSource source_; DISALLOW_COPY_AND_ASSIGN(DeoptIntInstr); }; -typedef DeoptIntInstr DeoptUint32Instr; -typedef DeoptIntInstr DeoptInt32Instr; -typedef DeoptIntInstr DeoptMintInstr; +typedef DeoptIntInstr + DeoptUint32Instr; +typedef DeoptIntInstr + DeoptInt32Instr; +typedef DeoptIntInstr + DeoptMintInstr; -template +template class DeoptFpuInstr : public DeoptInstr { public: explicit DeoptFpuInstr(intptr_t source_index) : source_(source_index) {} @@ -658,22 +683,39 @@ class DeoptFpuInstr : public DeoptInstr { reinterpret_cast(dest_addr)); } + CatchEntryMove ToCatchEntryMove(DeoptContext* deopt_context, + intptr_t dest_slot) { + return CatchEntryMove::FromSlot(slot_kind, source_.StackSlot(deopt_context), + dest_slot); + } + private: const FpuRegisterSource source_; DISALLOW_COPY_AND_ASSIGN(DeoptFpuInstr); }; -typedef DeoptFpuInstr DeoptDoubleInstr; +typedef DeoptFpuInstr + DeoptDoubleInstr; // Simd128 types. -typedef DeoptFpuInstr +typedef DeoptFpuInstr DeoptFloat32x4Instr; -typedef DeoptFpuInstr - DeoptFloat32x4Instr; -typedef DeoptFpuInstr +typedef DeoptFpuInstr DeoptFloat64x2Instr; -typedef DeoptFpuInstr +typedef DeoptFpuInstr DeoptInt32x4Instr; // Deoptimization instruction creating a PC marker for the code of diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h index 38d95fdce33..e2096b61d31 100644 --- a/runtime/vm/deopt_instructions.h +++ b/runtime/vm/deopt_instructions.h @@ -166,8 +166,10 @@ class DeoptContext { // objects. void FillDestFrame(); - // Allocate and prepare exceptions metadata for TrySync - intptr_t* CatchEntryState(intptr_t num_vars); + // Convert deoptimization instructions to a list of moves that need + // to be executed when entering catch entry block from this deoptimization + // point. + const CatchEntryMoves* ToCatchEntryMoves(intptr_t num_vars); // Materializes all deferred objects. Returns the total number of // artificial arguments used during deoptimization. @@ -334,11 +336,10 @@ class DeoptInstr : public ZoneAllocated { virtual void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) = 0; - // Convert DeoptInstr to TrySync metadata entry. - virtual CatchEntryStatePair ToCatchEntryStatePair(DeoptContext* deopt_context, - intptr_t dest_slot) { + virtual CatchEntryMove ToCatchEntryMove(DeoptContext* deopt_context, + intptr_t dest_slot) { UNREACHABLE(); - return CatchEntryStatePair(); + return CatchEntryMove(); } virtual DeoptInstr::Kind kind() const = 0; diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index 54379301913..52487822de3 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc @@ -141,20 +141,10 @@ static void BuildStackTrace(StackTraceBuilder* builder) { } } -static RawObject** VariableAt(uword fp, int stack_slot) { -#if defined(TARGET_ARCH_DBC) - return reinterpret_cast(fp + stack_slot * kWordSize); -#else - const intptr_t frame_slot = - runtime_frame_layout.FrameSlotForVariableIndex(-stack_slot); - return reinterpret_cast(fp + frame_slot * kWordSize); -#endif -} - class ExceptionHandlerFinder : public StackResource { public: explicit ExceptionHandlerFinder(Thread* thread) - : StackResource(thread), thread_(thread), cache_(NULL), metadata_(NULL) {} + : StackResource(thread), thread_(thread) {} // Iterate through the stack frames and try to find a frame with an // exception handler. Once found, set the pc, sp and fp so that execution @@ -172,7 +162,7 @@ class ExceptionHandlerFinder : public StackResource { uword temp_handler_pc = kUwordMax; bool is_optimized = false; code_ = NULL; - cache_ = thread_->isolate()->catch_entry_state_cache(); + catch_entry_moves_cache_ = thread_->isolate()->catch_entry_moves_cache(); while (!frame->IsEntryFrame()) { if (frame->IsDartFrame()) { @@ -187,13 +177,20 @@ class ExceptionHandlerFinder : public StackResource { if (is_optimized) { pc_ = frame->pc(); code_ = &Code::Handle(frame->LookupDartCode()); - CatchEntryState* state = cache_->Lookup(pc_); - if (state != NULL) cached_ = *state; + CatchEntryMovesRefPtr* cached_catch_entry_moves = + catch_entry_moves_cache_->Lookup(pc_); + if (cached_catch_entry_moves != NULL) { + cached_catch_entry_moves_ = *cached_catch_entry_moves; + } #if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER) intptr_t num_vars = Smi::Value(code_->variables()); - if (cached_.Empty()) GetMetaDataFromDeopt(num_vars, frame); + if (cached_catch_entry_moves_.IsEmpty()) { + GetCatchEntryMovesFromDeopt(num_vars, frame); + } #else - if (cached_.Empty()) ReadCompressedMetaData(); + if (cached_catch_entry_moves_.IsEmpty()) { + ReadCompressedCatchEntryMoves(); + } #endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER) } } @@ -216,80 +213,121 @@ class ExceptionHandlerFinder : public StackResource { return handler_pc_set_; } - void TrySync() { - if (code_ == NULL || !code_->is_optimized()) { + // When entering catch block in the optimized code we need to execute + // catch entry moves that would morph the state of the frame into + // what catch entry expects. + void PrepareFrameForCatchEntry() { + if (code_ == nullptr || !code_->is_optimized()) { return; } - if (!cached_.Empty()) { - // Cache hit. - TrySyncCached(&cached_); + + if (cached_catch_entry_moves_.IsEmpty()) { + catch_entry_moves_cache_->Insert( + pc_, CatchEntryMovesRefPtr(catch_entry_moves_)); } else { - // New cache entry. - CatchEntryState m(metadata_); - TrySyncCached(&m); - cache_->Insert(pc_, m); + catch_entry_moves_ = &cached_catch_entry_moves_.moves(); } + + ExecuteCatchEntryMoves(*catch_entry_moves_); } - void TrySyncCached(CatchEntryState* md) { + void ExecuteCatchEntryMoves(const CatchEntryMoves& moves) { uword fp = handler_fp; - ObjectPool* pool = NULL; - intptr_t pairs = md->Pairs(); - for (int j = 0; j < pairs; j++) { - intptr_t src = md->Src(j); - intptr_t dest = md->Dest(j); - if (md->isMove(j)) { - *VariableAt(fp, dest) = *VariableAt(fp, src); - } else { - if (pool == NULL) { - pool = &ObjectPool::Handle(code_->object_pool()); - } - RawObject* obj = pool->ObjectAt(src); - *VariableAt(fp, dest) = obj; + ObjectPool* pool = nullptr; + for (int j = 0; j < moves.count(); j++) { + const CatchEntryMove& move = moves.At(j); + + RawObject* value; + switch (move.source_kind()) { + case CatchEntryMove::SourceKind::kConstant: + if (pool == nullptr) { + pool = &ObjectPool::Handle(code_->object_pool()); + } + value = pool->ObjectAt(move.src_slot()); + break; + + case CatchEntryMove::SourceKind::kTaggedSlot: + value = *TaggedSlotAt(fp, move.src_slot()); + break; + + case CatchEntryMove::SourceKind::kDoubleSlot: + value = Double::New(*SlotAt(fp, move.src_slot())); + break; + + case CatchEntryMove::SourceKind::kFloat32x4Slot: + value = Float32x4::New(*SlotAt(fp, move.src_slot())); + break; + + case CatchEntryMove::SourceKind::kFloat64x2Slot: + value = Float64x2::New(*SlotAt(fp, move.src_slot())); + break; + + case CatchEntryMove::SourceKind::kInt32x4Slot: + value = Int32x4::New(*SlotAt(fp, move.src_slot())); + break; + + case CatchEntryMove::SourceKind::kInt64PairSlot: + value = Integer::New( + Utils::LowHighTo64Bits(*SlotAt(fp, move.src_lo_slot()), + *SlotAt(fp, move.src_hi_slot()))); + break; + + case CatchEntryMove::SourceKind::kInt64Slot: + value = Integer::New(*SlotAt(fp, move.src_slot())); + break; + + case CatchEntryMove::SourceKind::kInt32Slot: + value = Integer::New(*SlotAt(fp, move.src_slot())); + break; + + case CatchEntryMove::SourceKind::kUint32Slot: + value = Integer::New(*SlotAt(fp, move.src_slot())); + break; } + + *TaggedSlotAt(fp, move.dest_slot()) = value; } } #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER) - void ReadCompressedMetaData() { + void ReadCompressedCatchEntryMoves() { intptr_t pc_offset = pc_ - code_->PayloadStart(); - const TypedData& td = TypedData::Handle(code_->catch_entry_state_maps()); + const TypedData& td = TypedData::Handle(code_->catch_entry_moves_maps()); NoSafepointScope no_safepoint; ReadStream stream(static_cast(td.DataAddr(0)), td.Length()); - bool found_metadata = false; + intptr_t prefix_length, suffix_length, suffix_offset; while (stream.PendingBytes() > 0) { intptr_t target_pc_offset = Reader::Read(&stream); - intptr_t variables = Reader::Read(&stream); - intptr_t suffix_length = Reader::Read(&stream); - intptr_t suffix_offset = Reader::Read(&stream); + prefix_length = Reader::Read(&stream); + suffix_length = Reader::Read(&stream); + suffix_offset = Reader::Read(&stream); if (pc_offset == target_pc_offset) { - metadata_ = new intptr_t[2 * (variables + suffix_length) + 1]; - metadata_[0] = variables + suffix_length; - for (int j = 0; j < variables; j++) { - intptr_t src = Reader::Read(&stream); - intptr_t dest = Reader::Read(&stream); - metadata_[1 + 2 * j] = src; - metadata_[2 + 2 * j] = dest; - } - ReadCompressedSuffix(&stream, suffix_offset, suffix_length, metadata_, - 2 * variables + 1); - found_metadata = true; break; - } else { - for (intptr_t j = 0; j < 2 * variables; j++) { - Reader::Read(&stream); - } + } + + // Skip the moves. + for (intptr_t j = 0; j < prefix_length; j++) { + CatchEntryMove::ReadFrom(&stream); } } - ASSERT(found_metadata); + ASSERT((stream.PendingBytes() > 0) || (prefix_length == 0)); + + CatchEntryMoves* moves = + CatchEntryMoves::Allocate(prefix_length + suffix_length); + for (int j = 0; j < prefix_length; j++) { + moves->At(j) = CatchEntryMove::ReadFrom(&stream); + } + ReadCompressedCatchEntryMovesSuffix(&stream, suffix_offset, suffix_length, + moves, prefix_length); + catch_entry_moves_ = moves; } - void ReadCompressedSuffix(ReadStream* stream, - intptr_t offset, - intptr_t length, - intptr_t* target, - intptr_t target_offset) { + void ReadCompressedCatchEntryMovesSuffix(ReadStream* stream, + intptr_t offset, + intptr_t length, + CatchEntryMoves* moves, + intptr_t moves_offset) { stream->SetPosition(offset); Reader::Read(stream); // skip pc_offset Reader::Read(stream); // skip variables @@ -297,24 +335,23 @@ class ExceptionHandlerFinder : public StackResource { intptr_t suffix_offset = Reader::Read(stream); intptr_t to_read = length - suffix_length; for (int j = 0; j < to_read; j++) { - target[target_offset + 2 * j] = Reader::Read(stream); - target[target_offset + 2 * j + 1] = Reader::Read(stream); + moves->At(moves_offset + j) = CatchEntryMove::ReadFrom(stream); } if (suffix_length > 0) { - ReadCompressedSuffix(stream, suffix_offset, suffix_length, target, - target_offset + to_read * 2); + ReadCompressedCatchEntryMovesSuffix(stream, suffix_offset, suffix_length, + moves, moves_offset + to_read); } } #else - void GetMetaDataFromDeopt(intptr_t num_vars, StackFrame* frame) { + void GetCatchEntryMovesFromDeopt(intptr_t num_vars, StackFrame* frame) { Isolate* isolate = thread_->isolate(); DeoptContext* deopt_context = new DeoptContext(frame, *code_, DeoptContext::kDestIsAllocated, NULL, NULL, true, false /* deoptimizing_code */); isolate->set_deopt_context(deopt_context); - metadata_ = deopt_context->CatchEntryState(num_vars); + catch_entry_moves_ = deopt_context->ToCatchEntryMoves(num_vars); isolate->set_deopt_context(NULL); delete deopt_context; @@ -327,16 +364,47 @@ class ExceptionHandlerFinder : public StackResource { uword handler_fp; private: + template + static T* SlotAt(uword fp, int stack_slot) { +#if defined(TARGET_ARCH_DBC) + return reinterpret_cast(fp + stack_slot * kWordSize); +#else + const intptr_t frame_slot = + runtime_frame_layout.FrameSlotForVariableIndex(-stack_slot); + return reinterpret_cast(fp + frame_slot * kWordSize); +#endif + } + + static RawObject** TaggedSlotAt(uword fp, int stack_slot) { + return SlotAt(fp, stack_slot); + } + typedef ReadStream::Raw Reader; Thread* thread_; - CatchEntryStateCache* cache_; Code* code_; bool handler_pc_set_; - intptr_t* metadata_; // MetaData generated from deopt. - CatchEntryState cached_; // Value of per PC MetaData cache. intptr_t pc_; // Current pc in the handler frame. + + const CatchEntryMoves* catch_entry_moves_ = nullptr; + CatchEntryMovesCache* catch_entry_moves_cache_ = nullptr; + CatchEntryMovesRefPtr cached_catch_entry_moves_; }; +CatchEntryMove CatchEntryMove::ReadFrom(ReadStream* stream) { + using Reader = ReadStream::Raw; + const intptr_t src = Reader::Read(stream); + const intptr_t dest_and_kind = Reader::Read(stream); + return CatchEntryMove(src, dest_and_kind); +} + +#if !defined(DART_PRECOMPILED_RUNTIME) +void CatchEntryMove::WriteTo(WriteStream* stream) { + using Writer = WriteStream::Raw; + Writer::Write(stream, src_); + Writer::Write(stream, dest_and_kind_); +} +#endif + static void FindErrorHandler(uword* handler_pc, uword* handler_sp, uword* handler_fp) { @@ -619,7 +687,7 @@ static void ThrowExceptionHelper(Thread* thread, THR_Print("%s\n", stacktrace.ToCString()); } if (handler_exists) { - finder.TrySync(); + finder.PrepareFrameForCatchEntry(); // Found a dart handler for the exception, jump to it. JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, exception, stacktrace); diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h index d9b8c14cd31..b681b0ff6f9 100644 --- a/runtime/vm/exceptions.h +++ b/runtime/vm/exceptions.h @@ -6,6 +6,7 @@ #define RUNTIME_VM_EXCEPTIONS_H_ #include "vm/allocation.h" +#include "vm/bitfield.h" #include "vm/token_position.h" namespace dart { @@ -22,6 +23,8 @@ class RawInstance; class RawObject; class RawScript; class RawStackTrace; +class ReadStream; +class WriteStream; class String; class Thread; @@ -106,61 +109,193 @@ struct ExceptionHandlerInfo { int8_t is_generated; // True if this is a generated handler. }; -class CatchEntryState { +// +// Support for try/catch in the optimized code. +// +// Optimizing compiler does not model exceptional control flow explicitly, +// instead we rely on the runtime system to create correct state at the +// entry into the catch block by reshuffling values in the frame into +// positions where they are expected to be at the beginning of the catch block. +// +// See runtime/docs/compiler/exceptions.md for more details. +// + +// A single move from a stack slot or an object pool into another stack slot. +// Destination slot is expecting only tagged values, however source +// slot can contain an unboxed value (e.g. an unboxed double) - in this case +// we will box the value before executing the move. +class CatchEntryMove { public: - enum { kCatchEntryStateIsMove = 1, kCatchEntryStateDestShift = 1 }; + CatchEntryMove() + : src_(0), + dest_and_kind_(static_cast(SourceKind::kTaggedSlot)) { + ASSERT(IsRedundant()); + } - CatchEntryState() : data_(NULL), ref_count_(NULL) {} - explicit CatchEntryState(intptr_t* data) - : data_(data), ref_count_(new intptr_t(1)) {} + enum class SourceKind { + kConstant, + kTaggedSlot, + kDoubleSlot, + kFloat32x4Slot, + kFloat64x2Slot, + kInt32x4Slot, + kInt64PairSlot, + kInt64Slot, + kInt32Slot, + kUint32Slot, + }; - CatchEntryState(const CatchEntryState& state) { Copy(state); } + SourceKind source_kind() const { + return SourceKindField::decode(dest_and_kind_); + } - ~CatchEntryState() { Destroy(); } + intptr_t src_slot() const { + ASSERT(source_kind() != SourceKind::kInt64PairSlot); + return src_; + } - CatchEntryState& operator=(const CatchEntryState& state) { + intptr_t src_lo_slot() const { + ASSERT(source_kind() == SourceKind::kInt64PairSlot); + return LoSourceSlot::decode(src_); + } + + intptr_t src_hi_slot() const { + ASSERT(source_kind() == SourceKind::kInt64PairSlot); + return HiSourceSlot::decode(src_); + } + + intptr_t dest_slot() const { + return dest_and_kind_ >> SourceKindField::bitsize(); + } + + static CatchEntryMove FromConstant(intptr_t pool_id, intptr_t dest_slot) { + return FromSlot(SourceKind::kConstant, pool_id, dest_slot); + } + + static CatchEntryMove FromSlot(SourceKind kind, + intptr_t src_slot, + intptr_t dest_slot) { + return CatchEntryMove(src_slot, + SourceKindField::encode(kind) | + (dest_slot << SourceKindField::bitsize())); + } + + static intptr_t EncodePairSource(intptr_t src_lo_slot, intptr_t src_hi_slot) { + return LoSourceSlot::encode(src_lo_slot) | + HiSourceSlot::encode(src_hi_slot); + } + + bool IsRedundant() const { + return (source_kind() == SourceKind::kTaggedSlot) && + (dest_slot() == src_slot()); + } + + bool operator==(const CatchEntryMove& rhs) { + return src_ == rhs.src_ && dest_and_kind_ == rhs.dest_and_kind_; + } + + static CatchEntryMove ReadFrom(ReadStream* stream); + +#if !defined(DART_PRECOMPILED_RUNTIME) + void WriteTo(WriteStream* stream); +#endif + + private: + CatchEntryMove(intptr_t src, intptr_t dest_and_kind) + : src_(src), dest_and_kind_(dest_and_kind) {} + + // Note: BitField helper does not work with signed values of size that does + // not match the destination size - thus we don't use BitField for declaring + // DestinationField and instead encode and decode it manually. + using SourceKindField = BitField; + + static constexpr intptr_t kHalfSourceBits = kBitsPerWord / 2; + using LoSourceSlot = BitField; + using HiSourceSlot = + BitField; + + intptr_t src_; + intptr_t dest_and_kind_; +}; + +// A sequence of moves that needs to be executed to create a state expected +// at the catch entry. +// Note: this is a deserialized representation that is used by the runtime +// system as a temporary representation and for caching. That is why this +// object is allocated in the malloced heap and not in the Dart heap. +class CatchEntryMoves { + public: + static CatchEntryMoves* Allocate(intptr_t num_moves) { + auto result = reinterpret_cast( + malloc(sizeof(CatchEntryMoves) + sizeof(CatchEntryMove) * num_moves)); + result->count_ = num_moves; + return result; + } + + static void Free(const CatchEntryMoves* moves) { + free(const_cast(moves)); + } + + intptr_t count() const { return count_; } + CatchEntryMove& At(intptr_t i) { return Moves()[i]; } + const CatchEntryMove& At(intptr_t i) const { return Moves()[i]; } + + private: + CatchEntryMove* Moves() { + return reinterpret_cast(this + 1); + } + + const CatchEntryMove* Moves() const { + return reinterpret_cast(this + 1); + } + + intptr_t count_; + // Followed by CatchEntryMove[count_] +}; + +// A simple reference counting wrapper for CatchEntryMoves. +// +// TODO(vegorov) switch this to intrusive reference counting. +class CatchEntryMovesRefPtr { + public: + CatchEntryMovesRefPtr() : moves_(nullptr), ref_count_(nullptr) {} + explicit CatchEntryMovesRefPtr(const CatchEntryMoves* moves) + : moves_(moves), ref_count_(new intptr_t(1)) {} + + CatchEntryMovesRefPtr(const CatchEntryMovesRefPtr& state) { Copy(state); } + + ~CatchEntryMovesRefPtr() { Destroy(); } + + CatchEntryMovesRefPtr& operator=(const CatchEntryMovesRefPtr& state) { Destroy(); Copy(state); return *this; } - bool Empty() { return ref_count_ == NULL; } + bool IsEmpty() { return ref_count_ == nullptr; } - intptr_t Pairs() { return data_[0]; } - - intptr_t Src(intptr_t i) { return data_[1 + 2 * i]; } - - intptr_t Dest(intptr_t i) { - return data_[2 + 2 * i] >> kCatchEntryStateDestShift; - } - - bool isMove(intptr_t i) { return data_[2 + 2 * i] & kCatchEntryStateIsMove; } + const CatchEntryMoves& moves() { return *moves_; } private: void Destroy() { - if (ref_count_ != NULL) { + if (ref_count_ != nullptr) { (*ref_count_)--; if (*ref_count_ == 0) { delete ref_count_; - delete[] data_; + CatchEntryMoves::Free(moves_); } } } - void Copy(const CatchEntryState& state) { - data_ = state.data_; + void Copy(const CatchEntryMovesRefPtr& state) { + moves_ = state.moves_; ref_count_ = state.ref_count_; - if (ref_count_ != NULL) { + if (ref_count_ != nullptr) { (*ref_count_)++; } } - // data_ has the following format: - // 0 - number of pairs in this state - // 1-2 - 1st encoded src,dest pair - // 3-4 - 2nd pair - // .... - intptr_t* data_; + const CatchEntryMoves* moves_; intptr_t* ref_count_; }; diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc index de9911f323a..2b319e28d7e 100644 --- a/runtime/vm/heap/heap.cc +++ b/runtime/vm/heap/heap.cc @@ -431,7 +431,7 @@ void Heap::CollectOldSpaceGarbage(Thread* thread, NOT_IN_PRODUCT(PrintStatsToTimeline(&tds, reason)); // Some Code objects may have been collected so invalidate handler cache. thread->isolate()->handler_info_cache()->Clear(); - thread->isolate()->catch_entry_state_cache()->Clear(); + thread->isolate()->catch_entry_moves_cache()->Clear(); EndOldSpaceGC(); } } diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index af54df85721..aa4ae114fea 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -941,7 +941,7 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags) spawn_count_monitor_(new Monitor()), spawn_count_(0), handler_info_cache_(), - catch_entry_state_cache_(), + catch_entry_moves_cache_(), embedder_entry_points_(NULL), obfuscation_map_(NULL) { FlagsCopyFrom(api_flags); diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index b40651f0249..07e61972c0e 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -130,7 +130,7 @@ class NoReloadScope : public StackResource { // Fixed cache for exception handler lookup. typedef FixedCache HandlerInfoCache; // Fixed cache for catch entry state lookup. -typedef FixedCache CatchEntryStateCache; +typedef FixedCache CatchEntryMovesCache; // List of Isolate flags with corresponding members of Dart_IsolateFlags and // corresponding global command line flags. @@ -784,8 +784,8 @@ class Isolate : public BaseIsolate { HandlerInfoCache* handler_info_cache() { return &handler_info_cache_; } - CatchEntryStateCache* catch_entry_state_cache() { - return &catch_entry_state_cache_; + CatchEntryMovesCache* catch_entry_moves_cache() { + return &catch_entry_moves_cache_; } void MaybeIncreaseReloadEveryNStackOverflowChecks(); @@ -1017,7 +1017,7 @@ class Isolate : public BaseIsolate { intptr_t spawn_count_; HandlerInfoCache handler_info_cache_; - CatchEntryStateCache catch_entry_state_cache_; + CatchEntryMovesCache catch_entry_moves_cache_; Dart_QualifiedFunctionName* embedder_entry_points_; const char** obfuscation_map_; diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index c8149f6f327..434de7b1e81 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -15398,8 +15398,8 @@ void Code::set_variables(const Smi& smi) const { StorePointer(&raw_ptr()->catch_entry_.variables_, smi.raw()); } #else -void Code::set_catch_entry_state_maps(const TypedData& maps) const { - StorePointer(&raw_ptr()->catch_entry_.catch_entry_state_maps_, maps.raw()); +void Code::set_catch_entry_moves_maps(const TypedData& maps) const { + StorePointer(&raw_ptr()->catch_entry_.catch_entry_moves_maps_, maps.raw()); } #endif diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 6613544b3d0..11ea3987b6b 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -5045,10 +5045,10 @@ class Code : public Object { RawSmi* variables() const { return raw_ptr()->catch_entry_.variables_; } void set_variables(const Smi& smi) const; #else - RawTypedData* catch_entry_state_maps() const { - return raw_ptr()->catch_entry_.catch_entry_state_maps_; + RawTypedData* catch_entry_moves_maps() const { + return raw_ptr()->catch_entry_.catch_entry_moves_maps_; } - void set_catch_entry_state_maps(const TypedData& maps) const; + void set_catch_entry_moves_maps(const TypedData& maps) const; #endif RawArray* stackmaps() const { return raw_ptr()->stackmaps_; } diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc index a6400e89088..2fe88417e0a 100644 --- a/runtime/vm/program_visitor.cc +++ b/runtime/vm/program_visitor.cc @@ -380,51 +380,51 @@ void ProgramVisitor::DedupDeoptEntries() { #endif // !defined(DART_PRECOMPILED_RUNTIME) #if defined(DART_PRECOMPILER) -void ProgramVisitor::DedupCatchEntryStateMaps() { +void ProgramVisitor::DedupCatchEntryMovesMaps() { if (!FLAG_precompiled_mode) { return; } - class DedupCatchEntryStateMapsVisitor : public FunctionVisitor { + class DedupCatchEntryMovesMapsVisitor : public FunctionVisitor { public: - explicit DedupCatchEntryStateMapsVisitor(Zone* zone) + explicit DedupCatchEntryMovesMapsVisitor(Zone* zone) : zone_(zone), - canonical_catch_entry_state_maps_(), + canonical_catch_entry_moves_maps_(), code_(Code::Handle(zone)), - catch_entry_state_maps_(TypedData::Handle(zone)) {} + catch_entry_moves_maps_(TypedData::Handle(zone)) {} void Visit(const Function& function) { if (!function.HasCode()) { return; } code_ = function.CurrentCode(); - catch_entry_state_maps_ = code_.catch_entry_state_maps(); - catch_entry_state_maps_ = - DedupCatchEntryStateMaps(catch_entry_state_maps_); - code_.set_catch_entry_state_maps(catch_entry_state_maps_); + catch_entry_moves_maps_ = code_.catch_entry_moves_maps(); + catch_entry_moves_maps_ = + DedupCatchEntryMovesMaps(catch_entry_moves_maps_); + code_.set_catch_entry_moves_maps(catch_entry_moves_maps_); } - RawTypedData* DedupCatchEntryStateMaps( - const TypedData& catch_entry_state_maps) { - const TypedData* canonical_catch_entry_state_maps = - canonical_catch_entry_state_maps_.LookupValue( - &catch_entry_state_maps); - if (canonical_catch_entry_state_maps == NULL) { - canonical_catch_entry_state_maps_.Insert( - &TypedData::ZoneHandle(zone_, catch_entry_state_maps.raw())); - return catch_entry_state_maps.raw(); + RawTypedData* DedupCatchEntryMovesMaps( + const TypedData& catch_entry_moves_maps) { + const TypedData* canonical_catch_entry_moves_maps = + canonical_catch_entry_moves_maps_.LookupValue( + &catch_entry_moves_maps); + if (canonical_catch_entry_moves_maps == NULL) { + canonical_catch_entry_moves_maps_.Insert( + &TypedData::ZoneHandle(zone_, catch_entry_moves_maps.raw())); + return catch_entry_moves_maps.raw(); } else { - return canonical_catch_entry_state_maps->raw(); + return canonical_catch_entry_moves_maps->raw(); } } private: Zone* zone_; - TypedDataSet canonical_catch_entry_state_maps_; + TypedDataSet canonical_catch_entry_moves_maps_; Code& code_; - TypedData& catch_entry_state_maps_; + TypedData& catch_entry_moves_maps_; }; - DedupCatchEntryStateMapsVisitor visitor(Thread::Current()->zone()); + DedupCatchEntryMovesMapsVisitor visitor(Thread::Current()->zone()); ProgramVisitor::VisitFunctions(&visitor); } #endif // !defined(DART_PRECOMPILER) @@ -724,7 +724,7 @@ void ProgramVisitor::Dedup() { DedupPcDescriptors(); NOT_IN_PRECOMPILED(DedupDeoptEntries()); #if defined(DART_PRECOMPILER) - DedupCatchEntryStateMaps(); + DedupCatchEntryMovesMaps(); #endif DedupCodeSourceMaps(); DedupLists(); diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h index 4125f71512c..f2b255aa61e 100644 --- a/runtime/vm/program_visitor.h +++ b/runtime/vm/program_visitor.h @@ -35,7 +35,7 @@ class ProgramVisitor : public AllStatic { static void DedupPcDescriptors(); NOT_IN_PRECOMPILED(static void DedupDeoptEntries()); #if defined(DART_PRECOMPILER) - static void DedupCatchEntryStateMaps(); + static void DedupCatchEntryMovesMaps(); #endif static void DedupCodeSourceMaps(); static void DedupLists(); diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 57950fa716f..f8dacf3af19 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -1391,7 +1391,7 @@ class RawCode : public RawObject { RawExceptionHandlers* exception_handlers_; RawPcDescriptors* pc_descriptors_; union { - RawTypedData* catch_entry_state_maps_; + RawTypedData* catch_entry_moves_maps_; RawSmi* variables_; } catch_entry_; RawArray* stackmaps_;