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 10259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10270 size, | 10270 size, |
10271 Heap::kOld); | 10271 Heap::kOld); |
10272 NoGCScope no_gc; | 10272 NoGCScope no_gc; |
10273 result ^= raw; | 10273 result ^= raw; |
10274 result.SetLength(num_descriptors); | 10274 result.SetLength(num_descriptors); |
10275 } | 10275 } |
10276 return result.raw(); | 10276 return result.raw(); |
10277 } | 10277 } |
10278 | 10278 |
10279 | 10279 |
10280 const char* PcDescriptors::KindAsStr(intptr_t index) const { | 10280 const char* PcDescriptors::KindAsStr(RawPcDescriptors::Kind kind) { |
10281 switch (DescriptorKind(index)) { | 10281 switch (kind) { |
10282 case PcDescriptors::kDeopt: return "deopt "; | 10282 case RawPcDescriptors::kDeopt: return "deopt "; |
10283 case PcDescriptors::kIcCall: return "ic-call "; | 10283 case RawPcDescriptors::kIcCall: return "ic-call "; |
10284 case PcDescriptors::kOptStaticCall: return "opt-call "; | 10284 case RawPcDescriptors::kOptStaticCall: return "opt-call "; |
10285 case PcDescriptors::kUnoptStaticCall: return "unopt-call "; | 10285 case RawPcDescriptors::kUnoptStaticCall: return "unopt-call "; |
10286 case PcDescriptors::kClosureCall: return "closure-call "; | 10286 case RawPcDescriptors::kClosureCall: return "closure-call "; |
10287 case PcDescriptors::kRuntimeCall: return "runtime-call "; | 10287 case RawPcDescriptors::kRuntimeCall: return "runtime-call "; |
10288 case PcDescriptors::kOsrEntry: return "osr-entry "; | 10288 case RawPcDescriptors::kOsrEntry: return "osr-entry "; |
10289 case PcDescriptors::kOther: return "other "; | 10289 case RawPcDescriptors::kOther: return "other "; |
10290 } | 10290 } |
10291 UNREACHABLE(); | 10291 UNREACHABLE(); |
10292 return ""; | 10292 return ""; |
10293 } | 10293 } |
10294 | 10294 |
10295 | 10295 |
10296 void PcDescriptors::PrintHeaderString() { | 10296 void PcDescriptors::PrintHeaderString() { |
10297 // 4 bits per hex digit + 2 for "0x". | 10297 // 4 bits per hex digit + 2 for "0x". |
10298 const int addr_width = (kBitsPerWord / 4) + 2; | 10298 const int addr_width = (kBitsPerWord / 4) + 2; |
10299 // "*" in a printf format specifier tells it to read the field width from | 10299 // "*" in a printf format specifier tells it to read the field width from |
10300 // the printf argument list. | 10300 // the printf argument list. |
10301 OS::Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\n", | 10301 OS::Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\n", |
10302 addr_width, "pc"); | 10302 addr_width, "pc"); |
10303 } | 10303 } |
10304 | 10304 |
10305 | 10305 |
10306 const char* PcDescriptors::ToCString() const { | 10306 const char* PcDescriptors::ToCString() const { |
10307 if (Length() == 0) { | 10307 if (Length() == 0) { |
10308 return "No pc descriptors\n"; | 10308 return "No pc descriptors\n"; |
10309 } | 10309 } |
10310 // 4 bits per hex digit. | 10310 // 4 bits per hex digit. |
10311 const int addr_width = kBitsPerWord / 4; | 10311 const int addr_width = kBitsPerWord / 4; |
10312 // "*" in a printf format specifier tells it to read the field width from | 10312 // "*" in a printf format specifier tells it to read the field width from |
10313 // the printf argument list. | 10313 // the printf argument list. |
10314 const char* kFormat = | 10314 const char* kFormat = |
10315 "%#-*" Px "\t%s\t%" Pd "\t\t%" Pd "\t%" Pd "\n"; | 10315 "%#-*" Px "\t%s\t%" Pd "\t\t%" Pd "\t%" Pd "\n"; |
10316 // First compute the buffer size required. | 10316 // First compute the buffer size required. |
10317 intptr_t len = 1; // Trailing '\0'. | 10317 intptr_t len = 1; // Trailing '\0'. |
10318 for (intptr_t i = 0; i < Length(); i++) { | 10318 Iterator iter(*this); |
| 10319 while (iter.HasNext()) { |
| 10320 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
10319 len += OS::SNPrint(NULL, 0, kFormat, addr_width, | 10321 len += OS::SNPrint(NULL, 0, kFormat, addr_width, |
10320 PC(i), | 10322 rec.pc, |
10321 KindAsStr(i), | 10323 KindAsStr(rec.kind()), |
10322 DeoptId(i), | 10324 rec.deopt_id, |
10323 TokenPos(i), | 10325 rec.token_pos, |
10324 TryIndex(i)); | 10326 rec.try_index); |
10325 } | 10327 } |
10326 // Allocate the buffer. | 10328 // Allocate the buffer. |
10327 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len); | 10329 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len); |
10328 // Layout the fields in the buffer. | 10330 // Layout the fields in the buffer. |
10329 intptr_t index = 0; | 10331 intptr_t index = 0; |
10330 for (intptr_t i = 0; i < Length(); i++) { | 10332 Iterator iter2(*this); |
| 10333 while (iter2.HasNext()) { |
| 10334 const RawPcDescriptors::PcDescriptorRec& rec = iter2.Next(); |
10331 index += OS::SNPrint((buffer + index), (len - index), kFormat, addr_width, | 10335 index += OS::SNPrint((buffer + index), (len - index), kFormat, addr_width, |
10332 PC(i), | 10336 rec.pc, |
10333 KindAsStr(i), | 10337 KindAsStr(rec.kind()), |
10334 DeoptId(i), | 10338 rec.deopt_id, |
10335 TokenPos(i), | 10339 rec.token_pos, |
10336 TryIndex(i)); | 10340 rec.try_index); |
10337 } | 10341 } |
10338 return buffer; | 10342 return buffer; |
10339 } | 10343 } |
10340 | 10344 |
10341 | 10345 |
10342 void PcDescriptors::PrintToJSONObject(JSONObject* jsobj) const { | 10346 void PcDescriptors::PrintToJSONObject(JSONObject* jsobj) const { |
10343 jsobj->AddProperty("type", JSONType(false)); | 10347 jsobj->AddProperty("type", JSONType(false)); |
10344 // TODO(johnmccutchan): Generate a valid ID. | 10348 // TODO(johnmccutchan): Generate a valid ID. |
10345 // PcDescriptors hang off a Code object but do not have a back reference to | 10349 // PcDescriptors hang off a Code object but do not have a back reference to |
10346 // generate an ID. Currently we only print PcDescriptors inline with a Code. | 10350 // generate an ID. Currently we only print PcDescriptors inline with a Code. |
10347 jsobj->AddProperty("id", ""); | 10351 jsobj->AddProperty("id", ""); |
10348 JSONArray members(jsobj, "members"); | 10352 JSONArray members(jsobj, "members"); |
10349 for (intptr_t i = 0; i < Length(); i++) { | 10353 Iterator iter(*this); |
| 10354 while (iter.HasNext()) { |
| 10355 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
10350 JSONObject descriptor(&members); | 10356 JSONObject descriptor(&members); |
10351 descriptor.AddPropertyF("pc", "%" Px "", PC(i)); | 10357 descriptor.AddPropertyF("pc", "%" Px "", rec.pc); |
10352 descriptor.AddProperty("kind", KindAsStr(i)); | 10358 descriptor.AddProperty("kind", KindAsStr(rec.kind())); |
10353 descriptor.AddProperty("deoptId", DeoptId(i)); | 10359 descriptor.AddProperty("deoptId", static_cast<intptr_t>(rec.deopt_id)); |
10354 descriptor.AddProperty("tokenPos", TokenPos(i)); | 10360 descriptor.AddProperty("tokenPos", static_cast<intptr_t>(rec.token_pos)); |
10355 descriptor.AddProperty("tryIndex", TryIndex(i)); | 10361 descriptor.AddProperty("tryIndex", static_cast<intptr_t>(rec.try_index)); |
10356 } | 10362 } |
10357 } | 10363 } |
10358 | 10364 |
10359 | 10365 |
10360 void PcDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const { | 10366 void PcDescriptors::PrintJSONImpl(JSONStream* stream, bool ref) const { |
10361 JSONObject jsobj(stream); | 10367 JSONObject jsobj(stream); |
10362 PrintToJSONObject(&jsobj); | 10368 PrintToJSONObject(&jsobj); |
10363 } | 10369 } |
10364 | 10370 |
10365 | 10371 |
10366 // Verify assumptions (in debug mode only). | 10372 // Verify assumptions (in debug mode only). |
10367 // - No two deopt descriptors have the same deoptimization id. | 10373 // - No two deopt descriptors have the same deoptimization id. |
10368 // - No two ic-call descriptors have the same deoptimization id (type feedback). | 10374 // - No two ic-call descriptors have the same deoptimization id (type feedback). |
10369 // A function without unique ids is marked as non-optimizable (e.g., because of | 10375 // A function without unique ids is marked as non-optimizable (e.g., because of |
10370 // finally blocks). | 10376 // finally blocks). |
10371 void PcDescriptors::Verify(const Function& function) const { | 10377 void PcDescriptors::Verify(const Function& function) const { |
10372 #if defined(DEBUG) | 10378 #if defined(DEBUG) |
10373 // TODO(srdjan): Implement a more efficient way to check, currently drop | 10379 // TODO(srdjan): Implement a more efficient way to check, currently drop |
10374 // the check for too large number of descriptors. | 10380 // the check for too large number of descriptors. |
10375 if (Length() > 3000) { | 10381 if (Length() > 3000) { |
10376 if (FLAG_trace_compiler) { | 10382 if (FLAG_trace_compiler) { |
10377 OS::Print("Not checking pc decriptors, length %" Pd "\n", Length()); | 10383 OS::Print("Not checking pc decriptors, length %" Pd "\n", Length()); |
10378 } | 10384 } |
10379 return; | 10385 return; |
10380 } | 10386 } |
10381 // Only check ids for unoptimized code that is optimizable. | 10387 // Only check ids for unoptimized code that is optimizable. |
10382 if (!function.IsOptimizable()) return; | 10388 if (!function.IsOptimizable()) { |
10383 for (intptr_t i = 0; i < Length(); i++) { | 10389 return; |
10384 PcDescriptors::Kind kind = DescriptorKind(i); | 10390 } |
| 10391 Iterator iter(*this); |
| 10392 while (iter.HasNext()) { |
| 10393 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 10394 RawPcDescriptors::Kind kind = rec.kind(); |
10385 // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind. | 10395 // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind. |
10386 intptr_t deopt_id = Isolate::kNoDeoptId; | 10396 intptr_t deopt_id = Isolate::kNoDeoptId; |
10387 if ((DescriptorKind(i) != PcDescriptors::kDeopt) || | 10397 if ((kind != RawPcDescriptors::kDeopt) || |
10388 (DescriptorKind(i) != PcDescriptors::kIcCall)) { | 10398 (kind != RawPcDescriptors::kIcCall)) { |
10389 continue; | 10399 continue; |
10390 } | 10400 } |
10391 | 10401 |
10392 deopt_id = DeoptId(i); | 10402 deopt_id = rec.deopt_id; |
10393 if (Isolate::IsDeoptAfter(deopt_id)) { | 10403 if (Isolate::IsDeoptAfter(deopt_id)) { |
10394 // TODO(vegorov): some instructions contain multiple calls and have | 10404 // TODO(vegorov): some instructions contain multiple calls and have |
10395 // multiple "after" targets recorded. Right now it is benign but might | 10405 // multiple "after" targets recorded. Right now it is benign but might |
10396 // lead to issues in the future. Fix that and enable verification. | 10406 // lead to issues in the future. Fix that and enable verification. |
10397 continue; | 10407 continue; |
10398 } | 10408 } |
10399 | 10409 |
10400 for (intptr_t k = i + 1; k < Length(); k++) { | 10410 Iterator nested(iter); |
10401 if (kind == DescriptorKind(k)) { | 10411 while (iter.HasNext()) { |
| 10412 const RawPcDescriptors::PcDescriptorRec& nested_rec = nested.Next(); |
| 10413 if (kind == nested_rec.kind()) { |
10402 if (deopt_id != Isolate::kNoDeoptId) { | 10414 if (deopt_id != Isolate::kNoDeoptId) { |
10403 ASSERT(DeoptId(k) != deopt_id); | 10415 ASSERT(nested_rec.deopt_id != deopt_id); |
10404 } | 10416 } |
10405 } | 10417 } |
10406 } | 10418 } |
10407 } | 10419 } |
10408 #endif // DEBUG | 10420 #endif // DEBUG |
10409 } | 10421 } |
10410 | 10422 |
10411 | 10423 |
10412 uword PcDescriptors::GetPcForKind(Kind kind) const { | 10424 uword PcDescriptors::GetPcForKind(RawPcDescriptors::Kind kind) const { |
10413 for (intptr_t i = 0; i < Length(); i++) { | 10425 Iterator iter(*this); |
10414 if (DescriptorKind(i) == kind) { | 10426 while (iter.HasNext()) { |
10415 return PC(i); | 10427 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
| 10428 if (rec.kind() == kind) { |
| 10429 return rec.pc; |
10416 } | 10430 } |
10417 } | 10431 } |
10418 return 0; | 10432 return 0; |
10419 } | 10433 } |
10420 | 10434 |
10421 | 10435 |
10422 bool Stackmap::GetBit(intptr_t bit_index) const { | 10436 bool Stackmap::GetBit(intptr_t bit_index) const { |
10423 ASSERT(InRange(bit_index)); | 10437 ASSERT(InRange(bit_index)); |
10424 int byte_index = bit_index >> kBitsPerByteLog2; | 10438 int byte_index = bit_index >> kBitsPerByteLog2; |
10425 int bit_remainder = bit_index & (kBitsPerByte - 1); | 10439 int bit_remainder = bit_index & (kBitsPerByte - 1); |
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11902 if (!code.IsNull() && (code.compile_timestamp() == timestamp) && | 11916 if (!code.IsNull() && (code.compile_timestamp() == timestamp) && |
11903 (code.EntryPoint() == pc)) { | 11917 (code.EntryPoint() == pc)) { |
11904 // Found code in VM isolate. | 11918 // Found code in VM isolate. |
11905 return code.raw(); | 11919 return code.raw(); |
11906 } | 11920 } |
11907 return Code::null(); | 11921 return Code::null(); |
11908 } | 11922 } |
11909 | 11923 |
11910 | 11924 |
11911 intptr_t Code::GetTokenIndexOfPC(uword pc) const { | 11925 intptr_t Code::GetTokenIndexOfPC(uword pc) const { |
11912 intptr_t token_pos = -1; | |
11913 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 11926 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
11914 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 11927 PcDescriptors::Iterator iter(descriptors); |
11915 if (descriptors.PC(i) == pc) { | 11928 while (iter.HasNext()) { |
11916 token_pos = descriptors.TokenPos(i); | 11929 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
11917 break; | 11930 if (rec.pc == pc) { |
| 11931 return rec.token_pos; |
11918 } | 11932 } |
11919 } | 11933 } |
11920 return token_pos; | 11934 return -1; |
11921 } | 11935 } |
11922 | 11936 |
11923 | 11937 |
11924 uword Code::GetPcForDeoptId(intptr_t deopt_id, PcDescriptors::Kind kind) const { | 11938 uword Code::GetPcForDeoptId(intptr_t deopt_id, |
| 11939 RawPcDescriptors::Kind kind) const { |
11925 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 11940 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
11926 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 11941 PcDescriptors::Iterator iter(descriptors); |
11927 if ((descriptors.DeoptId(i) == deopt_id) && | 11942 while (iter.HasNext()) { |
11928 (descriptors.DescriptorKind(i) == kind)) { | 11943 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
11929 uword pc = descriptors.PC(i); | 11944 if ((rec.deopt_id == deopt_id) && (rec.kind() == kind)) { |
| 11945 uword pc = rec.pc; |
11930 ASSERT(ContainsInstructionAt(pc)); | 11946 ASSERT(ContainsInstructionAt(pc)); |
11931 return pc; | 11947 return pc; |
11932 } | 11948 } |
11933 } | 11949 } |
11934 return 0; | 11950 return 0; |
11935 } | 11951 } |
11936 | 11952 |
11937 | 11953 |
11938 intptr_t Code::GetDeoptIdForOsr(uword pc) const { | 11954 intptr_t Code::GetDeoptIdForOsr(uword pc) const { |
11939 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 11955 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
11940 for (intptr_t i = 0; i < descriptors.Length(); ++i) { | 11956 PcDescriptors::Iterator iter(descriptors); |
11941 if ((descriptors.PC(i) == pc) && | 11957 while (iter.HasNext()) { |
11942 (descriptors.DescriptorKind(i) == PcDescriptors::kOsrEntry)) { | 11958 const RawPcDescriptors::PcDescriptorRec& rec = iter.Next(); |
11943 return descriptors.DeoptId(i); | 11959 if ((rec.pc == pc) && (rec.kind() == RawPcDescriptors::kOsrEntry)) { |
| 11960 return rec.deopt_id; |
11944 } | 11961 } |
11945 } | 11962 } |
11946 return Isolate::kNoDeoptId; | 11963 return Isolate::kNoDeoptId; |
11947 } | 11964 } |
11948 | 11965 |
11949 | 11966 |
11950 const char* Code::ToCString() const { | 11967 const char* Code::ToCString() const { |
11951 const char* kFormat = "Code entry:%p"; | 11968 const char* kFormat = "Code entry:%p"; |
11952 intptr_t len = OS::SNPrint(NULL, 0, kFormat, EntryPoint()) + 1; | 11969 intptr_t len = OS::SNPrint(NULL, 0, kFormat, EntryPoint()) + 1; |
11953 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 11970 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
(...skipping 7136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19090 return tag_label.ToCString(); | 19107 return tag_label.ToCString(); |
19091 } | 19108 } |
19092 | 19109 |
19093 | 19110 |
19094 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 19111 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
19095 Instance::PrintJSONImpl(stream, ref); | 19112 Instance::PrintJSONImpl(stream, ref); |
19096 } | 19113 } |
19097 | 19114 |
19098 | 19115 |
19099 } // namespace dart | 19116 } // namespace dart |
OLD | NEW |