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

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
« vm/object.h ('K') | « 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 4993 matching lines...) Expand 10 before | Expand all | Expand 10 after
5004 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != 5004 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) !=
5005 (*reinterpret_cast<RawObject**>(other_addr + offset))) { 5005 (*reinterpret_cast<RawObject**>(other_addr + offset))) {
5006 return false; 5006 return false;
5007 } 5007 }
5008 } 5008 }
5009 } 5009 }
5010 return true; 5010 return true;
5011 } 5011 }
5012 5012
5013 5013
5014 static void InsertCanonicalConstant(const Class& cls,
5015 const Array& canonical_list,
5016 intptr_t index,
5017 const Instance& constant) {
srdjan 2011/12/15 22:02:26 Why not make it a Class function?
siva 2011/12/15 23:42:54 Done.
5018 // The constant needs to be added to the list. Grow the list if it is full.
5019 const intptr_t list_len = canonical_list.Length();
5020 if (index == list_len) {
srdjan 2011/12/15 22:02:26 index >= list_len ?
siva 2011/12/15 23:42:54 Done.
5021 const intptr_t new_length = (list_len == 0) ? 4 : list_len * 2;
srdjan 2011/12/15 22:02:26 That grows a little bit too quickly, IMHO.
siva 2011/12/15 23:42:54 Changed it to (list_len + 4) for growth, so grow b
5022 const Array& new_canonical_list =
5023 Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld));
5024 cls.set_constants(new_canonical_list);
5025 new_canonical_list.SetAt(index, constant);
5026 } else {
5027 canonical_list.SetAt(index, constant);
5028 }
5029 }
5030
5031
5014 RawInstance* Instance::Canonicalize() const { 5032 RawInstance* Instance::Canonicalize() const {
5015 ASSERT(!IsNull()); 5033 ASSERT(!IsNull());
5016 if (!IsCanonical()) { 5034 if (!IsCanonical()) {
srdjan 2011/12/15 22:02:26 Can we move all this code into Class, thus no acce
siva 2011/12/15 23:42:54 As discussed off-line, I have added a TODO to cons
5017 const Class& cls = Class::Handle(this->clazz()); 5035 const Class& cls = Class::Handle(this->clazz());
5018 Array& constants = Array::Handle(cls.constants()); 5036 Array& constants = Array::Handle(cls.constants());
5019 const intptr_t constants_len = constants.Length(); 5037 const intptr_t constants_len = constants.Length();
5020 // Linear search to see whether this value is already present in the 5038 // Linear search to see whether this value is already present in the
5021 // list of canonicalized constants. 5039 // list of canonicalized constants.
5022 Instance& norm_value = Instance::Handle(); 5040 Instance& norm_value = Instance::Handle();
5023 intptr_t index = 0; 5041 intptr_t index = 0;
5024 while (index < constants_len) { 5042 while (index < constants_len) {
5025 norm_value ^= constants.At(index); 5043 norm_value ^= constants.At(index);
5026 if (norm_value.IsNull()) { 5044 if (norm_value.IsNull()) {
5027 break; 5045 break;
5028 } 5046 }
5029 if (this->Equals(norm_value)) { 5047 if (this->Equals(norm_value)) {
5030 return norm_value.raw(); 5048 return norm_value.raw();
5031 } 5049 }
5032 index++; 5050 index++;
5033 } 5051 }
5034 // The value needs to be added to the list. Grow the list if 5052 // The value needs to be added to the list. Grow the list if
5035 // it is full. 5053 // it is full.
5036 // TODO(srdjan): Copy instance into old space if canonicalized? 5054 // TODO(srdjan): Copy instance into old space if canonicalized?
5037 if (index == constants_len) { 5055 InsertCanonicalConstant(cls, constants, 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(); 5056 SetCanonical();
5050 } 5057 }
5051 return this->raw(); 5058 return this->raw();
5052 } 5059 }
5053 5060
5054 5061
5055 RawType* Instance::GetType() const { 5062 RawType* Instance::GetType() const {
5056 if (IsNull()) { 5063 if (IsNull()) {
5057 return Type::NullType(); 5064 return Type::NullType();
5058 } 5065 }
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
5376 { 5383 {
5377 RawObject* raw = Object::Allocate(cls, Mint::InstanceSize(), space); 5384 RawObject* raw = Object::Allocate(cls, Mint::InstanceSize(), space);
5378 NoGCScope no_gc; 5385 NoGCScope no_gc;
5379 result ^= raw; 5386 result ^= raw;
5380 } 5387 }
5381 result.set_value(val); 5388 result.set_value(val);
5382 return result.raw(); 5389 return result.raw();
5383 } 5390 }
5384 5391
5385 5392
5393 RawMint* Mint::NewCanonical(int64_t value) {
5394 // Do not allocate a Mint if Smi would do.
5395 ASSERT(!Smi::IsValid64(value));
srdjan 2011/12/15 22:02:26 If we move this code into Class, we could share it
siva 2011/12/15 23:42:54 Ditto. On 2011/12/15 22:02:26, srdjan wrote:
5396 const Class& cls =
5397 Class::Handle(Isolate::Current()->object_store()->mint_class());
srdjan 2011/12/15 22:02:26 Isn't cls = Class::Handle(clazz()); ?
siva 2011/12/15 23:42:54 This is a static method, clazz() is not valid. On
5398 const Array& constants = Array::Handle(cls.constants());
5399 const intptr_t constants_len = constants.Length();
5400 // Linear search to see whether this value is already present in the
5401 // list of canonicalized constants.
5402 Mint& canonical_value = Mint::Handle();
5403 intptr_t index = 0;
5404 while (index < constants_len) {
5405 canonical_value ^= constants.At(index);
5406 if (canonical_value.IsNull()) {
5407 break;
5408 }
5409 if (canonical_value.value() == value) {
5410 return canonical_value.raw();
5411 }
5412 index++;
5413 }
5414 // The value needs to be added to the constants list. Grow the list if
5415 // it is full.
5416 canonical_value = Mint::New(value, Heap::kOld);
5417 InsertCanonicalConstant(cls, constants, index, canonical_value);
5418 canonical_value.SetCanonical();
5419 return canonical_value.raw();
5420 }
5421
5422
5386 bool Mint::Equals(const Instance& other) const { 5423 bool Mint::Equals(const Instance& other) const {
5387 if (this->raw() == other.raw()) { 5424 if (this->raw() == other.raw()) {
5388 // Both handles point to the same raw instance. 5425 // Both handles point to the same raw instance.
5389 return true; 5426 return true;
5390 } 5427 }
5391 5428
5392 if (!other.IsMint() || other.IsNull()) { 5429 if (!other.IsMint() || other.IsNull()) {
5393 return false; 5430 return false;
5394 } 5431 }
5395 5432
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5446 OS::SNPrint(chars, len, kFormat, value()); 5483 OS::SNPrint(chars, len, kFormat, value());
5447 return chars; 5484 return chars;
5448 } 5485 }
5449 5486
5450 5487
5451 void Double::set_value(double value) const { 5488 void Double::set_value(double value) const {
5452 raw_ptr()->value_ = value; 5489 raw_ptr()->value_ = value;
5453 } 5490 }
5454 5491
5455 5492
5493 bool Double::Equals(double value) const {
5494 intptr_t value_offset = Double::value_offset();
5495 void* this_addr = reinterpret_cast<void*>(
5496 reinterpret_cast<uword>(this->raw_ptr()) + value_offset);
5497 void* other_addr = reinterpret_cast<void*>(&value);
5498 return memcmp(this_addr, other_addr, sizeof(value)) == 0;
5499 }
srdjan 2011/12/15 22:02:26 Can you use (*reinterpret_cast<int64_t*>(&value) t
siva 2011/12/15 23:42:54 If I do that I get : error: dereferencing type-pun
5500
5501
5502 bool Double::Equals(const Instance& other) const {
5503 if (this->raw() == other.raw()) {
5504 return true; // "===".
5505 }
5506 if (other.IsNull() || !other.IsDouble()) {
5507 return false;
5508 }
5509 Double& other_dbl = Double::Handle();
5510 other_dbl ^= other.raw();
5511 return Equals(other_dbl.value());
5512 }
5513
5514
5456 RawDouble* Double::New(double d, Heap::Space space) { 5515 RawDouble* Double::New(double d, Heap::Space space) {
5457 Isolate* isolate = Isolate::Current(); 5516 Isolate* isolate = Isolate::Current();
5458 const Class& cls = 5517 const Class& cls =
5459 Class::Handle(isolate->object_store()->double_class()); 5518 Class::Handle(isolate->object_store()->double_class());
5460 Double& result = Double::Handle(); 5519 Double& result = Double::Handle();
5461 { 5520 {
5462 RawObject* raw = Object::Allocate(cls, Double::InstanceSize(), space); 5521 RawObject* raw = Object::Allocate(cls, Double::InstanceSize(), space);
5463 NoGCScope no_gc; 5522 NoGCScope no_gc;
5464 result ^= raw; 5523 result ^= raw;
5465 } 5524 }
5466 result.set_value(d); 5525 result.set_value(d);
5467 return result.raw(); 5526 return result.raw();
5468 } 5527 }
5469 5528
5470 5529
5471 static bool IsWhiteSpace(char ch) { 5530 static bool IsWhiteSpace(char ch) {
5472 return ch == '\0' || ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t'; 5531 return ch == '\0' || ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t';
5473 } 5532 }
5474 5533
5475 5534
5535 static bool StringToDouble(const String& str, double* double_value) {
5536 ASSERT(double_value != NULL);
5537 // TODO(regis): For now, we use strtod to convert a string to double.
5538 const char* nptr = str.ToCString();
5539 char* endptr = NULL;
5540 *double_value = strtod(nptr, &endptr);
5541 // We do not treat overflow or underflow as an error and therefore do not
5542 // check errno for ERANGE.
5543 if (!IsWhiteSpace(*endptr)) {
5544 return false;
5545 }
5546 return true;
5547 }
5548
5549
5476 RawDouble* Double::New(const String& str, Heap::Space space) { 5550 RawDouble* Double::New(const String& str, Heap::Space space) {
5477 // TODO(regis): For now, we use strtod to convert a string to double. 5551 double double_value;
5478 const char* nptr = str.ToCString(); 5552 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(); 5553 return Double::Handle().raw();
5485 } 5554 }
5486 return New(double_value, space); 5555 return New(double_value, space);
5487 } 5556 }
5488 5557
5489 5558
5559 RawDouble* Double::NewCanonical(double value) {
5560 const Class& cls =
5561 Class::Handle(Isolate::Current()->object_store()->double_class());
5562 const Array& constants = Array::Handle(cls.constants());
5563 const intptr_t constants_len = constants.Length();
5564 // Linear search to see whether this value is already present in the
5565 // list of canonicalized constants.
5566 Double& canonical_value = Double::Handle();
5567 intptr_t index = 0;
5568 while (index < constants_len) {
5569 canonical_value ^= constants.At(index);
5570 if (canonical_value.IsNull()) {
5571 break;
5572 }
5573 if (canonical_value.Equals(value)) {
5574 return canonical_value.raw();
5575 }
5576 index++;
5577 }
5578 // The value needs to be added to the constants list. Grow the list if
5579 // it is full.
5580 canonical_value = Double::New(value, Heap::kOld);
5581 InsertCanonicalConstant(cls, constants, index, canonical_value);
5582 canonical_value.SetCanonical();
5583 return canonical_value.raw();
5584 }
5585
5586
5587 RawDouble* Double::NewCanonical(const String& str) {
5588 double double_value;
5589 if (!StringToDouble(str, &double_value)) {
5590 return Double::Handle().raw();
5591 }
5592 return NewCanonical(double_value);
5593 }
5594
5595
5490 const char* Double::ToCString() const { 5596 const char* Double::ToCString() const {
5491 if (isnan(value())) { 5597 if (isnan(value())) {
5492 return "NaN"; 5598 return "NaN";
5493 } 5599 }
5494 if (isinf(value())) { 5600 if (isinf(value())) {
5495 return value() < 0 ? "-Infinity" : "Infinity"; 5601 return value() < 0 ? "-Infinity" : "Infinity";
5496 } 5602 }
5497 const char* kFormat = "%f"; 5603 const char* kFormat = "%f";
5498 // Calculate the size of the string. 5604 // Calculate the size of the string.
5499 intptr_t len = OS::SNPrint(NULL, 0, kFormat, value()) + 1; 5605 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()); 7411 const String& str = String::Handle(pattern());
7306 const char* format = "JSRegExp: pattern=%s flags=%s"; 7412 const char* format = "JSRegExp: pattern=%s flags=%s";
7307 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); 7413 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags());
7308 char* chars = reinterpret_cast<char*>( 7414 char* chars = reinterpret_cast<char*>(
7309 Isolate::Current()->current_zone()->Allocate(len + 1)); 7415 Isolate::Current()->current_zone()->Allocate(len + 1));
7310 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); 7416 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags());
7311 return chars; 7417 return chars;
7312 } 7418 }
7313 7419
7314 } // namespace dart 7420 } // namespace dart
OLDNEW
« vm/object.h ('K') | « vm/object.h ('k') | vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698