| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 #include "vm/assert.h" | 8 #include "vm/assert.h" |
| 9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
| 10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
| (...skipping 1602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1613 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); | 1613 const char* library_name = lib.IsNull() ? "" : lib.ToCString(); |
| 1614 const char* class_name = String::Handle(Name()).ToCString(); | 1614 const char* class_name = String::Handle(Name()).ToCString(); |
| 1615 intptr_t len = OS::SNPrint(NULL, 0, format, library_name, class_name) + 1; | 1615 intptr_t len = OS::SNPrint(NULL, 0, format, library_name, class_name) + 1; |
| 1616 char* chars = reinterpret_cast<char*>( | 1616 char* chars = reinterpret_cast<char*>( |
| 1617 Isolate::Current()->current_zone()->Allocate(len)); | 1617 Isolate::Current()->current_zone()->Allocate(len)); |
| 1618 OS::SNPrint(chars, len, format, library_name, class_name); | 1618 OS::SNPrint(chars, len, format, library_name, class_name); |
| 1619 return chars; | 1619 return chars; |
| 1620 } | 1620 } |
| 1621 | 1621 |
| 1622 | 1622 |
| 1623 void Class::InsertCanonicalConstant(intptr_t index, |
| 1624 const Instance& constant) const { |
| 1625 // The constant needs to be added to the list. Grow the list if it is full. |
| 1626 Array& canonical_list = Array::Handle(constants()); |
| 1627 const intptr_t list_len = canonical_list.Length(); |
| 1628 if (index >= list_len) { |
| 1629 const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4; |
| 1630 const Array& new_canonical_list = |
| 1631 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld)); |
| 1632 set_constants(new_canonical_list); |
| 1633 new_canonical_list.SetAt(index, constant); |
| 1634 } else { |
| 1635 canonical_list.SetAt(index, constant); |
| 1636 } |
| 1637 } |
| 1638 |
| 1639 |
| 1623 RawUnresolvedClass* UnresolvedClass::New(intptr_t token_index, | 1640 RawUnresolvedClass* UnresolvedClass::New(intptr_t token_index, |
| 1624 const String& qualifier, | 1641 const String& qualifier, |
| 1625 const String& ident) { | 1642 const String& ident) { |
| 1626 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New()); | 1643 const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New()); |
| 1627 type.set_token_index(token_index); | 1644 type.set_token_index(token_index); |
| 1628 type.set_qualifier(qualifier); | 1645 type.set_qualifier(qualifier); |
| 1629 type.set_ident(ident); | 1646 type.set_ident(ident); |
| 1630 return type.raw(); | 1647 return type.raw(); |
| 1631 } | 1648 } |
| 1632 | 1649 |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2135 const Class& cls = Class::Handle(type_class()); | 2152 const Class& cls = Class::Handle(type_class()); |
| 2136 Array& canonical_types = Array::Handle(cls.canonical_types()); | 2153 Array& canonical_types = Array::Handle(cls.canonical_types()); |
| 2137 if (canonical_types.IsNull()) { | 2154 if (canonical_types.IsNull()) { |
| 2138 // Types defined in the VM isolate are canonicalized via the object store. | 2155 // Types defined in the VM isolate are canonicalized via the object store. |
| 2139 return this->raw(); | 2156 return this->raw(); |
| 2140 } | 2157 } |
| 2141 if (!IsCanonical()) { | 2158 if (!IsCanonical()) { |
| 2142 const intptr_t canonical_types_len = canonical_types.Length(); | 2159 const intptr_t canonical_types_len = canonical_types.Length(); |
| 2143 // Linear search to see whether this type is already present in the | 2160 // Linear search to see whether this type is already present in the |
| 2144 // list of canonicalized types. | 2161 // list of canonicalized types. |
| 2162 // TODO(asiva): Try to re-factor this lookup code to make sharing |
| 2163 // easy between the 4 versions of this loop. |
| 2145 Type& type = Type::Handle(); | 2164 Type& type = Type::Handle(); |
| 2146 intptr_t index = 0; | 2165 intptr_t index = 0; |
| 2147 while (index < canonical_types_len) { | 2166 while (index < canonical_types_len) { |
| 2148 type ^= canonical_types.At(index); | 2167 type ^= canonical_types.At(index); |
| 2149 if (type.IsNull()) { | 2168 if (type.IsNull()) { |
| 2150 break; | 2169 break; |
| 2151 } | 2170 } |
| 2152 if (!type.IsFinalized()) { | 2171 if (!type.IsFinalized()) { |
| 2153 ASSERT((index == 0) && cls.IsSignatureClass()); | 2172 ASSERT((index == 0) && cls.IsSignatureClass()); |
| 2154 index++; | 2173 index++; |
| (...skipping 2872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5027 break; | 5046 break; |
| 5028 } | 5047 } |
| 5029 if (this->Equals(norm_value)) { | 5048 if (this->Equals(norm_value)) { |
| 5030 return norm_value.raw(); | 5049 return norm_value.raw(); |
| 5031 } | 5050 } |
| 5032 index++; | 5051 index++; |
| 5033 } | 5052 } |
| 5034 // The value needs to be added to the list. Grow the list if | 5053 // The value needs to be added to the list. Grow the list if |
| 5035 // it is full. | 5054 // it is full. |
| 5036 // TODO(srdjan): Copy instance into old space if canonicalized? | 5055 // TODO(srdjan): Copy instance into old space if canonicalized? |
| 5037 if (index == constants_len) { | 5056 cls.InsertCanonicalConstant(index, *this); |
| 5038 const intptr_t kInitialConstLength = 4; | |
| 5039 const intptr_t old_length = constants.Length(); | |
| 5040 const intptr_t new_length = | |
| 5041 (old_length == 0) ? kInitialConstLength : old_length * 2; | |
| 5042 const Array& new_constants = | |
| 5043 Array::Handle(Array::Grow(constants, new_length, Heap::kOld)); | |
| 5044 cls.set_constants(new_constants); | |
| 5045 new_constants.SetAt(index, *this); | |
| 5046 } else { | |
| 5047 constants.SetAt(index, *this); | |
| 5048 } | |
| 5049 SetCanonical(); | 5057 SetCanonical(); |
| 5050 } | 5058 } |
| 5051 return this->raw(); | 5059 return this->raw(); |
| 5052 } | 5060 } |
| 5053 | 5061 |
| 5054 | 5062 |
| 5055 RawType* Instance::GetType() const { | 5063 RawType* Instance::GetType() const { |
| 5056 if (IsNull()) { | 5064 if (IsNull()) { |
| 5057 return Type::NullType(); | 5065 return Type::NullType(); |
| 5058 } | 5066 } |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5376 { | 5384 { |
| 5377 RawObject* raw = Object::Allocate(cls, Mint::InstanceSize(), space); | 5385 RawObject* raw = Object::Allocate(cls, Mint::InstanceSize(), space); |
| 5378 NoGCScope no_gc; | 5386 NoGCScope no_gc; |
| 5379 result ^= raw; | 5387 result ^= raw; |
| 5380 } | 5388 } |
| 5381 result.set_value(val); | 5389 result.set_value(val); |
| 5382 return result.raw(); | 5390 return result.raw(); |
| 5383 } | 5391 } |
| 5384 | 5392 |
| 5385 | 5393 |
| 5394 RawMint* Mint::NewCanonical(int64_t value) { |
| 5395 // Do not allocate a Mint if Smi would do. |
| 5396 ASSERT(!Smi::IsValid64(value)); |
| 5397 const Class& cls = |
| 5398 Class::Handle(Isolate::Current()->object_store()->mint_class()); |
| 5399 const Array& constants = Array::Handle(cls.constants()); |
| 5400 const intptr_t constants_len = constants.Length(); |
| 5401 // Linear search to see whether this value is already present in the |
| 5402 // list of canonicalized constants. |
| 5403 Mint& canonical_value = Mint::Handle(); |
| 5404 intptr_t index = 0; |
| 5405 while (index < constants_len) { |
| 5406 canonical_value ^= constants.At(index); |
| 5407 if (canonical_value.IsNull()) { |
| 5408 break; |
| 5409 } |
| 5410 if (canonical_value.value() == value) { |
| 5411 return canonical_value.raw(); |
| 5412 } |
| 5413 index++; |
| 5414 } |
| 5415 // The value needs to be added to the constants list. Grow the list if |
| 5416 // it is full. |
| 5417 canonical_value = Mint::New(value, Heap::kOld); |
| 5418 cls.InsertCanonicalConstant(index, canonical_value); |
| 5419 canonical_value.SetCanonical(); |
| 5420 return canonical_value.raw(); |
| 5421 } |
| 5422 |
| 5423 |
| 5386 bool Mint::Equals(const Instance& other) const { | 5424 bool Mint::Equals(const Instance& other) const { |
| 5387 if (this->raw() == other.raw()) { | 5425 if (this->raw() == other.raw()) { |
| 5388 // Both handles point to the same raw instance. | 5426 // Both handles point to the same raw instance. |
| 5389 return true; | 5427 return true; |
| 5390 } | 5428 } |
| 5391 | 5429 |
| 5392 if (!other.IsMint() || other.IsNull()) { | 5430 if (!other.IsMint() || other.IsNull()) { |
| 5393 return false; | 5431 return false; |
| 5394 } | 5432 } |
| 5395 | 5433 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5446 OS::SNPrint(chars, len, kFormat, value()); | 5484 OS::SNPrint(chars, len, kFormat, value()); |
| 5447 return chars; | 5485 return chars; |
| 5448 } | 5486 } |
| 5449 | 5487 |
| 5450 | 5488 |
| 5451 void Double::set_value(double value) const { | 5489 void Double::set_value(double value) const { |
| 5452 raw_ptr()->value_ = value; | 5490 raw_ptr()->value_ = value; |
| 5453 } | 5491 } |
| 5454 | 5492 |
| 5455 | 5493 |
| 5494 bool Double::EqualsToDouble(double value) const { |
| 5495 intptr_t value_offset = Double::value_offset(); |
| 5496 void* this_addr = reinterpret_cast<void*>( |
| 5497 reinterpret_cast<uword>(this->raw_ptr()) + value_offset); |
| 5498 void* other_addr = reinterpret_cast<void*>(&value); |
| 5499 return (memcmp(this_addr, other_addr, sizeof(value)) == 0); |
| 5500 } |
| 5501 |
| 5502 |
| 5503 bool Double::Equals(const Instance& other) const { |
| 5504 if (this->raw() == other.raw()) { |
| 5505 return true; // "===". |
| 5506 } |
| 5507 if (other.IsNull() || !other.IsDouble()) { |
| 5508 return false; |
| 5509 } |
| 5510 Double& other_dbl = Double::Handle(); |
| 5511 other_dbl ^= other.raw(); |
| 5512 return EqualsToDouble(other_dbl.value()); |
| 5513 } |
| 5514 |
| 5515 |
| 5456 RawDouble* Double::New(double d, Heap::Space space) { | 5516 RawDouble* Double::New(double d, Heap::Space space) { |
| 5457 Isolate* isolate = Isolate::Current(); | 5517 Isolate* isolate = Isolate::Current(); |
| 5458 const Class& cls = | 5518 const Class& cls = |
| 5459 Class::Handle(isolate->object_store()->double_class()); | 5519 Class::Handle(isolate->object_store()->double_class()); |
| 5460 Double& result = Double::Handle(); | 5520 Double& result = Double::Handle(); |
| 5461 { | 5521 { |
| 5462 RawObject* raw = Object::Allocate(cls, Double::InstanceSize(), space); | 5522 RawObject* raw = Object::Allocate(cls, Double::InstanceSize(), space); |
| 5463 NoGCScope no_gc; | 5523 NoGCScope no_gc; |
| 5464 result ^= raw; | 5524 result ^= raw; |
| 5465 } | 5525 } |
| 5466 result.set_value(d); | 5526 result.set_value(d); |
| 5467 return result.raw(); | 5527 return result.raw(); |
| 5468 } | 5528 } |
| 5469 | 5529 |
| 5470 | 5530 |
| 5471 static bool IsWhiteSpace(char ch) { | 5531 static bool IsWhiteSpace(char ch) { |
| 5472 return ch == '\0' || ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t'; | 5532 return ch == '\0' || ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t'; |
| 5473 } | 5533 } |
| 5474 | 5534 |
| 5475 | 5535 |
| 5536 static bool StringToDouble(const String& str, double* double_value) { |
| 5537 ASSERT(double_value != NULL); |
| 5538 // TODO(regis): For now, we use strtod to convert a string to double. |
| 5539 const char* nptr = str.ToCString(); |
| 5540 char* endptr = NULL; |
| 5541 *double_value = strtod(nptr, &endptr); |
| 5542 // We do not treat overflow or underflow as an error and therefore do not |
| 5543 // check errno for ERANGE. |
| 5544 if (!IsWhiteSpace(*endptr)) { |
| 5545 return false; |
| 5546 } |
| 5547 return true; |
| 5548 } |
| 5549 |
| 5550 |
| 5476 RawDouble* Double::New(const String& str, Heap::Space space) { | 5551 RawDouble* Double::New(const String& str, Heap::Space space) { |
| 5477 // TODO(regis): For now, we use strtod to convert a string to double. | 5552 double double_value; |
| 5478 const char* nptr = str.ToCString(); | 5553 if (!StringToDouble(str, &double_value)) { |
| 5479 char* endptr = NULL; | |
| 5480 double double_value = strtod(nptr, &endptr); | |
| 5481 // We do not treat overflow or underflow as an error and therefore do not | |
| 5482 // check errno for ERANGE. | |
| 5483 if (!IsWhiteSpace(*endptr)) { | |
| 5484 return Double::Handle().raw(); | 5554 return Double::Handle().raw(); |
| 5485 } | 5555 } |
| 5486 return New(double_value, space); | 5556 return New(double_value, space); |
| 5487 } | 5557 } |
| 5488 | 5558 |
| 5489 | 5559 |
| 5560 RawDouble* Double::NewCanonical(double value) { |
| 5561 const Class& cls = |
| 5562 Class::Handle(Isolate::Current()->object_store()->double_class()); |
| 5563 const Array& constants = Array::Handle(cls.constants()); |
| 5564 const intptr_t constants_len = constants.Length(); |
| 5565 // Linear search to see whether this value is already present in the |
| 5566 // list of canonicalized constants. |
| 5567 Double& canonical_value = Double::Handle(); |
| 5568 intptr_t index = 0; |
| 5569 while (index < constants_len) { |
| 5570 canonical_value ^= constants.At(index); |
| 5571 if (canonical_value.IsNull()) { |
| 5572 break; |
| 5573 } |
| 5574 if (canonical_value.EqualsToDouble(value)) { |
| 5575 return canonical_value.raw(); |
| 5576 } |
| 5577 index++; |
| 5578 } |
| 5579 // The value needs to be added to the constants list. Grow the list if |
| 5580 // it is full. |
| 5581 canonical_value = Double::New(value, Heap::kOld); |
| 5582 cls.InsertCanonicalConstant(index, canonical_value); |
| 5583 canonical_value.SetCanonical(); |
| 5584 return canonical_value.raw(); |
| 5585 } |
| 5586 |
| 5587 |
| 5588 RawDouble* Double::NewCanonical(const String& str) { |
| 5589 double double_value; |
| 5590 if (!StringToDouble(str, &double_value)) { |
| 5591 return Double::Handle().raw(); |
| 5592 } |
| 5593 return NewCanonical(double_value); |
| 5594 } |
| 5595 |
| 5596 |
| 5490 const char* Double::ToCString() const { | 5597 const char* Double::ToCString() const { |
| 5491 if (isnan(value())) { | 5598 if (isnan(value())) { |
| 5492 return "NaN"; | 5599 return "NaN"; |
| 5493 } | 5600 } |
| 5494 if (isinf(value())) { | 5601 if (isinf(value())) { |
| 5495 return value() < 0 ? "-Infinity" : "Infinity"; | 5602 return value() < 0 ? "-Infinity" : "Infinity"; |
| 5496 } | 5603 } |
| 5497 const char* kFormat = "%f"; | 5604 const char* kFormat = "%f"; |
| 5498 // Calculate the size of the string. | 5605 // Calculate the size of the string. |
| 5499 intptr_t len = OS::SNPrint(NULL, 0, kFormat, value()) + 1; | 5606 intptr_t len = OS::SNPrint(NULL, 0, kFormat, value()) + 1; |
| (...skipping 1805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7305 const String& str = String::Handle(pattern()); | 7412 const String& str = String::Handle(pattern()); |
| 7306 const char* format = "JSRegExp: pattern=%s flags=%s"; | 7413 const char* format = "JSRegExp: pattern=%s flags=%s"; |
| 7307 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); | 7414 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); |
| 7308 char* chars = reinterpret_cast<char*>( | 7415 char* chars = reinterpret_cast<char*>( |
| 7309 Isolate::Current()->current_zone()->Allocate(len + 1)); | 7416 Isolate::Current()->current_zone()->Allocate(len + 1)); |
| 7310 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); | 7417 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); |
| 7311 return chars; | 7418 return chars; |
| 7312 } | 7419 } |
| 7313 | 7420 |
| 7314 } // namespace dart | 7421 } // namespace dart |
| OLD | NEW |