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/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 10177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10188 size, | 10188 size, |
10189 Heap::kOld); | 10189 Heap::kOld); |
10190 NoGCScope no_gc; | 10190 NoGCScope no_gc; |
10191 result ^= raw; | 10191 result ^= raw; |
10192 result.SetLength(num_descriptors); | 10192 result.SetLength(num_descriptors); |
10193 } | 10193 } |
10194 return result.raw(); | 10194 return result.raw(); |
10195 } | 10195 } |
10196 | 10196 |
10197 | 10197 |
10198 const char* PcDescriptors::KindAsStr(intptr_t index) const { | 10198 const char* PcDescriptors::KindAsStr(RawPcDescriptors::Kind kind) { |
10199 switch (DescriptorKind(index)) { | 10199 switch (kind) { |
10200 case PcDescriptors::kDeopt: return "deopt "; | 10200 case RawPcDescriptors::kDeopt: return "deopt "; |
10201 case PcDescriptors::kIcCall: return "ic-call "; | 10201 case RawPcDescriptors::kIcCall: return "ic-call "; |
10202 case PcDescriptors::kOptStaticCall: return "opt-call "; | 10202 case RawPcDescriptors::kOptStaticCall: return "opt-call "; |
10203 case PcDescriptors::kUnoptStaticCall: return "unopt-call "; | 10203 case RawPcDescriptors::kUnoptStaticCall: return "unopt-call "; |
10204 case PcDescriptors::kClosureCall: return "closure-call "; | 10204 case RawPcDescriptors::kClosureCall: return "closure-call "; |
10205 case PcDescriptors::kRuntimeCall: return "runtime-call "; | 10205 case RawPcDescriptors::kRuntimeCall: return "runtime-call "; |
10206 case PcDescriptors::kOsrEntry: return "osr-entry "; | 10206 case RawPcDescriptors::kOsrEntry: return "osr-entry "; |
10207 case PcDescriptors::kOther: return "other "; | 10207 case RawPcDescriptors::kOther: return "other "; |
10208 } | 10208 } |
10209 UNREACHABLE(); | 10209 UNREACHABLE(); |
10210 return ""; | 10210 return ""; |
10211 } | 10211 } |
10212 | 10212 |
10213 | 10213 |
10214 void PcDescriptors::PrintHeaderString() { | 10214 void PcDescriptors::PrintHeaderString() { |
10215 // 4 bits per hex digit + 2 for "0x". | 10215 // 4 bits per hex digit + 2 for "0x". |
10216 const int addr_width = (kBitsPerWord / 4) + 2; | 10216 const int addr_width = (kBitsPerWord / 4) + 2; |
10217 // "*" in a printf format specifier tells it to read the field width from | 10217 // "*" in a printf format specifier tells it to read the field width from |
10218 // the printf argument list. | 10218 // the printf argument list. |
10219 OS::Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\n", | 10219 OS::Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\n", |
10220 addr_width, "pc"); | 10220 addr_width, "pc"); |
10221 } | 10221 } |
10222 | 10222 |
10223 | 10223 |
10224 const char* PcDescriptors::ToCString() const { | 10224 const char* PcDescriptors::ToCString() const { |
10225 if (Length() == 0) { | 10225 if (Length() == 0) { |
10226 return "No pc descriptors\n"; | 10226 return "No pc descriptors\n"; |
10227 } | 10227 } |
10228 // 4 bits per hex digit. | 10228 // 4 bits per hex digit. |
10229 const int addr_width = kBitsPerWord / 4; | 10229 const int addr_width = kBitsPerWord / 4; |
10230 // "*" in a printf format specifier tells it to read the field width from | 10230 // "*" in a printf format specifier tells it to read the field width from |
10231 // the printf argument list. | 10231 // the printf argument list. |
10232 const char* kFormat = | 10232 const char* kFormat = |
10233 "%#-*" Px "\t%s\t%" Pd "\t\t%" Pd "\t%" Pd "\n"; | 10233 "%#-*" Px "\t%s\t%" Pd "\t\t%" Pd "\t%" Pd "\n"; |
10234 // First compute the buffer size required. | 10234 // First compute the buffer size required. |
10235 intptr_t len = 1; // Trailing '\0'. | 10235 intptr_t len = 1; // Trailing '\0'. |
10236 for (intptr_t i = 0; i < Length(); i++) { | 10236 Iterator iter(*this); |
| 10237 while (iter.HasNext()) { |
| 10238 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
10237 len += OS::SNPrint(NULL, 0, kFormat, addr_width, | 10239 len += OS::SNPrint(NULL, 0, kFormat, addr_width, |
10238 PC(i), | 10240 rec.pc, |
10239 KindAsStr(i), | 10241 KindAsStr(rec.kind()), |
10240 DeoptId(i), | 10242 rec.deopt_id, |
10241 TokenPos(i), | 10243 rec.token_pos, |
10242 TryIndex(i)); | 10244 rec.try_index); |
10243 } | 10245 } |
10244 // Allocate the buffer. | 10246 // Allocate the buffer. |
10245 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len); | 10247 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len); |
10246 // Layout the fields in the buffer. | 10248 // Layout the fields in the buffer. |
10247 intptr_t index = 0; | 10249 intptr_t index = 0; |
10248 for (intptr_t i = 0; i < Length(); i++) { | 10250 Iterator iter2(*this); |
| 10251 while (iter2.HasNext()) { |
| 10252 const RawPcDescriptors::PcDescriptorRec& rec = iter2.Next(); |
10249 index += OS::SNPrint((buffer + index), (len - index), kFormat, addr_width, | 10253 index += OS::SNPrint((buffer + index), (len - index), kFormat, addr_width, |
10250 PC(i), | 10254 rec.pc, |
10251 KindAsStr(i), | 10255 KindAsStr(rec.kind()), |
10252 DeoptId(i), | 10256 rec.deopt_id, |
10253 TokenPos(i), | 10257 rec.token_pos, |
10254 TryIndex(i)); | 10258 rec.try_index); |
10255 } | 10259 } |
10256 return buffer; | 10260 return buffer; |
10257 } | 10261 } |
10258 | 10262 |
10259 | 10263 |
10260 void PcDescriptors::PrintToJSONObject(JSONObject* jsobj) const { | 10264 void PcDescriptors::PrintToJSONObject(JSONObject* jsobj) const { |
10261 jsobj->AddProperty("type", JSONType(false)); | 10265 jsobj->AddProperty("type", JSONType(false)); |
10262 // TODO(johnmccutchan): Generate a valid ID. | 10266 // TODO(johnmccutchan): Generate a valid ID. |
10263 // PcDescriptors hang off a Code object but do not have a back reference to | 10267 // PcDescriptors hang off a Code object but do not have a back reference to |
10264 // generate an ID. Currently we only print PcDescriptors inline with a Code. | 10268 // generate an ID. Currently we only print PcDescriptors inline with a Code. |
10265 jsobj->AddProperty("id", ""); | 10269 jsobj->AddProperty("id", ""); |
10266 JSONArray members(jsobj, "members"); | 10270 JSONArray members(jsobj, "members"); |
10267 for (intptr_t i = 0; i < Length(); i++) { | 10271 Iterator iter(*this); |
| 10272 while (iter.HasNext()) { |
| 10273 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
10268 JSONObject descriptor(&members); | 10274 JSONObject descriptor(&members); |
10269 descriptor.AddPropertyF("pc", "%" Px "", PC(i)); | 10275 descriptor.AddPropertyF("pc", "%" Px "", rec.pc); |
10270 descriptor.AddProperty("kind", KindAsStr(i)); | 10276 descriptor.AddProperty("kind", KindAsStr(rec.kind())); |
10271 descriptor.AddProperty("deoptId", DeoptId(i)); | 10277 descriptor.AddProperty("deoptId", static_cast<intptr_t>(rec.deopt_id)); |
10272 descriptor.AddProperty("tokenPos", TokenPos(i)); | 10278 descriptor.AddProperty("tokenPos", static_cast<intptr_t>(rec.token_pos)); |
10273 descriptor.AddProperty("tryIndex", TryIndex(i)); | 10279 descriptor.AddProperty("tryIndex", static_cast<intptr_t>(rec.try_index)); |
10274 } | 10280 } |
10275 } | 10281 } |
10276 | 10282 |
10277 | 10283 |
10278 void PcDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const { | 10284 void PcDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const { |
10279 JSONObject jsobj(stream); | 10285 JSONObject jsobj(stream); |
10280 PrintToJSONObject(&jsobj); | 10286 PrintToJSONObject(&jsobj); |
10281 } | 10287 } |
10282 | 10288 |
10283 | 10289 |
10284 // Verify assumptions (in debug mode only). | 10290 // Verify assumptions (in debug mode only). |
10285 // - No two deopt descriptors have the same deoptimization id. | 10291 // - No two deopt descriptors have the same deoptimization id. |
10286 // - No two ic-call descriptors have the same deoptimization id (type feedback). | 10292 // - No two ic-call descriptors have the same deoptimization id (type feedback). |
10287 // A function without unique ids is marked as non-optimizable (e.g., because of | 10293 // A function without unique ids is marked as non-optimizable (e.g., because of |
10288 // finally blocks). | 10294 // finally blocks). |
10289 void PcDescriptors::Verify(const Function& function) const { | 10295 void PcDescriptors::Verify(const Function& function) const { |
10290 #if defined(DEBUG) | 10296 #if defined(DEBUG) |
10291 // TODO(srdjan): Implement a more efficient way to check, currently drop | 10297 // TODO(srdjan): Implement a more efficient way to check, currently drop |
10292 // the check for too large number of descriptors. | 10298 // the check for too large number of descriptors. |
10293 if (Length() > 3000) { | 10299 if (Length() > 3000) { |
10294 if (FLAG_trace_compiler) { | 10300 if (FLAG_trace_compiler) { |
10295 OS::Print("Not checking pc decriptors, length %" Pd "\n", Length()); | 10301 OS::Print("Not checking pc decriptors, length %" Pd "\n", Length()); |
10296 } | 10302 } |
10297 return; | 10303 return; |
10298 } | 10304 } |
10299 // Only check ids for unoptimized code that is optimizable. | 10305 // Only check ids for unoptimized code that is optimizable. |
10300 if (!function.IsOptimizable()) return; | 10306 if (!function.IsOptimizable()) { |
10301 for (intptr_t i = 0; i < Length(); i++) { | 10307 return; |
10302 PcDescriptors::Kind kind = DescriptorKind(i); | 10308 } |
| 10309 Iterator iter(*this); |
| 10310 while (iter.HasNext()) { |
| 10311 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 10312 RawPcDescriptors::Kind kind = rec.kind(); |
10303 // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind. | 10313 // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind. |
10304 intptr_t deopt_id = Isolate::kNoDeoptId; | 10314 intptr_t deopt_id = Isolate::kNoDeoptId; |
10305 if ((DescriptorKind(i) != PcDescriptors::kDeopt) || | 10315 if ((kind != RawPcDescriptors::kDeopt) || |
10306 (DescriptorKind(i) != PcDescriptors::kIcCall)) { | 10316 (kind != RawPcDescriptors::kIcCall)) { |
10307 continue; | 10317 continue; |
10308 } | 10318 } |
10309 | 10319 |
10310 deopt_id = DeoptId(i); | 10320 deopt_id = rec.deopt_id; |
10311 if (Isolate::IsDeoptAfter(deopt_id)) { | 10321 if (Isolate::IsDeoptAfter(deopt_id)) { |
10312 // TODO(vegorov): some instructions contain multiple calls and have | 10322 // TODO(vegorov): some instructions contain multiple calls and have |
10313 // multiple "after" targets recorded. Right now it is benign but might | 10323 // multiple "after" targets recorded. Right now it is benign but might |
10314 // lead to issues in the future. Fix that and enable verification. | 10324 // lead to issues in the future. Fix that and enable verification. |
10315 continue; | 10325 continue; |
10316 } | 10326 } |
10317 | 10327 |
10318 for (intptr_t k = i + 1; k < Length(); k++) { | 10328 Iterator nested(iter); |
10319 if (kind == DescriptorKind(k)) { | 10329 while (iter.HasNext()) { |
| 10330 const RawPcDescriptors::PcDescriptorRec& nested_rec = nested.Next(); |
| 10331 if (kind == nested_rec.kind()) { |
10320 if (deopt_id != Isolate::kNoDeoptId) { | 10332 if (deopt_id != Isolate::kNoDeoptId) { |
10321 ASSERT(DeoptId(k) != deopt_id); | 10333 ASSERT(nested_rec.deopt_id != deopt_id); |
10322 } | 10334 } |
10323 } | 10335 } |
10324 } | 10336 } |
10325 } | 10337 } |
10326 #endif // DEBUG | 10338 #endif // DEBUG |
10327 } | 10339 } |
10328 | 10340 |
10329 | 10341 |
10330 uword PcDescriptors::GetPcForKind(Kind kind) const { | 10342 uword PcDescriptors::GetPcForKind(RawPcDescriptors::Kind kind) const { |
10331 for (intptr_t i = 0; i < Length(); i++) { | 10343 Iterator iter(*this); |
10332 if (DescriptorKind(i) == kind) { | 10344 while (iter.HasNext()) { |
10333 return PC(i); | 10345 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 10346 if (rec.kind() == kind) { |
| 10347 return rec.pc; |
10334 } | 10348 } |
10335 } | 10349 } |
10336 return 0; | 10350 return 0; |
10337 } | 10351 } |
10338 | 10352 |
10339 | 10353 |
10340 bool Stackmap::GetBit(intptr_t bit_index) const { | 10354 bool Stackmap::GetBit(intptr_t bit_index) const { |
10341 ASSERT(InRange(bit_index)); | 10355 ASSERT(InRange(bit_index)); |
10342 int byte_index = bit_index >> kBitsPerByteLog2; | 10356 int byte_index = bit_index >> kBitsPerByteLog2; |
10343 int bit_remainder = bit_index & (kBitsPerByte - 1); | 10357 int bit_remainder = bit_index & (kBitsPerByte - 1); |
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11820 if (!code.IsNull() && (code.compile_timestamp() == timestamp) && | 11834 if (!code.IsNull() && (code.compile_timestamp() == timestamp) && |
11821 (code.EntryPoint() == pc)) { | 11835 (code.EntryPoint() == pc)) { |
11822 // Found code in VM isolate. | 11836 // Found code in VM isolate. |
11823 return code.raw(); | 11837 return code.raw(); |
11824 } | 11838 } |
11825 return Code::null(); | 11839 return Code::null(); |
11826 } | 11840 } |
11827 | 11841 |
11828 | 11842 |
11829 intptr_t Code::GetTokenIndexOfPC(uword pc) const { | 11843 intptr_t Code::GetTokenIndexOfPC(uword pc) const { |
11830 intptr_t token_pos = -1; | |
11831 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 11844 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
11832 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 11845 PcDescriptors::Iterator iter(descriptors); |
11833 if (descriptors.PC(i) == pc) { | 11846 while (iter.HasNext()) { |
11834 token_pos = descriptors.TokenPos(i); | 11847 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
11835 break; | 11848 if (rec.pc == pc) { |
| 11849 return rec.token_pos; |
11836 } | 11850 } |
11837 } | 11851 } |
11838 return token_pos; | 11852 return -1; |
11839 } | 11853 } |
11840 | 11854 |
11841 | 11855 |
11842 uword Code::GetPcForDeoptId(intptr_t deopt_id, PcDescriptors::Kind kind) const { | 11856 uword Code::GetPcForDeoptId(intptr_t deopt_id, |
| 11857 RawPcDescriptors::Kind kind) const { |
11843 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 11858 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
11844 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 11859 PcDescriptors::Iterator iter(descriptors); |
11845 if ((descriptors.DeoptId(i) == deopt_id) && | 11860 while (iter.HasNext()) { |
11846 (descriptors.DescriptorKind(i) == kind)) { | 11861 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
11847 uword pc = descriptors.PC(i); | 11862 if ((rec.deopt_id == deopt_id) && (rec.kind() == kind)) { |
| 11863 uword pc = rec.pc; |
11848 ASSERT(ContainsInstructionAt(pc)); | 11864 ASSERT(ContainsInstructionAt(pc)); |
11849 return pc; | 11865 return pc; |
11850 } | 11866 } |
11851 } | 11867 } |
11852 return 0; | 11868 return 0; |
11853 } | 11869 } |
11854 | 11870 |
11855 | 11871 |
11856 intptr_t Code::GetDeoptIdForOsr(uword pc) const { | 11872 intptr_t Code::GetDeoptIdForOsr(uword pc) const { |
11857 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 11873 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
11858 for (intptr_t i = 0; i < descriptors.Length(); ++i) { | 11874 PcDescriptors::Iterator iter(descriptors); |
11859 if ((descriptors.PC(i) == pc) && | 11875 while (iter.HasNext()) { |
11860 (descriptors.DescriptorKind(i) == PcDescriptors::kOsrEntry)) { | 11876 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
11861 return descriptors.DeoptId(i); | 11877 if ((rec.pc == pc) && (rec.kind() == RawPcDescriptors::kOsrEntry)) { |
| 11878 return rec.deopt_id; |
11862 } | 11879 } |
11863 } | 11880 } |
11864 return Isolate::kNoDeoptId; | 11881 return Isolate::kNoDeoptId; |
11865 } | 11882 } |
11866 | 11883 |
11867 | 11884 |
11868 const char* Code::ToCString() const { | 11885 const char* Code::ToCString() const { |
11869 const char* kFormat = "Code entry:%p"; | 11886 const char* kFormat = "Code entry:%p"; |
11870 intptr_t len = OS::SNPrint(NULL, 0, kFormat, EntryPoint()) + 1; | 11887 intptr_t len = OS::SNPrint(NULL, 0, kFormat, EntryPoint()) + 1; |
11871 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 11888 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
(...skipping 7165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19037 return tag_label.ToCString(); | 19054 return tag_label.ToCString(); |
19038 } | 19055 } |
19039 | 19056 |
19040 | 19057 |
19041 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 19058 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
19042 Instance::PrintJSONImpl(stream, ref); | 19059 Instance::PrintJSONImpl(stream, ref); |
19043 } | 19060 } |
19044 | 19061 |
19045 | 19062 |
19046 } // namespace dart | 19063 } // namespace dart |
OLD | NEW |