// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/code_descriptors.h" #include "vm/compiler.h" namespace dart { void DescriptorList::AddDescriptor(RawPcDescriptors::Kind kind, intptr_t pc_offset, intptr_t deopt_id, intptr_t token_pos, intptr_t try_index) { ASSERT((kind == RawPcDescriptors::kRuntimeCall) || (kind == RawPcDescriptors::kOther) || (deopt_id != Thread::kNoDeoptId)); // When precompiling, we only use pc descriptors for exceptions. if (Compiler::allow_recompilation() || try_index != -1) { intptr_t merged_kind_try = RawPcDescriptors::MergedKindTry::Encode(kind, try_index); PcDescriptors::EncodeInteger(&encoded_data_, merged_kind_try); PcDescriptors::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset); PcDescriptors::EncodeInteger(&encoded_data_, deopt_id - prev_deopt_id); PcDescriptors::EncodeInteger(&encoded_data_, token_pos - prev_token_pos); prev_pc_offset = pc_offset; prev_deopt_id = deopt_id; prev_token_pos = token_pos; } } RawPcDescriptors* DescriptorList::FinalizePcDescriptors(uword entry_point) { if (encoded_data_.length() == 0) { return Object::empty_descriptors().raw(); } return PcDescriptors::New(&encoded_data_); } void CodeSourceMapBuilder::AddEntry(intptr_t pc_offset, intptr_t token_pos) { CodeSourceMap::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset); CodeSourceMap::EncodeInteger(&encoded_data_, token_pos - prev_token_pos); prev_pc_offset = pc_offset; prev_token_pos = token_pos; } RawCodeSourceMap* CodeSourceMapBuilder::Finalize() { return CodeSourceMap::New(&encoded_data_); } void StackmapTableBuilder::AddEntry(intptr_t pc_offset, BitmapBuilder* bitmap, intptr_t register_bit_count) { stack_map_ = Stackmap::New(pc_offset, bitmap, register_bit_count); list_.Add(stack_map_, Heap::kOld); } bool StackmapTableBuilder::Verify() { intptr_t num_entries = Length(); Stackmap& map1 = Stackmap::Handle(); Stackmap& map2 = Stackmap::Handle(); for (intptr_t i = 1; i < num_entries; i++) { map1 = MapAt(i - 1); map2 = MapAt(i); // Ensure there are no duplicates and the entries are sorted. if (map1.PcOffset() >= map2.PcOffset()) { return false; } } return true; } RawArray* StackmapTableBuilder::FinalizeStackmaps(const Code& code) { ASSERT(Verify()); intptr_t num_entries = Length(); if (num_entries == 0) { return Object::empty_array().raw(); } return Array::MakeArray(list_); } RawStackmap* StackmapTableBuilder::MapAt(intptr_t index) const { Stackmap& map = Stackmap::Handle(); map ^= list_.At(index); return map.raw(); } RawExceptionHandlers* ExceptionHandlerList::FinalizeExceptionHandlers( uword entry_point) const { intptr_t num_handlers = Length(); if (num_handlers == 0) { return Object::empty_exception_handlers().raw(); } const ExceptionHandlers& handlers = ExceptionHandlers::Handle(ExceptionHandlers::New(num_handlers)); for (intptr_t i = 0; i < num_handlers; i++) { // Assert that every element in the array has been initialized. if (list_[i].handler_types == NULL) { // Unreachable handler, entry not computed. // Initialize it to some meaningful value. const bool has_catch_all = false; // Check it is uninitialized. ASSERT((list_[i].outer_try_index == -1) && (list_[i].pc_offset == ExceptionHandlers::kInvalidPcOffset)); handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset, list_[i].needs_stacktrace, has_catch_all); handlers.SetHandledTypes(i, Array::null_array()); } else { const bool has_catch_all = ContainsDynamic(*list_[i].handler_types); handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset, list_[i].needs_stacktrace, has_catch_all); handlers.SetHandledTypes(i, *list_[i].handler_types); } } return handlers.raw(); } } // namespace dart