OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/object.h" | 5 #include "vm/object.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/become.h" | 10 #include "vm/become.h" |
(...skipping 12078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12089 deopt_ids->Add(iter.DeoptId()); | 12089 deopt_ids->Add(iter.DeoptId()); |
12090 } else { | 12090 } else { |
12091 ASSERT(!iccall_ids->Contains(iter.DeoptId())); | 12091 ASSERT(!iccall_ids->Contains(iter.DeoptId())); |
12092 iccall_ids->Add(iter.DeoptId()); | 12092 iccall_ids->Add(iter.DeoptId()); |
12093 } | 12093 } |
12094 } | 12094 } |
12095 #endif // DEBUG | 12095 #endif // DEBUG |
12096 } | 12096 } |
12097 | 12097 |
12098 | 12098 |
12099 TokenPosition CodeSourceMap::TokenPositionForPCOffset(uword pc_offset) const { | |
12100 Iterator iterator(*this); | |
12101 | |
12102 TokenPosition result = TokenPosition::kNoSource; | |
12103 | |
12104 while (iterator.MoveNext()) { | |
12105 if (iterator.PcOffset() > pc_offset) { | |
12106 break; | |
12107 } | |
12108 result = iterator.TokenPos(); | |
12109 } | |
12110 | |
12111 return result; | |
12112 } | |
12113 | |
12114 | |
12115 RawFunction* CodeSourceMap::FunctionForPCOffset(const Code& code, | |
12116 const Function& function, | |
12117 uword pc_offset) const { | |
12118 GrowableArray<Function*> inlined_functions; | |
12119 code.GetInlinedFunctionsAt(pc_offset, &inlined_functions); | |
12120 if (inlined_functions.length() > 0) { | |
12121 Function* inlined_function = inlined_functions[0]; | |
12122 return inlined_function->raw(); | |
12123 } else { | |
12124 return function.raw(); | |
12125 } | |
12126 } | |
12127 | |
12128 | |
12129 RawScript* CodeSourceMap::ScriptForPCOffset(const Code& code, | |
12130 const Function& function, | |
12131 uword pc_offset) const { | |
12132 const Function& func = | |
12133 Function::Handle(FunctionForPCOffset(code, function, pc_offset)); | |
12134 return func.script(); | |
12135 } | |
12136 | |
12137 | |
12138 void CodeSourceMap::Dump(const CodeSourceMap& code_source_map, | |
12139 const Code& code, | |
12140 const Function& function) { | |
12141 const char* code_name = code.QualifiedName(); | |
12142 THR_Print("Dumping Code Source Map for %s\n", code_name); | |
12143 if (code_source_map.Length() == 0) { | |
12144 THR_Print("<empty>\n"); | |
12145 return; | |
12146 } | |
12147 | |
12148 const int addr_width = kBitsPerWord / 4; | |
12149 | |
12150 Iterator iterator(code_source_map); | |
12151 Function& current_function = Function::Handle(); | |
12152 Script& current_script = Script::Handle(); | |
12153 TokenPosition tp; | |
12154 while (iterator.MoveNext()) { | |
12155 const uword pc_offset = iterator.PcOffset(); | |
12156 tp = code_source_map.TokenPositionForPCOffset(pc_offset); | |
12157 current_function ^= | |
12158 code_source_map.FunctionForPCOffset(code, function, pc_offset); | |
12159 current_script ^= | |
12160 code_source_map.ScriptForPCOffset(code, function, pc_offset); | |
12161 if (current_function.IsNull() || current_script.IsNull()) { | |
12162 THR_Print("%#-*" Px "\t%s\t%s\n", addr_width, pc_offset, tp.ToCString(), | |
12163 code_name); | |
12164 continue; | |
12165 } | |
12166 const String& uri = String::Handle(current_script.url()); | |
12167 ASSERT(!uri.IsNull()); | |
12168 THR_Print("%#-*" Px "\t%s\t%s\t%s\n", addr_width, pc_offset, tp.ToCString(), | |
12169 current_function.ToQualifiedCString(), uri.ToCString()); | |
12170 } | |
12171 } | |
12172 | |
12173 | |
12174 intptr_t CodeSourceMap::Length() const { | |
12175 return raw_ptr()->length_; | |
12176 } | |
12177 | |
12178 | |
12179 void CodeSourceMap::SetLength(intptr_t value) const { | 12099 void CodeSourceMap::SetLength(intptr_t value) const { |
12180 StoreNonPointer(&raw_ptr()->length_, value); | 12100 StoreNonPointer(&raw_ptr()->length_, value); |
12181 } | 12101 } |
12182 | 12102 |
12183 | 12103 |
12184 void CodeSourceMap::CopyData(GrowableArray<uint8_t>* delta_encoded_data) { | |
12185 NoSafepointScope no_safepoint; | |
12186 uint8_t* data = UnsafeMutableNonPointer(&raw_ptr()->data()[0]); | |
12187 for (intptr_t i = 0; i < delta_encoded_data->length(); ++i) { | |
12188 data[i] = (*delta_encoded_data)[i]; | |
12189 } | |
12190 } | |
12191 | |
12192 | |
12193 RawCodeSourceMap* CodeSourceMap::New(GrowableArray<uint8_t>* data) { | |
12194 ASSERT(Object::code_source_map_class() != Class::null()); | |
12195 Thread* thread = Thread::Current(); | |
12196 CodeSourceMap& result = CodeSourceMap::Handle(thread->zone()); | |
12197 { | |
12198 uword size = CodeSourceMap::InstanceSize(data->length()); | |
12199 RawObject* raw = | |
12200 Object::Allocate(CodeSourceMap::kClassId, size, Heap::kOld); | |
12201 NoSafepointScope no_safepoint; | |
12202 result ^= raw; | |
12203 result.SetLength(data->length()); | |
12204 result.CopyData(data); | |
12205 } | |
12206 return result.raw(); | |
12207 } | |
12208 | |
12209 | |
12210 RawCodeSourceMap* CodeSourceMap::New(intptr_t length) { | 12104 RawCodeSourceMap* CodeSourceMap::New(intptr_t length) { |
12211 ASSERT(Object::code_source_map_class() != Class::null()); | 12105 ASSERT(Object::code_source_map_class() != Class::null()); |
12212 Thread* thread = Thread::Current(); | 12106 Thread* thread = Thread::Current(); |
12213 CodeSourceMap& result = CodeSourceMap::Handle(thread->zone()); | 12107 CodeSourceMap& result = CodeSourceMap::Handle(thread->zone()); |
12214 { | 12108 { |
12215 uword size = CodeSourceMap::InstanceSize(length); | 12109 uword size = CodeSourceMap::InstanceSize(length); |
12216 RawObject* raw = | 12110 RawObject* raw = |
12217 Object::Allocate(CodeSourceMap::kClassId, size, Heap::kOld); | 12111 Object::Allocate(CodeSourceMap::kClassId, size, Heap::kOld); |
12218 NoSafepointScope no_safepoint; | 12112 NoSafepointScope no_safepoint; |
12219 result ^= raw; | 12113 result ^= raw; |
12220 result.SetLength(length); | 12114 result.SetLength(length); |
12221 } | 12115 } |
12222 return result.raw(); | 12116 return result.raw(); |
12223 } | 12117 } |
12224 | 12118 |
12225 | 12119 |
12226 const char* CodeSourceMap::ToCString() const { | 12120 const char* CodeSourceMap::ToCString() const { |
12227 // "*" in a printf format specifier tells it to read the field width from | 12121 return "CodeSourceMap"; |
12228 // the printf argument list. | |
12229 #define FORMAT "%#-*" Px "\t%s\n" | |
12230 if (Length() == 0) { | |
12231 return "empty CodeSourceMap\n"; | |
12232 } | |
12233 // 4 bits per hex digit. | |
12234 const int addr_width = kBitsPerWord / 4; | |
12235 // First compute the buffer size required. | |
12236 intptr_t len = 1; // Trailing '\0'. | |
12237 { | |
12238 Iterator iter(*this); | |
12239 while (iter.MoveNext()) { | |
12240 len += OS::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(), | |
12241 iter.TokenPos().ToCString()); | |
12242 } | |
12243 } | |
12244 // Allocate the buffer. | |
12245 char* buffer = Thread::Current()->zone()->Alloc<char>(len); | |
12246 // Layout the fields in the buffer. | |
12247 intptr_t index = 0; | |
12248 Iterator iter(*this); | |
12249 while (iter.MoveNext()) { | |
12250 index += OS::SNPrint((buffer + index), (len - index), FORMAT, addr_width, | |
12251 iter.PcOffset(), iter.TokenPos().ToCString()); | |
12252 } | |
12253 return buffer; | |
12254 #undef FORMAT | |
12255 } | 12122 } |
12256 | 12123 |
12257 | 12124 |
12258 // Encode integer in SLEB128 format. | |
12259 void CodeSourceMap::EncodeInteger(GrowableArray<uint8_t>* data, | |
12260 intptr_t value) { | |
12261 return EncodeSLEB128(data, value); | |
12262 } | |
12263 | |
12264 | |
12265 // Decode SLEB128 encoded integer. Update byte_index to the next integer. | |
12266 intptr_t CodeSourceMap::DecodeInteger(intptr_t* byte_index) const { | |
12267 NoSafepointScope no_safepoint; | |
12268 const uint8_t* data = raw_ptr()->data(); | |
12269 return DecodeSLEB128(data, Length(), byte_index); | |
12270 } | |
12271 | |
12272 | |
12273 bool StackMap::GetBit(intptr_t bit_index) const { | 12125 bool StackMap::GetBit(intptr_t bit_index) const { |
12274 ASSERT(InRange(bit_index)); | 12126 ASSERT(InRange(bit_index)); |
12275 int byte_index = bit_index >> kBitsPerByteLog2; | 12127 int byte_index = bit_index >> kBitsPerByteLog2; |
12276 int bit_remainder = bit_index & (kBitsPerByte - 1); | 12128 int bit_remainder = bit_index & (kBitsPerByte - 1); |
12277 uint8_t byte_mask = 1U << bit_remainder; | 12129 uint8_t byte_mask = 1U << bit_remainder; |
12278 uint8_t byte = raw_ptr()->data()[byte_index]; | 12130 uint8_t byte = raw_ptr()->data()[byte_index]; |
12279 return (byte & byte_mask); | 12131 return (byte & byte_mask); |
12280 } | 12132 } |
12281 | 12133 |
12282 | 12134 |
(...skipping 1757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14040 | 13892 |
14041 | 13893 |
14042 bool Code::HasBreakpoint() const { | 13894 bool Code::HasBreakpoint() const { |
14043 if (!FLAG_support_debugger) { | 13895 if (!FLAG_support_debugger) { |
14044 return false; | 13896 return false; |
14045 } | 13897 } |
14046 return Isolate::Current()->debugger()->HasBreakpoint(*this); | 13898 return Isolate::Current()->debugger()->HasBreakpoint(*this); |
14047 } | 13899 } |
14048 | 13900 |
14049 | 13901 |
14050 TokenPosition Code::GetTokenPositionAt(intptr_t offset) const { | |
14051 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); | |
14052 if (map.IsNull()) { | |
14053 return TokenPosition::kNoSource; | |
14054 } | |
14055 return map.TokenPositionForPCOffset(offset); | |
14056 } | |
14057 | |
14058 | |
14059 RawTypedData* Code::GetDeoptInfoAtPc(uword pc, | 13902 RawTypedData* Code::GetDeoptInfoAtPc(uword pc, |
14060 ICData::DeoptReasonId* deopt_reason, | 13903 ICData::DeoptReasonId* deopt_reason, |
14061 uint32_t* deopt_flags) const { | 13904 uint32_t* deopt_flags) const { |
14062 ASSERT(is_optimized()); | 13905 ASSERT(is_optimized()); |
14063 const Instructions& instrs = Instructions::Handle(instructions()); | 13906 const Instructions& instrs = Instructions::Handle(instructions()); |
14064 uword code_entry = instrs.PayloadStart(); | 13907 uword code_entry = instrs.PayloadStart(); |
14065 const Array& table = Array::Handle(deopt_info_array()); | 13908 const Array& table = Array::Handle(deopt_info_array()); |
14066 if (table.IsNull()) { | 13909 if (table.IsNull()) { |
14067 ASSERT(Dart::vm_snapshot_kind() == Snapshot::kAppAOT); | 13910 ASSERT(Dart::vm_snapshot_kind() == Snapshot::kAppAOT); |
14068 return TypedData::null(); | 13911 return TypedData::null(); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14236 // In the future we may put something other than a smi in | 14079 // In the future we may put something other than a smi in |
14237 // |return_address_metadata_|. | 14080 // |return_address_metadata_|. |
14238 if (object.IsNull() || !object.IsSmi()) { | 14081 if (object.IsNull() || !object.IsSmi()) { |
14239 return -1; | 14082 return -1; |
14240 } | 14083 } |
14241 return Smi::Cast(object).Value(); | 14084 return Smi::Cast(object).Value(); |
14242 #endif | 14085 #endif |
14243 } | 14086 } |
14244 | 14087 |
14245 | 14088 |
14246 RawArray* Code::GetInlinedIntervals() const { | 14089 RawArray* Code::inlined_id_to_function() const { |
14247 #if defined(DART_PRECOMPILED_RUNTIME) | 14090 #if defined(DART_PRECOMPILED_RUNTIME) |
14248 return Array::null(); | 14091 return Array::null(); |
14249 #else | 14092 #else |
14250 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | 14093 return raw_ptr()->inlined_id_to_function_; |
14251 if (metadata.IsNull()) { | |
14252 return metadata.raw(); | |
14253 } | |
14254 return reinterpret_cast<RawArray*>( | |
14255 metadata.At(RawCode::kInlinedIntervalsIndex)); | |
14256 #endif | 14094 #endif |
14257 } | 14095 } |
14258 | 14096 |
14259 | 14097 |
14260 void Code::SetInlinedIntervals(const Array& value) const { | 14098 void Code::set_inlined_id_to_function(const Array& value) const { |
14261 #if defined(DART_PRECOMPILED_RUNTIME) | 14099 #if defined(DART_PRECOMPILED_RUNTIME) |
14262 UNREACHABLE(); | 14100 UNREACHABLE(); |
14263 #else | 14101 #else |
14264 if (raw_ptr()->inlined_metadata_ == Array::null()) { | |
14265 StorePointer(&raw_ptr()->inlined_metadata_, | |
14266 Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); | |
14267 } | |
14268 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | |
14269 ASSERT(!metadata.IsNull()); | |
14270 ASSERT(metadata.IsOld()); | |
14271 ASSERT(value.IsOld()); | 14102 ASSERT(value.IsOld()); |
14272 metadata.SetAt(RawCode::kInlinedIntervalsIndex, value); | 14103 StorePointer(&raw_ptr()->inlined_id_to_function_, value.raw()); |
14273 #endif | 14104 #endif |
14274 } | 14105 } |
14275 | 14106 |
14276 | |
14277 RawArray* Code::GetInlinedIdToFunction() const { | |
14278 #if defined(DART_PRECOMPILED_RUNTIME) | |
14279 return Array::null(); | |
14280 #else | |
14281 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | |
14282 if (metadata.IsNull()) { | |
14283 return metadata.raw(); | |
14284 } | |
14285 return reinterpret_cast<RawArray*>( | |
14286 metadata.At(RawCode::kInlinedIdToFunctionIndex)); | |
14287 #endif | |
14288 } | |
14289 | |
14290 | |
14291 void Code::SetInlinedIdToFunction(const Array& value) const { | |
14292 #if defined(DART_PRECOMPILED_RUNTIME) | |
14293 UNREACHABLE(); | |
14294 #else | |
14295 if (raw_ptr()->inlined_metadata_ == Array::null()) { | |
14296 StorePointer(&raw_ptr()->inlined_metadata_, | |
14297 Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); | |
14298 } | |
14299 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | |
14300 ASSERT(!metadata.IsNull()); | |
14301 ASSERT(metadata.IsOld()); | |
14302 ASSERT(value.IsOld()); | |
14303 metadata.SetAt(RawCode::kInlinedIdToFunctionIndex, value); | |
14304 #endif | |
14305 } | |
14306 | |
14307 | |
14308 RawArray* Code::GetInlinedIdToTokenPos() const { | |
14309 #if defined(DART_PRECOMPILED_RUNTIME) | |
14310 return Array::null(); | |
14311 #else | |
14312 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | |
14313 if (metadata.IsNull()) { | |
14314 return metadata.raw(); | |
14315 } | |
14316 return reinterpret_cast<RawArray*>( | |
14317 metadata.At(RawCode::kInlinedIdToTokenPosIndex)); | |
14318 #endif | |
14319 } | |
14320 | |
14321 | |
14322 void Code::SetInlinedIdToTokenPos(const Array& value) const { | |
14323 #if defined(DART_PRECOMPILED_RUNTIME) | |
14324 UNREACHABLE(); | |
14325 #else | |
14326 if (raw_ptr()->inlined_metadata_ == Array::null()) { | |
14327 StorePointer(&raw_ptr()->inlined_metadata_, | |
14328 Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); | |
14329 } | |
14330 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | |
14331 ASSERT(!metadata.IsNull()); | |
14332 ASSERT(metadata.IsOld()); | |
14333 ASSERT(value.IsOld()); | |
14334 metadata.SetAt(RawCode::kInlinedIdToTokenPosIndex, value); | |
14335 #endif | |
14336 } | |
14337 | |
14338 | |
14339 RawArray* Code::GetInlinedCallerIdMap() const { | |
14340 #if defined(DART_PRECOMPILED_RUNTIME) | |
14341 return Array::null(); | |
14342 #else | |
14343 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | |
14344 if (metadata.IsNull()) { | |
14345 return metadata.raw(); | |
14346 } | |
14347 return reinterpret_cast<RawArray*>( | |
14348 metadata.At(RawCode::kInlinedCallerIdMapIndex)); | |
14349 #endif | |
14350 } | |
14351 | |
14352 | |
14353 void Code::SetInlinedCallerIdMap(const Array& value) const { | |
14354 #if defined(DART_PRECOMPILED_RUNTIME) | |
14355 UNREACHABLE(); | |
14356 #else | |
14357 if (raw_ptr()->inlined_metadata_ == Array::null()) { | |
14358 StorePointer(&raw_ptr()->inlined_metadata_, | |
14359 Array::New(RawCode::kInlinedMetadataSize, Heap::kOld)); | |
14360 } | |
14361 const Array& metadata = Array::Handle(raw_ptr()->inlined_metadata_); | |
14362 ASSERT(!metadata.IsNull()); | |
14363 ASSERT(metadata.IsOld()); | |
14364 ASSERT(value.IsOld()); | |
14365 metadata.SetAt(RawCode::kInlinedCallerIdMapIndex, value); | |
14366 #endif | |
14367 } | |
14368 | |
14369 | 14107 |
14370 RawCode* Code::New(intptr_t pointer_offsets_length) { | 14108 RawCode* Code::New(intptr_t pointer_offsets_length) { |
14371 if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) { | 14109 if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) { |
14372 // This should be caught before we reach here. | 14110 // This should be caught before we reach here. |
14373 FATAL1("Fatal error in Code::New: invalid pointer_offsets_length %" Pd "\n", | 14111 FATAL1("Fatal error in Code::New: invalid pointer_offsets_length %" Pd "\n", |
14374 pointer_offsets_length); | 14112 pointer_offsets_length); |
14375 } | 14113 } |
14376 ASSERT(Object::code_class() != Class::null()); | 14114 ASSERT(Object::code_class() != Class::null()); |
14377 Code& result = Code::Handle(); | 14115 Code& result = Code::Handle(); |
14378 { | 14116 { |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14715 // If we are missing a stack map, this must either be unoptimized code, or | 14453 // If we are missing a stack map, this must either be unoptimized code, or |
14716 // the entry to an osr function. (In which case all stack slots are | 14454 // the entry to an osr function. (In which case all stack slots are |
14717 // considered to have tagged pointers.) | 14455 // considered to have tagged pointers.) |
14718 // Running with --verify-on-transition should hit this. | 14456 // Running with --verify-on-transition should hit this. |
14719 ASSERT(!is_optimized() || | 14457 ASSERT(!is_optimized() || |
14720 (pc_offset == UncheckedEntryPoint() - PayloadStart())); | 14458 (pc_offset == UncheckedEntryPoint() - PayloadStart())); |
14721 return StackMap::null(); | 14459 return StackMap::null(); |
14722 } | 14460 } |
14723 | 14461 |
14724 | 14462 |
14725 intptr_t Code::GetCallerId(intptr_t inlined_id) const { | |
14726 if (inlined_id < 0) { | |
14727 return -1; | |
14728 } | |
14729 const Array& map = Array::Handle(GetInlinedCallerIdMap()); | |
14730 if (map.IsNull() || (map.Length() == 0)) { | |
14731 return -1; | |
14732 } | |
14733 Smi& smi = Smi::Handle(); | |
14734 smi ^= map.At(inlined_id); | |
14735 return smi.Value(); | |
14736 } | |
14737 | |
14738 | |
14739 void Code::GetInlinedFunctionsAt( | 14463 void Code::GetInlinedFunctionsAt( |
14740 intptr_t offset, | 14464 intptr_t pc_offset, |
14741 GrowableArray<Function*>* fs, | 14465 GrowableArray<const Function*>* functions, |
14742 GrowableArray<TokenPosition>* token_positions) const { | 14466 GrowableArray<TokenPosition>* token_positions) const { |
14743 fs->Clear(); | 14467 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
14744 if (token_positions != NULL) { | 14468 if (map.IsNull()) { |
14745 token_positions->Clear(); | 14469 // Stub code. |
14746 } | |
14747 const Array& intervals = Array::Handle(GetInlinedIntervals()); | |
14748 if (intervals.IsNull() || (intervals.Length() == 0)) { | |
14749 // E.g., for code stubs. | |
14750 return; | 14470 return; |
14751 } | 14471 } |
14752 // First find the right interval. TODO(srdjan): use binary search since | 14472 const Array& id_map = Array::Handle(inlined_id_to_function()); |
14753 // intervals are sorted. | 14473 const Function& root = Function::Handle(function()); |
14754 Smi& start = Smi::Handle(); | 14474 CodeSourceMapReader reader(map, id_map, root); |
14755 Smi& end = Smi::Handle(); | 14475 reader.GetInlinedFunctionsAt(pc_offset, functions, token_positions); |
14756 intptr_t found_interval_ix = intervals.Length() - Code::kInlIntNumEntries; | |
14757 for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries; | |
14758 i += Code::kInlIntNumEntries) { | |
14759 start ^= intervals.At(i + Code::kInlIntStart); | |
14760 if (!start.IsNull()) { | |
14761 end ^= intervals.At(i + Code::kInlIntNumEntries + Code::kInlIntStart); | |
14762 if ((start.Value() <= offset) && (offset < end.Value())) { | |
14763 found_interval_ix = i; | |
14764 break; | |
14765 } | |
14766 } | |
14767 } | |
14768 | |
14769 // Find all functions. | |
14770 const Array& id_map = Array::Handle(GetInlinedIdToFunction()); | |
14771 const Array& token_pos_map = Array::Handle(GetInlinedIdToTokenPos()); | |
14772 Smi& temp_smi = Smi::Handle(); | |
14773 temp_smi ^= intervals.At(found_interval_ix + Code::kInlIntInliningId); | |
14774 intptr_t inlining_id = temp_smi.Value(); | |
14775 ASSERT(inlining_id >= 0); | |
14776 intptr_t caller_id = GetCallerId(inlining_id); | |
14777 while (inlining_id >= 0) { | |
14778 Function& function = Function::ZoneHandle(); | |
14779 function ^= id_map.At(inlining_id); | |
14780 fs->Add(&function); | |
14781 if ((token_positions != NULL) && (inlining_id < token_pos_map.Length())) { | |
14782 temp_smi ^= token_pos_map.At(inlining_id); | |
14783 token_positions->Add(TokenPosition(temp_smi.Value())); | |
14784 } | |
14785 inlining_id = caller_id; | |
14786 caller_id = GetCallerId(inlining_id); | |
14787 } | |
14788 } | 14476 } |
14789 | 14477 |
14790 | 14478 |
14791 void Code::DumpInlinedIntervals() const { | 14479 #ifndef PRODUCT |
14792 LogBlock lb; | 14480 void Code::PrintJSONInlineIntervals(JSONObject* jsobj) const { |
14793 THR_Print("Inlined intervals:\n"); | 14481 if (!is_optimized()) { |
14794 const Array& intervals = Array::Handle(GetInlinedIntervals()); | 14482 return; // No inlining. |
14795 if (intervals.IsNull() || (intervals.Length() == 0)) return; | 14483 } |
14796 Smi& start = Smi::Handle(); | 14484 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
14797 Smi& inlining_id = Smi::Handle(); | 14485 const Array& id_map = Array::Handle(inlined_id_to_function()); |
14798 GrowableArray<Function*> inlined_functions; | 14486 const Function& root = Function::Handle(function()); |
14799 const Function& inliner = Function::Handle(function()); | 14487 CodeSourceMapReader reader(map, id_map, root); |
14800 for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) { | 14488 reader.PrintJSONInlineIntervals(jsobj); |
14801 start ^= intervals.At(i + Code::kInlIntStart); | 14489 } |
14802 ASSERT(!start.IsNull()); | 14490 #endif |
14803 if (start.IsNull()) continue; | |
14804 inlining_id ^= intervals.At(i + Code::kInlIntInliningId); | |
14805 THR_Print(" %" Px " iid: %" Pd " ; ", start.Value(), inlining_id.Value()); | |
14806 inlined_functions.Clear(); | |
14807 | 14491 |
14808 THR_Print("inlined: "); | |
14809 GetInlinedFunctionsAt(start.Value(), &inlined_functions); | |
14810 | 14492 |
14811 for (intptr_t j = 0; j < inlined_functions.length(); j++) { | 14493 void Code::DumpInlineIntervals() const { |
14812 const char* name = inlined_functions[j]->ToQualifiedCString(); | 14494 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
14813 THR_Print(" %s <-", name); | 14495 if (map.IsNull()) { |
14814 } | 14496 // Stub code. |
14815 if (inlined_functions[inlined_functions.length() - 1]->raw() != | 14497 return; |
14816 inliner.raw()) { | |
14817 THR_Print(" (ERROR, missing inliner)\n"); | |
14818 } else { | |
14819 THR_Print("\n"); | |
14820 } | |
14821 } | 14498 } |
14822 THR_Print("Inlined ids:\n"); | 14499 const Array& id_map = Array::Handle(inlined_id_to_function()); |
14823 const Array& id_map = Array::Handle(GetInlinedIdToFunction()); | 14500 const Function& root = Function::Handle(function()); |
14824 Function& function = Function::Handle(); | 14501 CodeSourceMapReader reader(map, id_map, root); |
14825 for (intptr_t i = 0; i < id_map.Length(); i++) { | 14502 reader.DumpInlineIntervals(PayloadStart()); |
14826 function ^= id_map.At(i); | |
14827 if (!function.IsNull()) { | |
14828 THR_Print(" %" Pd ": %s\n", i, function.ToQualifiedCString()); | |
14829 } | |
14830 } | |
14831 THR_Print("Inlined token pos:\n"); | |
14832 const Array& token_pos_map = Array::Handle(GetInlinedIdToTokenPos()); | |
14833 Smi& smi = Smi::Handle(); | |
14834 for (intptr_t i = 0; i < token_pos_map.Length(); i++) { | |
14835 smi ^= token_pos_map.At(i); | |
14836 TokenPosition tp = TokenPosition(smi.Value()); | |
14837 THR_Print(" %" Pd ": %s\n", i, tp.ToCString()); | |
14838 } | |
14839 THR_Print("Caller Inlining Ids:\n"); | |
14840 const Array& caller_map = Array::Handle(GetInlinedCallerIdMap()); | |
14841 for (intptr_t i = 0; i < caller_map.Length(); i++) { | |
14842 smi ^= caller_map.At(i); | |
14843 THR_Print(" iid: %" Pd " caller iid: %" Pd "\n", i, smi.Value()); | |
14844 } | |
14845 } | 14503 } |
14846 | 14504 |
14847 | 14505 |
| 14506 void Code::DumpSourcePositions() const { |
| 14507 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
| 14508 if (map.IsNull()) { |
| 14509 // Stub code. |
| 14510 return; |
| 14511 } |
| 14512 const Array& id_map = Array::Handle(inlined_id_to_function()); |
| 14513 const Function& root = Function::Handle(function()); |
| 14514 CodeSourceMapReader reader(map, id_map, root); |
| 14515 reader.DumpSourcePositions(PayloadStart()); |
| 14516 } |
| 14517 |
| 14518 |
14848 RawContext* Context::New(intptr_t num_variables, Heap::Space space) { | 14519 RawContext* Context::New(intptr_t num_variables, Heap::Space space) { |
14849 ASSERT(num_variables >= 0); | 14520 ASSERT(num_variables >= 0); |
14850 ASSERT(Object::context_class() != Class::null()); | 14521 ASSERT(Object::context_class() != Class::null()); |
14851 | 14522 |
14852 if (num_variables < 0 || num_variables > kMaxElements) { | 14523 if (num_variables < 0 || num_variables > kMaxElements) { |
14853 // This should be caught before we reach here. | 14524 // This should be caught before we reach here. |
14854 FATAL1("Fatal error in Context::New: invalid num_variables %" Pd "\n", | 14525 FATAL1("Fatal error in Context::New: invalid num_variables %" Pd "\n", |
14855 num_variables); | 14526 num_variables); |
14856 } | 14527 } |
14857 Context& result = Context::Handle(); | 14528 Context& result = Context::Handle(); |
(...skipping 8230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
23088 return UserTag::null(); | 22759 return UserTag::null(); |
23089 } | 22760 } |
23090 | 22761 |
23091 | 22762 |
23092 const char* UserTag::ToCString() const { | 22763 const char* UserTag::ToCString() const { |
23093 const String& tag_label = String::Handle(label()); | 22764 const String& tag_label = String::Handle(label()); |
23094 return tag_label.ToCString(); | 22765 return tag_label.ToCString(); |
23095 } | 22766 } |
23096 | 22767 |
23097 } // namespace dart | 22768 } // namespace dart |
OLD | NEW |