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