| Index: runtime/vm/code_descriptors.cc
|
| diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
|
| index 3922ada243d4c31dda4dafc100a63254654cef72..5ab856d4469b194e862ba50bc9c5ff29e0bc3881 100644
|
| --- a/runtime/vm/code_descriptors.cc
|
| +++ b/runtime/vm/code_descriptors.cc
|
| @@ -125,6 +125,103 @@ static uint8_t* zone_allocator(uint8_t* ptr,
|
| }
|
|
|
|
|
| +class CatchEntryStateMapBuilder::TrieNode : public ZoneAllocated {
|
| + public:
|
| + TrieNode() : pair_(), entry_state_offset_(-1) {}
|
| + TrieNode(CatchEntryStatePair pair, intptr_t index)
|
| + : pair_(pair), entry_state_offset_(index) {}
|
| +
|
| + intptr_t Offset() { return entry_state_offset_; }
|
| +
|
| + TrieNode* Insert(TrieNode* node) {
|
| + children_.Add(node);
|
| + return node;
|
| + }
|
| +
|
| + TrieNode* Follow(CatchEntryStatePair next) {
|
| + for (intptr_t i = 0; i < children_.length(); i++) {
|
| + if (children_[i]->pair_ == next) return children_[i];
|
| + }
|
| + return NULL;
|
| + }
|
| +
|
| + private:
|
| + CatchEntryStatePair pair_;
|
| + const intptr_t entry_state_offset_;
|
| + GrowableArray<TrieNode*> children_;
|
| +};
|
| +
|
| +CatchEntryStateMapBuilder::CatchEntryStateMapBuilder()
|
| + : zone_(Thread::Current()->zone()),
|
| + root_(new TrieNode()),
|
| + current_pc_offset_(0),
|
| + buffer_(NULL),
|
| + stream_(&buffer_, zone_allocator, 64) {}
|
| +
|
| +
|
| +void CatchEntryStateMapBuilder::AppendMove(intptr_t src_slot,
|
| + intptr_t dest_slot) {
|
| + moves_.Add(CatchEntryStatePair::FromMove(src_slot, dest_slot));
|
| +}
|
| +
|
| +
|
| +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) {
|
| + moves_.Clear();
|
| + current_pc_offset_ = pc_offset;
|
| +}
|
| +
|
| +
|
| +void CatchEntryStateMapBuilder::EndMapping() {
|
| + intptr_t suffix_length = 0;
|
| + TrieNode* suffix = root_;
|
| + // Find the largest common suffix, get the last node of the path.
|
| + for (intptr_t i = moves_.length() - 1; i >= 0; i--) {
|
| + TrieNode* n = suffix->Follow(moves_[i]);
|
| + if (n == NULL) break;
|
| + suffix_length++;
|
| + suffix = n;
|
| + }
|
| + intptr_t length = moves_.length() - suffix_length;
|
| + intptr_t current_offset = stream_.bytes_written();
|
| +
|
| + typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
|
| + Writer::Write(&stream_, current_pc_offset_);
|
| + Writer::Write(&stream_, length);
|
| + Writer::Write(&stream_, suffix_length);
|
| + Writer::Write(&stream_, suffix->Offset());
|
| +
|
| + // 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);
|
| +
|
| + TrieNode* child = new (zone_) TrieNode(moves_[i], current_offset);
|
| + node->Insert(child);
|
| + node = child;
|
| + }
|
| +}
|
| +
|
| +
|
| +RawTypedData* CatchEntryStateMapBuilder::FinalizeCatchEntryStateMap() {
|
| + TypedData& td = TypedData::Handle(TypedData::New(
|
| + kTypedDataInt8ArrayCid, stream_.bytes_written(), Heap::kOld));
|
| + NoSafepointScope no_safepoint;
|
| + uint8_t* dest = reinterpret_cast<uint8_t*>(td.DataAddr(0));
|
| + uint8_t* src = stream_.buffer();
|
| + for (intptr_t i = 0; i < stream_.bytes_written(); i++) {
|
| + dest[i] = src[i];
|
| + }
|
| + return td.raw();
|
| +}
|
| +
|
| +
|
| const TokenPosition CodeSourceMapBuilder::kInitialPosition =
|
| TokenPosition::kDartCodePrologue;
|
|
|
|
|