| 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 8734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8745 return 0; | 8745 return 0; |
| 8746 } | 8746 } |
| 8747 | 8747 |
| 8748 | 8748 |
| 8749 int Integer::CompareWith(const Integer& other) const { | 8749 int Integer::CompareWith(const Integer& other) const { |
| 8750 UNIMPLEMENTED(); | 8750 UNIMPLEMENTED(); |
| 8751 return 0; | 8751 return 0; |
| 8752 } | 8752 } |
| 8753 | 8753 |
| 8754 | 8754 |
| 8755 // Return the most compact presentation of an integer. |
| 8756 RawInteger* Integer::AsInteger(const Integer& value) { |
| 8757 if (value.IsSmi()) return value.raw(); |
| 8758 if (value.IsMint()) { |
| 8759 Mint& mint = Mint::Handle(); |
| 8760 mint ^= value.raw(); |
| 8761 if (Smi::IsValid64(mint.value())) { |
| 8762 return Smi::New(mint.value()); |
| 8763 } else { |
| 8764 return value.raw(); |
| 8765 } |
| 8766 } |
| 8767 ASSERT(value.IsBigint()); |
| 8768 Bigint& big_value = Bigint::Handle(); |
| 8769 big_value ^= value.raw(); |
| 8770 if (BigintOperations::FitsIntoSmi(big_value)) { |
| 8771 return BigintOperations::ToSmi(big_value); |
| 8772 } else if (BigintOperations::FitsIntoMint(big_value)) { |
| 8773 return Mint::New(BigintOperations::ToMint(big_value)); |
| 8774 } else { |
| 8775 return big_value.raw(); |
| 8776 } |
| 8777 } |
| 8778 |
| 8779 |
| 8780 RawInteger* Integer::BinaryOp(Token::Kind operation, |
| 8781 const Integer& left, |
| 8782 const Integer& right) { |
| 8783 // In 32-bit mode, the result of any operation between two Smis will fit in a |
| 8784 // 32-bit signed result, except the product of two Smis, which will be 64-bit. |
| 8785 // In 64-bit mode, the result of any operation between two Smis will fit in a |
| 8786 // 64-bit signed result, except the product of two Smis (unless the Smis are |
| 8787 // 32-bit or less). |
| 8788 if (left.IsSmi() && right.IsSmi()) { |
| 8789 Smi& left_smi = Smi::Handle(); |
| 8790 Smi& right_smi = Smi::Handle(); |
| 8791 left_smi ^= left.raw(); |
| 8792 right_smi ^= right.raw(); |
| 8793 const intptr_t left_value = left_smi.Value(); |
| 8794 const intptr_t right_value = right_smi.Value(); |
| 8795 switch (operation) { |
| 8796 case Token::kADD: |
| 8797 return Integer::New(left_value + right_value); |
| 8798 case Token::kSUB: |
| 8799 return Integer::New(left_value - right_value); |
| 8800 case Token::kMUL: { |
| 8801 if (Smi::kBits < 32) { |
| 8802 // In 32-bit mode, the product of two Smis fits in a 64-bit result. |
| 8803 return Integer::New(static_cast<int64_t>(left_value) * |
| 8804 static_cast<int64_t>(right_value)); |
| 8805 } else { |
| 8806 // In 64-bit mode, the product of two 32-bit signed integers fits in a |
| 8807 // 64-bit result. |
| 8808 ASSERT(sizeof(intptr_t) == sizeof(int64_t)); |
| 8809 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { |
| 8810 return Integer::New(left_value * right_value); |
| 8811 } |
| 8812 } |
| 8813 // Perform a Bigint multiplication below. |
| 8814 break; |
| 8815 } |
| 8816 case Token::kTRUNCDIV: |
| 8817 return Integer::New(left_value / right_value); |
| 8818 case Token::kMOD: { |
| 8819 const intptr_t remainder = left_value % right_value; |
| 8820 if (remainder < 0) { |
| 8821 if (right_value < 0) { |
| 8822 return Integer::New(remainder - right_value); |
| 8823 } else { |
| 8824 return Integer::New(remainder + right_value); |
| 8825 } |
| 8826 } |
| 8827 return Integer::New(remainder); |
| 8828 } |
| 8829 default: |
| 8830 UNIMPLEMENTED(); |
| 8831 } |
| 8832 } |
| 8833 // In 32-bit mode, the result of any operation between two 63-bit signed |
| 8834 // integers (or 32-bit for multiplication) will fit in a 64-bit signed result. |
| 8835 // In 64-bit mode, 63-bit signed integers are Smis, already processed above. |
| 8836 if ((Smi::kBits < 32) && !left.IsBigint() && !right.IsBigint()) { |
| 8837 const int64_t left_value = left.AsInt64Value(); |
| 8838 if (Utils::IsInt(63, left_value)) { |
| 8839 const int64_t right_value = right.AsInt64Value(); |
| 8840 if (Utils::IsInt(63, right_value)) { |
| 8841 switch (operation) { |
| 8842 case Token::kADD: |
| 8843 return Integer::New(left_value + right_value); |
| 8844 case Token::kSUB: |
| 8845 return Integer::New(left_value - right_value); |
| 8846 case Token::kMUL: { |
| 8847 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { |
| 8848 return Integer::New(left_value * right_value); |
| 8849 } |
| 8850 // Perform a Bigint multiplication below. |
| 8851 break; |
| 8852 } |
| 8853 case Token::kTRUNCDIV: |
| 8854 return Integer::New(left_value / right_value); |
| 8855 case Token::kMOD: { |
| 8856 const int64_t remainder = left_value % right_value; |
| 8857 if (remainder < 0) { |
| 8858 if (right_value < 0) { |
| 8859 return Integer::New(remainder - right_value); |
| 8860 } else { |
| 8861 return Integer::New(remainder + right_value); |
| 8862 } |
| 8863 } |
| 8864 return Integer::New(remainder); |
| 8865 } |
| 8866 default: |
| 8867 UNIMPLEMENTED(); |
| 8868 } |
| 8869 } |
| 8870 } |
| 8871 } |
| 8872 const Bigint& left_big = Bigint::Handle(Bigint::AsBigint(left)); |
| 8873 const Bigint& right_big = Bigint::Handle(Bigint::AsBigint(right)); |
| 8874 const Bigint& result = |
| 8875 Bigint::Handle(Bigint::BinaryOp(operation, left_big, right_big)); |
| 8876 return Integer::Handle(AsInteger(result)).raw(); |
| 8877 } |
| 8878 |
| 8879 |
| 8755 bool Smi::Equals(const Instance& other) const { | 8880 bool Smi::Equals(const Instance& other) const { |
| 8756 if (other.IsNull() || !other.IsSmi()) { | 8881 if (other.IsNull() || !other.IsSmi()) { |
| 8757 return false; | 8882 return false; |
| 8758 } | 8883 } |
| 8759 return (this->Value() == Smi::Cast(other).Value()); | 8884 return (this->Value() == Smi::Cast(other).Value()); |
| 8760 } | 8885 } |
| 8761 | 8886 |
| 8762 | 8887 |
| 8763 double Smi::AsDoubleValue() const { | 8888 double Smi::AsDoubleValue() const { |
| 8764 return static_cast<double>(this->Value()); | 8889 return static_cast<double>(this->Value()); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9047 return value() < 0 ? "-Infinity" : "Infinity"; | 9172 return value() < 0 ? "-Infinity" : "Infinity"; |
| 9048 } | 9173 } |
| 9049 const int kBufferSize = 128; | 9174 const int kBufferSize = 128; |
| 9050 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize); | 9175 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize); |
| 9051 buffer[kBufferSize - 1] = '\0'; | 9176 buffer[kBufferSize - 1] = '\0'; |
| 9052 DoubleToCString(value(), buffer, kBufferSize); | 9177 DoubleToCString(value(), buffer, kBufferSize); |
| 9053 return buffer; | 9178 return buffer; |
| 9054 } | 9179 } |
| 9055 | 9180 |
| 9056 | 9181 |
| 9182 // Returns value in form of a RawBigint. |
| 9183 RawBigint* Bigint::AsBigint(const Integer& value) { |
| 9184 ASSERT(!value.IsNull()); |
| 9185 if (value.IsSmi()) { |
| 9186 Smi& smi = Smi::Handle(); |
| 9187 smi ^= value.raw(); |
| 9188 return BigintOperations::NewFromSmi(smi); |
| 9189 } else if (value.IsMint()) { |
| 9190 Mint& mint = Mint::Handle(); |
| 9191 mint ^= value.raw(); |
| 9192 return BigintOperations::NewFromInt64(mint.value()); |
| 9193 } else { |
| 9194 ASSERT(value.IsBigint()); |
| 9195 Bigint& big = Bigint::Handle(); |
| 9196 big ^= value.raw(); |
| 9197 ASSERT(!BigintOperations::FitsIntoSmi(big)); |
| 9198 return big.raw(); |
| 9199 } |
| 9200 } |
| 9201 |
| 9202 |
| 9203 RawBigint* Bigint::BinaryOp(Token::Kind operation, |
| 9204 const Bigint& left, |
| 9205 const Bigint& right) { |
| 9206 switch (operation) { |
| 9207 case Token::kADD: |
| 9208 return BigintOperations::Add(left, right); |
| 9209 case Token::kSUB: |
| 9210 return BigintOperations::Subtract(left, right); |
| 9211 case Token::kMUL: |
| 9212 return BigintOperations::Multiply(left, right); |
| 9213 case Token::kTRUNCDIV: |
| 9214 return BigintOperations::Divide(left, right); |
| 9215 case Token::kMOD: |
| 9216 return BigintOperations::Modulo(left, right); |
| 9217 default: |
| 9218 UNIMPLEMENTED(); |
| 9219 return Bigint::null(); |
| 9220 } |
| 9221 } |
| 9222 |
| 9223 |
| 9057 bool Bigint::Equals(const Instance& other) const { | 9224 bool Bigint::Equals(const Instance& other) const { |
| 9058 if (this->raw() == other.raw()) { | 9225 if (this->raw() == other.raw()) { |
| 9059 // Both handles point to the same raw instance. | 9226 // Both handles point to the same raw instance. |
| 9060 return true; | 9227 return true; |
| 9061 } | 9228 } |
| 9062 | 9229 |
| 9063 if (!other.IsBigint() || other.IsNull()) { | 9230 if (!other.IsBigint() || other.IsNull()) { |
| 9064 return false; | 9231 return false; |
| 9065 } | 9232 } |
| 9066 | 9233 |
| (...skipping 2573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11640 } | 11807 } |
| 11641 return result.raw(); | 11808 return result.raw(); |
| 11642 } | 11809 } |
| 11643 | 11810 |
| 11644 | 11811 |
| 11645 const char* WeakProperty::ToCString() const { | 11812 const char* WeakProperty::ToCString() const { |
| 11646 return "_WeakProperty"; | 11813 return "_WeakProperty"; |
| 11647 } | 11814 } |
| 11648 | 11815 |
| 11649 } // namespace dart | 11816 } // namespace dart |
| OLD | NEW |