| 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 |