Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: vm/object.cc

Issue 8963001: Add Double::NewCanonical and Mint::NewCanonical so that it is possible to (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « vm/object.h ('k') | vm/object_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « vm/object.h ('k') | vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698