Chromium Code Reviews| 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 4993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |