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/bigint_operations.h" | 10 #include "vm/bigint_operations.h" |
(...skipping 6521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6532 PcDescriptors::Kind PcDescriptors::DescriptorKind(intptr_t index) const { | 6532 PcDescriptors::Kind PcDescriptors::DescriptorKind(intptr_t index) const { |
6533 return static_cast<PcDescriptors::Kind>(*(EntryAddr(index, kKindEntry))); | 6533 return static_cast<PcDescriptors::Kind>(*(EntryAddr(index, kKindEntry))); |
6534 } | 6534 } |
6535 | 6535 |
6536 | 6536 |
6537 void PcDescriptors::SetKind(intptr_t index, PcDescriptors::Kind value) const { | 6537 void PcDescriptors::SetKind(intptr_t index, PcDescriptors::Kind value) const { |
6538 *(EntryAddr(index, kKindEntry)) = value; | 6538 *(EntryAddr(index, kKindEntry)) = value; |
6539 } | 6539 } |
6540 | 6540 |
6541 | 6541 |
6542 intptr_t PcDescriptors::NodeId(intptr_t index) const { | 6542 intptr_t PcDescriptors::DeoptId(intptr_t index) const { |
6543 return Smi::Value(*SmiAddr(index, kNodeIdEntry)); | 6543 return Smi::Value(*SmiAddr(index, kDeoptIdEntry)); |
6544 } | 6544 } |
6545 | 6545 |
6546 | 6546 |
6547 void PcDescriptors::SetNodeId(intptr_t index, intptr_t value) const { | 6547 void PcDescriptors::SetDeoptId(intptr_t index, intptr_t value) const { |
6548 *SmiAddr(index, kNodeIdEntry) = Smi::New(value); | 6548 *SmiAddr(index, kDeoptIdEntry) = Smi::New(value); |
6549 } | 6549 } |
6550 | 6550 |
6551 | 6551 |
6552 intptr_t PcDescriptors::TokenIndex(intptr_t index) const { | 6552 intptr_t PcDescriptors::TokenPos(intptr_t index) const { |
6553 return Smi::Value(*SmiAddr(index, kTokenIndexEntry)); | 6553 return Smi::Value(*SmiAddr(index, kTokenPosEntry)); |
6554 } | 6554 } |
6555 | 6555 |
6556 | 6556 |
6557 void PcDescriptors::SetTokenIndex(intptr_t index, intptr_t value) const { | 6557 void PcDescriptors::SetTokenPos(intptr_t index, intptr_t value) const { |
6558 *SmiAddr(index, kTokenIndexEntry) = Smi::New(value); | 6558 *SmiAddr(index, kTokenPosEntry) = Smi::New(value); |
6559 } | 6559 } |
6560 | 6560 |
6561 | 6561 |
6562 intptr_t PcDescriptors::TryIndex(intptr_t index) const { | 6562 intptr_t PcDescriptors::TryIndex(intptr_t index) const { |
6563 ASSERT(DescriptorKind(index) != kDeoptIndex); | 6563 ASSERT(DescriptorKind(index) != kDeoptIndex); |
6564 return *(EntryAddr(index, kTryIndexEntry)); | 6564 return *(EntryAddr(index, kTryIndexEntry)); |
6565 } | 6565 } |
6566 | 6566 |
6567 | 6567 |
6568 intptr_t PcDescriptors::DeoptIndex(intptr_t index) const { | 6568 intptr_t PcDescriptors::DeoptIndex(intptr_t index) const { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6617 return "No pc descriptors\n"; | 6617 return "No pc descriptors\n"; |
6618 } | 6618 } |
6619 const char* kFormat = | 6619 const char* kFormat = |
6620 "0x%" PRIxPTR "\t%s\t%" PRIdPTR "\t%" PRIdPTR "\t%" PRIdPTR "\n"; | 6620 "0x%" PRIxPTR "\t%s\t%" PRIdPTR "\t%" PRIdPTR "\t%" PRIdPTR "\n"; |
6621 // First compute the buffer size required. | 6621 // First compute the buffer size required. |
6622 intptr_t len = 1; // Trailing '\0'. | 6622 intptr_t len = 1; // Trailing '\0'. |
6623 for (intptr_t i = 0; i < Length(); i++) { | 6623 for (intptr_t i = 0; i < Length(); i++) { |
6624 const intptr_t multi_purpose_index = DescriptorKind(i) == kDeoptIndex ? | 6624 const intptr_t multi_purpose_index = DescriptorKind(i) == kDeoptIndex ? |
6625 DeoptIndex(i) : TryIndex(i); | 6625 DeoptIndex(i) : TryIndex(i); |
6626 len += OS::SNPrint(NULL, 0, kFormat, | 6626 len += OS::SNPrint(NULL, 0, kFormat, |
6627 PC(i), KindAsStr(i), NodeId(i), TokenIndex(i), multi_purpose_index); | 6627 PC(i), KindAsStr(i), DeoptId(i), TokenPos(i), multi_purpose_index); |
6628 } | 6628 } |
6629 // Allocate the buffer. | 6629 // Allocate the buffer. |
6630 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len); | 6630 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len); |
6631 // Layout the fields in the buffer. | 6631 // Layout the fields in the buffer. |
6632 intptr_t index = 0; | 6632 intptr_t index = 0; |
6633 for (intptr_t i = 0; i < Length(); i++) { | 6633 for (intptr_t i = 0; i < Length(); i++) { |
6634 const intptr_t multi_purpose_index = DescriptorKind(i) == kDeoptIndex ? | 6634 const intptr_t multi_purpose_index = DescriptorKind(i) == kDeoptIndex ? |
6635 DeoptIndex(i) : TryIndex(i); | 6635 DeoptIndex(i) : TryIndex(i); |
6636 index += OS::SNPrint((buffer + index), (len - index), kFormat, | 6636 index += OS::SNPrint((buffer + index), (len - index), kFormat, |
6637 PC(i), KindAsStr(i), NodeId(i), TokenIndex(i), multi_purpose_index); | 6637 PC(i), KindAsStr(i), DeoptId(i), TokenPos(i), multi_purpose_index); |
6638 } | 6638 } |
6639 return buffer; | 6639 return buffer; |
6640 } | 6640 } |
6641 | 6641 |
6642 | 6642 |
6643 // Verify assumptions (in debug mode only). | 6643 // Verify assumptions (in debug mode only). |
6644 // - No two deopt descriptors have the same node id (deoptimization). | 6644 // - No two deopt descriptors have the same deoptimization id. |
6645 // - No two ic-call descriptors have the same node id (type feedback). | 6645 // - No two ic-call descriptors have the same deoptimization id (type feedback). |
6646 // - No two descriptors of same kind have the same PC. | 6646 // - No two descriptors of same kind have the same PC. |
6647 // A function without unique ids is marked as non-optimizable (e.g., because of | 6647 // A function without unique ids is marked as non-optimizable (e.g., because of |
6648 // finally blocks). | 6648 // finally blocks). |
6649 void PcDescriptors::Verify(bool check_ids) const { | 6649 void PcDescriptors::Verify(bool check_ids) const { |
6650 #if defined(DEBUG) | 6650 #if defined(DEBUG) |
6651 // TODO(srdjan): Implement a more efficient way to check, currently drop | 6651 // TODO(srdjan): Implement a more efficient way to check, currently drop |
6652 // the check for too large number of descriptors. | 6652 // the check for too large number of descriptors. |
6653 if (Length() > 3000) { | 6653 if (Length() > 3000) { |
6654 if (FLAG_trace_compiler) { | 6654 if (FLAG_trace_compiler) { |
6655 OS::Print("Not checking pc decriptors, length %d\n", Length()); | 6655 OS::Print("Not checking pc decriptors, length %d\n", Length()); |
6656 } | 6656 } |
6657 return; | 6657 return; |
6658 } | 6658 } |
6659 for (intptr_t i = 0; i < Length(); i++) { | 6659 for (intptr_t i = 0; i < Length(); i++) { |
6660 uword pc = PC(i); | 6660 uword pc = PC(i); |
6661 PcDescriptors::Kind kind = DescriptorKind(i); | 6661 PcDescriptors::Kind kind = DescriptorKind(i); |
6662 // 'node_id' is set for kDeopt and kIcCall and must be unique for one kind. | 6662 // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind. |
6663 intptr_t node_id = AstNode::kNoId; | 6663 intptr_t deopt_id = Isolate::kNoDeoptId; |
6664 if (check_ids) { | 6664 if (check_ids) { |
6665 if ((DescriptorKind(i) == PcDescriptors::kDeopt) || | 6665 if ((DescriptorKind(i) == PcDescriptors::kDeopt) || |
6666 (DescriptorKind(i) == PcDescriptors::kIcCall)) { | 6666 (DescriptorKind(i) == PcDescriptors::kIcCall)) { |
6667 node_id = NodeId(i); | 6667 deopt_id = DeoptId(i); |
6668 } | 6668 } |
6669 } | 6669 } |
6670 for (intptr_t k = i + 1; k < Length(); k++) { | 6670 for (intptr_t k = i + 1; k < Length(); k++) { |
6671 if (kind == DescriptorKind(k)) { | 6671 if (kind == DescriptorKind(k)) { |
6672 if (node_id != AstNode::kNoId) { | 6672 if (deopt_id != Isolate::kNoDeoptId) { |
6673 ASSERT(NodeId(k) != node_id); | 6673 ASSERT(DeoptId(k) != deopt_id); |
6674 } | 6674 } |
6675 ASSERT(pc != PC(k)); | 6675 ASSERT(pc != PC(k)); |
6676 } | 6676 } |
6677 } | 6677 } |
6678 } | 6678 } |
6679 #endif // DEBUG | 6679 #endif // DEBUG |
6680 } | 6680 } |
6681 | 6681 |
6682 | 6682 |
6683 void Stackmap::SetCode(const Code& code) const { | 6683 void Stackmap::SetCode(const Code& code) const { |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7190 } | 7190 } |
7191 return Code::null(); | 7191 return Code::null(); |
7192 } | 7192 } |
7193 | 7193 |
7194 | 7194 |
7195 intptr_t Code::GetTokenIndexOfPC(uword pc) const { | 7195 intptr_t Code::GetTokenIndexOfPC(uword pc) const { |
7196 intptr_t token_pos = -1; | 7196 intptr_t token_pos = -1; |
7197 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 7197 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
7198 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 7198 for (intptr_t i = 0; i < descriptors.Length(); i++) { |
7199 if (descriptors.PC(i) == pc) { | 7199 if (descriptors.PC(i) == pc) { |
7200 token_pos = descriptors.TokenIndex(i); | 7200 token_pos = descriptors.TokenPos(i); |
7201 break; | 7201 break; |
7202 } | 7202 } |
7203 } | 7203 } |
7204 return token_pos; | 7204 return token_pos; |
7205 } | 7205 } |
7206 | 7206 |
7207 | 7207 |
7208 uword Code::GetDeoptPcAtNodeId(intptr_t node_id) const { | 7208 uword Code::GetDeoptPcAtDeoptId(intptr_t deopt_id) const { |
7209 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); | 7209 const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors()); |
7210 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 7210 for (intptr_t i = 0; i < descriptors.Length(); i++) { |
7211 if ((descriptors.NodeId(i) == node_id) && | 7211 if ((descriptors.DeoptId(i) == deopt_id) && |
7212 (descriptors.DescriptorKind(i) == PcDescriptors::kDeopt)) { | 7212 (descriptors.DescriptorKind(i) == PcDescriptors::kDeopt)) { |
7213 return descriptors.PC(i); | 7213 return descriptors.PC(i); |
7214 } | 7214 } |
7215 } | 7215 } |
7216 return 0; | 7216 return 0; |
7217 } | 7217 } |
7218 | 7218 |
7219 | 7219 |
7220 const char* Code::ToCString() const { | 7220 const char* Code::ToCString() const { |
7221 const char* kFormat = "Code entry:0x%d"; | 7221 const char* kFormat = "Code entry:0x%d"; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7253 GrowableArray<intptr_t>* node_ids, | 7253 GrowableArray<intptr_t>* node_ids, |
7254 const GrowableObjectArray& ic_data_objs) const { | 7254 const GrowableObjectArray& ic_data_objs) const { |
7255 ASSERT(node_ids != NULL); | 7255 ASSERT(node_ids != NULL); |
7256 ASSERT(!ic_data_objs.IsNull()); | 7256 ASSERT(!ic_data_objs.IsNull()); |
7257 const PcDescriptors& descriptors = | 7257 const PcDescriptors& descriptors = |
7258 PcDescriptors::Handle(this->pc_descriptors()); | 7258 PcDescriptors::Handle(this->pc_descriptors()); |
7259 ICData& ic_data_obj = ICData::Handle(); | 7259 ICData& ic_data_obj = ICData::Handle(); |
7260 intptr_t max_id = -1; | 7260 intptr_t max_id = -1; |
7261 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 7261 for (intptr_t i = 0; i < descriptors.Length(); i++) { |
7262 if (descriptors.DescriptorKind(i) == PcDescriptors::kIcCall) { | 7262 if (descriptors.DescriptorKind(i) == PcDescriptors::kIcCall) { |
7263 intptr_t node_id = descriptors.NodeId(i); | 7263 intptr_t deopt_id = descriptors.DeoptId(i); |
7264 if (node_id > max_id) { | 7264 if (deopt_id > max_id) { |
7265 max_id = node_id; | 7265 max_id = deopt_id; |
7266 } | 7266 } |
7267 node_ids->Add(node_id); | 7267 node_ids->Add(deopt_id); |
7268 ic_data_obj = CodePatcher::GetInstanceCallIcDataAt(descriptors.PC(i)); | 7268 ic_data_obj = CodePatcher::GetInstanceCallIcDataAt(descriptors.PC(i)); |
7269 ic_data_objs.Add(ic_data_obj); | 7269 ic_data_objs.Add(ic_data_obj); |
7270 } | 7270 } |
7271 } | 7271 } |
7272 return max_id; | 7272 return max_id; |
7273 } | 7273 } |
7274 | 7274 |
7275 | 7275 |
7276 RawStackmap* Code::GetStackmap(uword pc, Array* maps, Stackmap* map) const { | 7276 RawStackmap* Code::GetStackmap(uword pc, Array* maps, Stackmap* map) const { |
7277 // This code is used during iterating frames during a GC and hence it | 7277 // This code is used during iterating frames during a GC and hence it |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7430 void ICData::set_function(const Function& value) const { | 7430 void ICData::set_function(const Function& value) const { |
7431 StorePointer(&raw_ptr()->function_, value.raw()); | 7431 StorePointer(&raw_ptr()->function_, value.raw()); |
7432 } | 7432 } |
7433 | 7433 |
7434 | 7434 |
7435 void ICData::set_target_name(const String& value) const { | 7435 void ICData::set_target_name(const String& value) const { |
7436 StorePointer(&raw_ptr()->target_name_, value.raw()); | 7436 StorePointer(&raw_ptr()->target_name_, value.raw()); |
7437 } | 7437 } |
7438 | 7438 |
7439 | 7439 |
7440 void ICData::set_id(intptr_t value) const { | 7440 void ICData::set_deopt_id(intptr_t value) const { |
7441 raw_ptr()->id_ = value; | 7441 raw_ptr()->deopt_id_ = value; |
7442 } | 7442 } |
7443 | 7443 |
7444 | 7444 |
7445 void ICData::set_num_args_tested(intptr_t value) const { | 7445 void ICData::set_num_args_tested(intptr_t value) const { |
7446 raw_ptr()->num_args_tested_ = value; | 7446 raw_ptr()->num_args_tested_ = value; |
7447 } | 7447 } |
7448 | 7448 |
7449 | 7449 |
7450 void ICData::set_ic_data(const Array& value) const { | 7450 void ICData::set_ic_data(const Array& value) const { |
7451 StorePointer(&raw_ptr()->ic_data_, value.raw()); | 7451 StorePointer(&raw_ptr()->ic_data_, value.raw()); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7583 | 7583 |
7584 | 7584 |
7585 RawICData* ICData::AsUnaryClassChecks() const { | 7585 RawICData* ICData::AsUnaryClassChecks() const { |
7586 ASSERT(!IsNull()); | 7586 ASSERT(!IsNull()); |
7587 ASSERT(num_args_tested() > 0); | 7587 ASSERT(num_args_tested() > 0); |
7588 if (num_args_tested() == 1) return raw(); | 7588 if (num_args_tested() == 1) return raw(); |
7589 const intptr_t kNumArgsTested = 1; | 7589 const intptr_t kNumArgsTested = 1; |
7590 ICData& result = ICData::Handle(ICData::New( | 7590 ICData& result = ICData::Handle(ICData::New( |
7591 Function::Handle(function()), | 7591 Function::Handle(function()), |
7592 String::Handle(target_name()), | 7592 String::Handle(target_name()), |
7593 id(), | 7593 deopt_id(), |
7594 kNumArgsTested)); | 7594 kNumArgsTested)); |
7595 for (intptr_t i = 0; i < NumberOfChecks(); i++) { | 7595 for (intptr_t i = 0; i < NumberOfChecks(); i++) { |
7596 const intptr_t class_id = GetReceiverClassIdAt(i); | 7596 const intptr_t class_id = GetReceiverClassIdAt(i); |
7597 intptr_t duplicate_class_id = -1; | 7597 intptr_t duplicate_class_id = -1; |
7598 for (intptr_t k = 0; k < result.NumberOfChecks(); k++) { | 7598 for (intptr_t k = 0; k < result.NumberOfChecks(); k++) { |
7599 if (class_id == result.GetReceiverClassIdAt(k)) { | 7599 if (class_id == result.GetReceiverClassIdAt(k)) { |
7600 duplicate_class_id = k; | 7600 duplicate_class_id = k; |
7601 break; | 7601 break; |
7602 } | 7602 } |
7603 } | 7603 } |
7604 if (duplicate_class_id >= 0) { | 7604 if (duplicate_class_id >= 0) { |
7605 ASSERT(result.GetTargetAt(duplicate_class_id) == GetTargetAt(i)); | 7605 ASSERT(result.GetTargetAt(duplicate_class_id) == GetTargetAt(i)); |
7606 } else { | 7606 } else { |
7607 // This will make sure that Smi is first if it exists. | 7607 // This will make sure that Smi is first if it exists. |
7608 result.AddReceiverCheck(class_id, | 7608 result.AddReceiverCheck(class_id, |
7609 Function::Handle(GetTargetAt(i))); | 7609 Function::Handle(GetTargetAt(i))); |
7610 } | 7610 } |
7611 } | 7611 } |
7612 return result.raw(); | 7612 return result.raw(); |
7613 } | 7613 } |
7614 | 7614 |
7615 | 7615 |
7616 RawICData* ICData::New(const Function& function, | 7616 RawICData* ICData::New(const Function& function, |
7617 const String& target_name, | 7617 const String& target_name, |
7618 intptr_t id, | 7618 intptr_t deopt_id, |
7619 intptr_t num_args_tested) { | 7619 intptr_t num_args_tested) { |
7620 ASSERT(Object::icdata_class() != Class::null()); | 7620 ASSERT(Object::icdata_class() != Class::null()); |
7621 ASSERT(num_args_tested > 0); | 7621 ASSERT(num_args_tested > 0); |
7622 ICData& result = ICData::Handle(); | 7622 ICData& result = ICData::Handle(); |
7623 { | 7623 { |
7624 // IC data objects are long living objects, allocate them in old generation. | 7624 // IC data objects are long living objects, allocate them in old generation. |
7625 RawObject* raw = Object::Allocate(ICData::kInstanceKind, | 7625 RawObject* raw = Object::Allocate(ICData::kInstanceKind, |
7626 ICData::InstanceSize(), | 7626 ICData::InstanceSize(), |
7627 Heap::kOld); | 7627 Heap::kOld); |
7628 NoGCScope no_gc; | 7628 NoGCScope no_gc; |
7629 result ^= raw; | 7629 result ^= raw; |
7630 } | 7630 } |
7631 result.set_function(function); | 7631 result.set_function(function); |
7632 result.set_target_name(target_name); | 7632 result.set_target_name(target_name); |
7633 result.set_id(id); | 7633 result.set_deopt_id(deopt_id); |
7634 result.set_num_args_tested(num_args_tested); | 7634 result.set_num_args_tested(num_args_tested); |
7635 // Number of array elements in one test entry (num_args_tested + 1) | 7635 // Number of array elements in one test entry (num_args_tested + 1) |
7636 intptr_t len = result.TestEntryLength(); | 7636 intptr_t len = result.TestEntryLength(); |
7637 // IC data array must be null terminated (sentinel entry). | 7637 // IC data array must be null terminated (sentinel entry). |
7638 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); | 7638 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); |
7639 result.set_ic_data(ic_data); | 7639 result.set_ic_data(ic_data); |
7640 result.WriteSentinel(); | 7640 result.WriteSentinel(); |
7641 return result.raw(); | 7641 return result.raw(); |
7642 } | 7642 } |
7643 | 7643 |
(...skipping 3402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11046 const char* JSRegExp::ToCString() const { | 11046 const char* JSRegExp::ToCString() const { |
11047 const String& str = String::Handle(pattern()); | 11047 const String& str = String::Handle(pattern()); |
11048 const char* format = "JSRegExp: pattern=%s flags=%s"; | 11048 const char* format = "JSRegExp: pattern=%s flags=%s"; |
11049 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); | 11049 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); |
11050 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 11050 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
11051 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); | 11051 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); |
11052 return chars; | 11052 return chars; |
11053 } | 11053 } |
11054 | 11054 |
11055 } // namespace dart | 11055 } // namespace dart |
OLD | NEW |