| 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 8709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8720 return 0; | 8720 return 0; |
| 8721 } | 8721 } |
| 8722 | 8722 |
| 8723 | 8723 |
| 8724 int Integer::CompareWith(const Integer& other) const { | 8724 int Integer::CompareWith(const Integer& other) const { |
| 8725 UNIMPLEMENTED(); | 8725 UNIMPLEMENTED(); |
| 8726 return 0; | 8726 return 0; |
| 8727 } | 8727 } |
| 8728 | 8728 |
| 8729 | 8729 |
| 8730 // Return the most compact presentation of an integer. |
| 8731 RawInteger* Integer::AsInteger(const Integer& value) { |
| 8732 if (value.IsSmi()) return value.raw(); |
| 8733 if (value.IsMint()) { |
| 8734 Mint& mint = Mint::Handle(); |
| 8735 mint ^= value.raw(); |
| 8736 if (Smi::IsValid64(mint.value())) { |
| 8737 return Smi::New(mint.value()); |
| 8738 } else { |
| 8739 return value.raw(); |
| 8740 } |
| 8741 } |
| 8742 ASSERT(value.IsBigint()); |
| 8743 Bigint& big_value = Bigint::Handle(); |
| 8744 big_value ^= value.raw(); |
| 8745 if (BigintOperations::FitsIntoSmi(big_value)) { |
| 8746 return BigintOperations::ToSmi(big_value); |
| 8747 } else if (BigintOperations::FitsIntoMint(big_value)) { |
| 8748 return Mint::New(BigintOperations::ToMint(big_value)); |
| 8749 } else { |
| 8750 return big_value.raw(); |
| 8751 } |
| 8752 } |
| 8753 |
| 8754 |
| 8755 RawInteger* Integer::BinaryOp(Token::Kind operation, |
| 8756 const Integer& left, |
| 8757 const Integer& right) { |
| 8758 // In 32-bit mode, the result of any operation between two Smis will fit in a |
| 8759 // 32-bit signed result, except the product of two Smis, which will be 64-bit. |
| 8760 // In 64-bit mode, the result of any operation between two Smis will fit in a |
| 8761 // 64-bit signed result, except the product of two Smis (unless the Smis are |
| 8762 // 32-bit or less). |
| 8763 if (left.IsSmi() && right.IsSmi()) { |
| 8764 Smi& left_smi = Smi::Handle(); |
| 8765 Smi& right_smi = Smi::Handle(); |
| 8766 left_smi ^= left.raw(); |
| 8767 right_smi ^= right.raw(); |
| 8768 const intptr_t left_value = left_smi.Value(); |
| 8769 const intptr_t right_value = right_smi.Value(); |
| 8770 switch (operation) { |
| 8771 case Token::kADD: |
| 8772 return Integer::New(left_value + right_value); |
| 8773 case Token::kSUB: |
| 8774 return Integer::New(left_value - right_value); |
| 8775 case Token::kMUL: { |
| 8776 if (Smi::kBits < 32) { |
| 8777 // In 32-bit mode, the product of two Smis fits in a 64-bit result. |
| 8778 return Integer::New(static_cast<int64_t>(left_value) * |
| 8779 static_cast<int64_t>(right_value)); |
| 8780 } else { |
| 8781 // In 64-bit mode, the product of two 32-bit signed integers fits in a |
| 8782 // 64-bit result. |
| 8783 ASSERT(sizeof(intptr_t) == sizeof(int64_t)); |
| 8784 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { |
| 8785 return Integer::New(left_value * right_value); |
| 8786 } |
| 8787 } |
| 8788 // Perform a Bigint multiplication below. |
| 8789 break; |
| 8790 } |
| 8791 case Token::kTRUNCDIV: |
| 8792 return Integer::New(left_value / right_value); |
| 8793 case Token::kMOD: { |
| 8794 const intptr_t remainder = left_value % right_value; |
| 8795 if (remainder < 0) { |
| 8796 if (right_value < 0) { |
| 8797 return Integer::New(remainder - right_value); |
| 8798 } else { |
| 8799 return Integer::New(remainder + right_value); |
| 8800 } |
| 8801 } |
| 8802 return Integer::New(remainder); |
| 8803 } |
| 8804 default: |
| 8805 UNIMPLEMENTED(); |
| 8806 } |
| 8807 } |
| 8808 // In 32-bit mode, the result of any operation between two 63-bit signed |
| 8809 // integers (or 32-bit for multiplication) will fit in a 64-bit signed result. |
| 8810 // In 64-bit mode, 63-bit signed integers are Smis, already processed above. |
| 8811 if ((Smi::kBits < 32) && !left.IsBigint() && !right.IsBigint()) { |
| 8812 const int64_t left_value = left.AsInt64Value(); |
| 8813 if (Utils::IsInt(63, left_value)) { |
| 8814 const int64_t right_value = right.AsInt64Value(); |
| 8815 if (Utils::IsInt(63, right_value)) { |
| 8816 switch (operation) { |
| 8817 case Token::kADD: |
| 8818 return Integer::New(left_value + right_value); |
| 8819 case Token::kSUB: |
| 8820 return Integer::New(left_value - right_value); |
| 8821 case Token::kMUL: { |
| 8822 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { |
| 8823 return Integer::New(left_value * right_value); |
| 8824 } |
| 8825 // Perform a Bigint multiplication below. |
| 8826 break; |
| 8827 } |
| 8828 case Token::kTRUNCDIV: |
| 8829 return Integer::New(left_value / right_value); |
| 8830 case Token::kMOD: { |
| 8831 const int64_t remainder = left_value % right_value; |
| 8832 if (remainder < 0) { |
| 8833 if (right_value < 0) { |
| 8834 return Integer::New(remainder - right_value); |
| 8835 } else { |
| 8836 return Integer::New(remainder + right_value); |
| 8837 } |
| 8838 } |
| 8839 return Integer::New(remainder); |
| 8840 } |
| 8841 default: |
| 8842 UNIMPLEMENTED(); |
| 8843 } |
| 8844 } |
| 8845 } |
| 8846 } |
| 8847 const Bigint& left_big = Bigint::Handle(Bigint::AsBigint(left)); |
| 8848 const Bigint& right_big = Bigint::Handle(Bigint::AsBigint(right)); |
| 8849 const Bigint& result = |
| 8850 Bigint::Handle(Bigint::BinaryOp(operation, left_big, right_big)); |
| 8851 return Integer::Handle(AsInteger(result)).raw(); |
| 8852 } |
| 8853 |
| 8854 |
| 8730 bool Smi::Equals(const Instance& other) const { | 8855 bool Smi::Equals(const Instance& other) const { |
| 8731 if (other.IsNull() || !other.IsSmi()) { | 8856 if (other.IsNull() || !other.IsSmi()) { |
| 8732 return false; | 8857 return false; |
| 8733 } | 8858 } |
| 8734 return (this->Value() == Smi::Cast(other).Value()); | 8859 return (this->Value() == Smi::Cast(other).Value()); |
| 8735 } | 8860 } |
| 8736 | 8861 |
| 8737 | 8862 |
| 8738 double Smi::AsDoubleValue() const { | 8863 double Smi::AsDoubleValue() const { |
| 8739 return static_cast<double>(this->Value()); | 8864 return static_cast<double>(this->Value()); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9022 return value() < 0 ? "-Infinity" : "Infinity"; | 9147 return value() < 0 ? "-Infinity" : "Infinity"; |
| 9023 } | 9148 } |
| 9024 const int kBufferSize = 128; | 9149 const int kBufferSize = 128; |
| 9025 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize); | 9150 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize); |
| 9026 buffer[kBufferSize - 1] = '\0'; | 9151 buffer[kBufferSize - 1] = '\0'; |
| 9027 DoubleToCString(value(), buffer, kBufferSize); | 9152 DoubleToCString(value(), buffer, kBufferSize); |
| 9028 return buffer; | 9153 return buffer; |
| 9029 } | 9154 } |
| 9030 | 9155 |
| 9031 | 9156 |
| 9157 // Returns value in form of a RawBigint. |
| 9158 RawBigint* Bigint::AsBigint(const Integer& value) { |
| 9159 ASSERT(!value.IsNull()); |
| 9160 if (value.IsSmi()) { |
| 9161 Smi& smi = Smi::Handle(); |
| 9162 smi ^= value.raw(); |
| 9163 return BigintOperations::NewFromSmi(smi); |
| 9164 } else if (value.IsMint()) { |
| 9165 Mint& mint = Mint::Handle(); |
| 9166 mint ^= value.raw(); |
| 9167 return BigintOperations::NewFromInt64(mint.value()); |
| 9168 } else { |
| 9169 ASSERT(value.IsBigint()); |
| 9170 Bigint& big = Bigint::Handle(); |
| 9171 big ^= value.raw(); |
| 9172 ASSERT(!BigintOperations::FitsIntoSmi(big)); |
| 9173 return big.raw(); |
| 9174 } |
| 9175 } |
| 9176 |
| 9177 |
| 9178 RawBigint* Bigint::BinaryOp(Token::Kind operation, |
| 9179 const Bigint& left, |
| 9180 const Bigint& right) { |
| 9181 switch (operation) { |
| 9182 case Token::kADD: |
| 9183 return BigintOperations::Add(left, right); |
| 9184 case Token::kSUB: |
| 9185 return BigintOperations::Subtract(left, right); |
| 9186 case Token::kMUL: |
| 9187 return BigintOperations::Multiply(left, right); |
| 9188 case Token::kTRUNCDIV: |
| 9189 return BigintOperations::Divide(left, right); |
| 9190 case Token::kMOD: |
| 9191 return BigintOperations::Modulo(left, right); |
| 9192 default: |
| 9193 UNIMPLEMENTED(); |
| 9194 return Bigint::null(); |
| 9195 } |
| 9196 } |
| 9197 |
| 9198 |
| 9032 bool Bigint::Equals(const Instance& other) const { | 9199 bool Bigint::Equals(const Instance& other) const { |
| 9033 if (this->raw() == other.raw()) { | 9200 if (this->raw() == other.raw()) { |
| 9034 // Both handles point to the same raw instance. | 9201 // Both handles point to the same raw instance. |
| 9035 return true; | 9202 return true; |
| 9036 } | 9203 } |
| 9037 | 9204 |
| 9038 if (!other.IsBigint() || other.IsNull()) { | 9205 if (!other.IsBigint() || other.IsNull()) { |
| 9039 return false; | 9206 return false; |
| 9040 } | 9207 } |
| 9041 | 9208 |
| (...skipping 2573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11615 } | 11782 } |
| 11616 return result.raw(); | 11783 return result.raw(); |
| 11617 } | 11784 } |
| 11618 | 11785 |
| 11619 | 11786 |
| 11620 const char* WeakProperty::ToCString() const { | 11787 const char* WeakProperty::ToCString() const { |
| 11621 return "_WeakProperty"; | 11788 return "_WeakProperty"; |
| 11622 } | 11789 } |
| 11623 | 11790 |
| 11624 } // namespace dart | 11791 } // namespace dart |
| OLD | NEW |