Chromium Code Reviews| 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/become.h" | 10 #include "vm/become.h" |
| (...skipping 18980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 18991 | 18991 |
| 18992 RawInteger* Integer::New(const String& str, Heap::Space space) { | 18992 RawInteger* Integer::New(const String& str, Heap::Space space) { |
| 18993 // We are not supposed to have integers represented as two byte strings. | 18993 // We are not supposed to have integers represented as two byte strings. |
| 18994 ASSERT(str.IsOneByteString()); | 18994 ASSERT(str.IsOneByteString()); |
| 18995 int64_t value; | 18995 int64_t value; |
| 18996 if (!OS::StringToInt64(str.ToCString(), &value)) { | 18996 if (!OS::StringToInt64(str.ToCString(), &value)) { |
| 18997 const Bigint& big = | 18997 const Bigint& big = |
| 18998 Bigint::Handle(Bigint::NewFromCString(str.ToCString(), space)); | 18998 Bigint::Handle(Bigint::NewFromCString(str.ToCString(), space)); |
| 18999 ASSERT(!big.FitsIntoSmi()); | 18999 ASSERT(!big.FitsIntoSmi()); |
| 19000 ASSERT(!big.FitsIntoInt64()); | 19000 ASSERT(!big.FitsIntoInt64()); |
| 19001 return big.raw(); | 19001 if (!FLAG_truncate_ints_to_64_bits) { |
| 19002 return big.raw(); | |
| 19003 } | |
| 19004 // TODO(alexmarkov): Throw error in FLAG_truncate_ints_to_64_bits mode. | |
|
siva
2017/07/07 23:11:20
You have this comment here and below of throwing a
alexmarkov
2017/07/10 16:58:12
Yes.
| |
| 19005 value = big.AsTruncatedInt64Value(); | |
| 19002 } | 19006 } |
| 19003 return Integer::New(value, space); | 19007 return Integer::New(value, space); |
| 19004 } | 19008 } |
| 19005 | 19009 |
| 19006 | 19010 |
| 19007 RawInteger* Integer::NewCanonical(const String& str) { | 19011 RawInteger* Integer::NewCanonical(const String& str) { |
| 19008 // We are not supposed to have integers represented as two byte strings. | 19012 // We are not supposed to have integers represented as two byte strings. |
| 19009 ASSERT(str.IsOneByteString()); | 19013 ASSERT(str.IsOneByteString()); |
| 19010 int64_t value; | 19014 int64_t value; |
| 19011 if (!OS::StringToInt64(str.ToCString(), &value)) { | 19015 if (!OS::StringToInt64(str.ToCString(), &value)) { |
| 19012 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str)); | 19016 const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str)); |
| 19013 ASSERT(!big.FitsIntoSmi()); | 19017 ASSERT(!big.FitsIntoSmi()); |
| 19014 ASSERT(!big.FitsIntoInt64()); | 19018 ASSERT(!big.FitsIntoInt64()); |
| 19015 return big.raw(); | 19019 if (!FLAG_truncate_ints_to_64_bits) { |
| 19020 return big.raw(); | |
| 19021 } | |
| 19022 // TODO(alexmarkov): Throw error in FLAG_truncate_ints_to_64_bits mode. | |
| 19023 value = big.AsTruncatedInt64Value(); | |
| 19016 } | 19024 } |
| 19017 if (Smi::IsValid(value)) { | 19025 if (Smi::IsValid(value)) { |
| 19018 return Smi::New(static_cast<intptr_t>(value)); | 19026 return Smi::New(static_cast<intptr_t>(value)); |
| 19019 } | 19027 } |
| 19020 return Mint::NewCanonical(value); | 19028 return Mint::NewCanonical(value); |
| 19021 } | 19029 } |
| 19022 | 19030 |
| 19023 | 19031 |
| 19024 RawInteger* Integer::New(int64_t value, Heap::Space space) { | 19032 RawInteger* Integer::New(int64_t value, Heap::Space space) { |
| 19025 const bool is_smi = Smi::IsValid(value); | 19033 const bool is_smi = Smi::IsValid(value); |
| 19026 if (is_smi) { | 19034 if (is_smi) { |
| 19027 return Smi::New(static_cast<intptr_t>(value)); | 19035 return Smi::New(static_cast<intptr_t>(value)); |
| 19028 } | 19036 } |
| 19029 return Mint::New(value, space); | 19037 return Mint::New(value, space); |
| 19030 } | 19038 } |
| 19031 | 19039 |
| 19032 | 19040 |
| 19033 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) { | 19041 RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) { |
| 19034 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { | 19042 if (value > static_cast<uint64_t>(Mint::kMaxValue)) { |
| 19035 return Bigint::NewFromUint64(value, space); | 19043 if (FLAG_truncate_ints_to_64_bits) { |
| 19044 // TODO(alexmarkov): Throw error in FLAG_truncate_ints_to_64_bits mode. | |
| 19045 return Integer::New(static_cast<int64_t>(value), space); | |
| 19046 } else { | |
| 19047 return Bigint::NewFromUint64(value, space); | |
| 19048 } | |
| 19036 } else { | 19049 } else { |
| 19037 return Integer::New(value, space); | 19050 return Integer::New(value, space); |
| 19038 } | 19051 } |
| 19039 } | 19052 } |
| 19040 | 19053 |
| 19041 | 19054 |
| 19042 bool Integer::Equals(const Instance& other) const { | 19055 bool Integer::Equals(const Instance& other) const { |
| 19043 // Integer is an abstract class. | 19056 // Integer is an abstract class. |
| 19044 UNREACHABLE(); | 19057 UNREACHABLE(); |
| 19045 return false; | 19058 return false; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19134 return Integer::New(left_value + right_value, space); | 19147 return Integer::New(left_value + right_value, space); |
| 19135 case Token::kSUB: | 19148 case Token::kSUB: |
| 19136 return Integer::New(left_value - right_value, space); | 19149 return Integer::New(left_value - right_value, space); |
| 19137 case Token::kMUL: { | 19150 case Token::kMUL: { |
| 19138 if (Smi::kBits < 32) { | 19151 if (Smi::kBits < 32) { |
| 19139 // In 32-bit mode, the product of two Smis fits in a 64-bit result. | 19152 // In 32-bit mode, the product of two Smis fits in a 64-bit result. |
| 19140 return Integer::New(static_cast<int64_t>(left_value) * | 19153 return Integer::New(static_cast<int64_t>(left_value) * |
| 19141 static_cast<int64_t>(right_value), | 19154 static_cast<int64_t>(right_value), |
| 19142 space); | 19155 space); |
| 19143 } else { | 19156 } else { |
| 19144 // In 64-bit mode, the product of two signed integers fits in a | |
| 19145 // 64-bit result if the sum of the highest bits of their absolute | |
| 19146 // values is smaller than 62. | |
| 19147 ASSERT(sizeof(intptr_t) == sizeof(int64_t)); | 19157 ASSERT(sizeof(intptr_t) == sizeof(int64_t)); |
| 19148 if ((Utils::HighestBit(left_value) + Utils::HighestBit(right_value)) < | 19158 if (FLAG_truncate_ints_to_64_bits) { |
| 19149 62) { | 19159 return Integer::New( |
| 19150 return Integer::New(left_value * right_value, space); | 19160 Utils::MulWithWrapAround(left_value, right_value), space); |
| 19161 } else { | |
| 19162 // In 64-bit mode, the product of two signed integers fits in a | |
| 19163 // 64-bit result if the sum of the highest bits of their absolute | |
| 19164 // values is smaller than 62. | |
| 19165 if ((Utils::HighestBit(left_value) + | |
| 19166 Utils::HighestBit(right_value)) < 62) { | |
| 19167 return Integer::New(left_value * right_value, space); | |
| 19168 } | |
| 19151 } | 19169 } |
| 19152 } | 19170 } |
| 19153 // Perform a Bigint multiplication below. | 19171 // Perform a Bigint multiplication below. |
| 19154 break; | 19172 break; |
| 19155 } | 19173 } |
| 19156 case Token::kTRUNCDIV: | 19174 case Token::kTRUNCDIV: |
| 19157 return Integer::New(left_value / right_value, space); | 19175 return Integer::New(left_value / right_value, space); |
| 19158 case Token::kMOD: { | 19176 case Token::kMOD: { |
| 19159 const intptr_t remainder = left_value % right_value; | 19177 const intptr_t remainder = left_value % right_value; |
| 19160 if (remainder < 0) { | 19178 if (remainder < 0) { |
| 19161 if (right_value < 0) { | 19179 if (right_value < 0) { |
| 19162 return Integer::New(remainder - right_value, space); | 19180 return Integer::New(remainder - right_value, space); |
| 19163 } else { | 19181 } else { |
| 19164 return Integer::New(remainder + right_value, space); | 19182 return Integer::New(remainder + right_value, space); |
| 19165 } | 19183 } |
| 19166 } | 19184 } |
| 19167 return Integer::New(remainder, space); | 19185 return Integer::New(remainder, space); |
| 19168 } | 19186 } |
| 19169 default: | 19187 default: |
| 19170 UNIMPLEMENTED(); | 19188 UNIMPLEMENTED(); |
| 19171 } | 19189 } |
| 19172 } | 19190 } |
| 19173 if (!IsBigint() && !other.IsBigint()) { | 19191 if (!IsBigint() && !other.IsBigint()) { |
| 19174 const int64_t left_value = AsInt64Value(); | 19192 const int64_t left_value = AsInt64Value(); |
| 19175 const int64_t right_value = other.AsInt64Value(); | 19193 const int64_t right_value = other.AsInt64Value(); |
| 19176 switch (operation) { | 19194 switch (operation) { |
| 19177 case Token::kADD: { | 19195 case Token::kADD: { |
| 19178 if (!Utils::WillAddOverflow(left_value, right_value)) { | 19196 if (FLAG_truncate_ints_to_64_bits) { |
| 19179 return Integer::New(left_value + right_value, space); | 19197 return Integer::New(Utils::AddWithWrapAround(left_value, right_value), |
| 19198 space); | |
| 19199 } else { | |
| 19200 if (!Utils::WillAddOverflow(left_value, right_value)) { | |
| 19201 return Integer::New(left_value + right_value, space); | |
| 19202 } | |
| 19180 } | 19203 } |
| 19181 break; | 19204 break; |
| 19182 } | 19205 } |
| 19183 case Token::kSUB: { | 19206 case Token::kSUB: { |
| 19184 if (!Utils::WillSubOverflow(left_value, right_value)) { | 19207 if (FLAG_truncate_ints_to_64_bits) { |
| 19185 return Integer::New(left_value - right_value, space); | 19208 return Integer::New(Utils::SubWithWrapAround(left_value, right_value), |
| 19209 space); | |
| 19210 } else { | |
| 19211 if (!Utils::WillSubOverflow(left_value, right_value)) { | |
| 19212 return Integer::New(left_value - right_value, space); | |
| 19213 } | |
| 19186 } | 19214 } |
| 19187 break; | 19215 break; |
| 19188 } | 19216 } |
| 19189 case Token::kMUL: { | 19217 case Token::kMUL: { |
| 19190 if ((Utils::HighestBit(left_value) + Utils::HighestBit(right_value)) < | 19218 if (FLAG_truncate_ints_to_64_bits) { |
| 19191 62) { | 19219 return Integer::New(Utils::MulWithWrapAround(left_value, right_value), |
| 19192 return Integer::New(left_value * right_value, space); | 19220 space); |
| 19221 } else { | |
| 19222 if ((Utils::HighestBit(left_value) + Utils::HighestBit(right_value)) < | |
| 19223 62) { | |
| 19224 return Integer::New(left_value * right_value, space); | |
| 19225 } | |
| 19193 } | 19226 } |
| 19194 break; | 19227 break; |
| 19195 } | 19228 } |
| 19196 case Token::kTRUNCDIV: { | 19229 case Token::kTRUNCDIV: { |
| 19197 if ((left_value != Mint::kMinValue) || (right_value != -1)) { | 19230 if ((left_value == Mint::kMinValue) && (right_value == -1)) { |
| 19231 // Division special case: overflow in int64_t. | |
| 19232 if (FLAG_truncate_ints_to_64_bits) { | |
| 19233 // MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE | |
| 19234 return Integer::New(Mint::kMinValue, space); | |
| 19235 } | |
| 19236 } else { | |
| 19198 return Integer::New(left_value / right_value, space); | 19237 return Integer::New(left_value / right_value, space); |
| 19199 } | 19238 } |
| 19200 break; | 19239 break; |
| 19201 } | 19240 } |
| 19202 case Token::kMOD: { | 19241 case Token::kMOD: { |
| 19203 const int64_t remainder = left_value % right_value; | 19242 const int64_t remainder = left_value % right_value; |
| 19204 if (remainder < 0) { | 19243 if (remainder < 0) { |
| 19205 if (right_value < 0) { | 19244 if (right_value < 0) { |
| 19206 return Integer::New(remainder - right_value, space); | 19245 return Integer::New(remainder - right_value, space); |
| 19207 } else { | 19246 } else { |
| 19208 return Integer::New(remainder + right_value, space); | 19247 return Integer::New(remainder + right_value, space); |
| 19209 } | 19248 } |
| 19210 } | 19249 } |
| 19211 return Integer::New(remainder, space); | 19250 return Integer::New(remainder, space); |
| 19212 } | 19251 } |
| 19213 default: | 19252 default: |
| 19214 UNIMPLEMENTED(); | 19253 UNIMPLEMENTED(); |
| 19215 } | 19254 } |
| 19216 } | 19255 } |
| 19256 ASSERT(!FLAG_truncate_ints_to_64_bits); | |
| 19217 return Integer::null(); // Notify caller that a bigint operation is required. | 19257 return Integer::null(); // Notify caller that a bigint operation is required. |
| 19218 } | 19258 } |
| 19219 | 19259 |
| 19220 | 19260 |
| 19221 static bool Are64bitOperands(const Integer& op1, const Integer& op2) { | 19261 static bool Are64bitOperands(const Integer& op1, const Integer& op2) { |
| 19222 return !op1.IsBigint() && !op2.IsBigint(); | 19262 return !op1.IsBigint() && !op2.IsBigint(); |
| 19223 } | 19263 } |
| 19224 | 19264 |
| 19225 | 19265 |
| 19226 RawInteger* Integer::BitOp(Token::Kind kind, | 19266 RawInteger* Integer::BitOp(Token::Kind kind, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 19252 case Token::kBIT_AND: | 19292 case Token::kBIT_AND: |
| 19253 return Integer::New(a & b, space); | 19293 return Integer::New(a & b, space); |
| 19254 case Token::kBIT_OR: | 19294 case Token::kBIT_OR: |
| 19255 return Integer::New(a | b, space); | 19295 return Integer::New(a | b, space); |
| 19256 case Token::kBIT_XOR: | 19296 case Token::kBIT_XOR: |
| 19257 return Integer::New(a ^ b, space); | 19297 return Integer::New(a ^ b, space); |
| 19258 default: | 19298 default: |
| 19259 UNIMPLEMENTED(); | 19299 UNIMPLEMENTED(); |
| 19260 } | 19300 } |
| 19261 } | 19301 } |
| 19302 ASSERT(!FLAG_truncate_ints_to_64_bits); | |
| 19262 return Integer::null(); // Notify caller that a bigint operation is required. | 19303 return Integer::null(); // Notify caller that a bigint operation is required. |
| 19263 } | 19304 } |
| 19264 | 19305 |
| 19265 | 19306 |
| 19266 // TODO(srdjan): Clarify handling of negative right operand in a shift op. | 19307 // TODO(srdjan): Clarify handling of negative right operand in a shift op. |
| 19267 RawInteger* Smi::ShiftOp(Token::Kind kind, | 19308 RawInteger* Smi::ShiftOp(Token::Kind kind, |
| 19268 const Smi& other, | 19309 const Smi& other, |
| 19269 Heap::Space space) const { | 19310 Heap::Space space) const { |
| 19270 intptr_t result = 0; | 19311 intptr_t result = 0; |
| 19271 const intptr_t left_value = Value(); | 19312 const intptr_t left_value = Value(); |
| 19272 const intptr_t right_value = other.Value(); | 19313 const intptr_t right_value = other.Value(); |
| 19273 ASSERT(right_value >= 0); | 19314 ASSERT(right_value >= 0); |
| 19274 switch (kind) { | 19315 switch (kind) { |
| 19275 case Token::kSHL: { | 19316 case Token::kSHL: { |
| 19276 if ((left_value == 0) || (right_value == 0)) { | 19317 if ((left_value == 0) || (right_value == 0)) { |
| 19277 return raw(); | 19318 return raw(); |
| 19278 } | 19319 } |
| 19279 { // Check for overflow. | 19320 { // Check for overflow. |
| 19280 int cnt = Utils::BitLength(left_value); | 19321 int cnt = Utils::BitLength(left_value); |
| 19281 if ((cnt + right_value) > Smi::kBits) { | 19322 if (right_value > (Smi::kBits - cnt)) { |
| 19282 if ((cnt + right_value) > Mint::kBits) { | 19323 if (FLAG_truncate_ints_to_64_bits) { |
| 19283 return Bigint::NewFromShiftedInt64(left_value, right_value, space); | 19324 return Integer::New( |
| 19325 Utils::ShiftLeftWithTruncation(left_value, right_value), space); | |
| 19284 } else { | 19326 } else { |
| 19285 int64_t left_64 = left_value; | 19327 if (right_value > (Mint::kBits - cnt)) { |
| 19286 return Integer::New(left_64 << right_value, space); | 19328 return Bigint::NewFromShiftedInt64(left_value, right_value, |
| 19329 space); | |
| 19330 } else { | |
| 19331 int64_t left_64 = left_value; | |
| 19332 return Integer::New(left_64 << right_value, space); | |
| 19333 } | |
| 19287 } | 19334 } |
| 19288 } | 19335 } |
| 19289 } | 19336 } |
| 19290 result = left_value << right_value; | 19337 result = left_value << right_value; |
| 19291 break; | 19338 break; |
| 19292 } | 19339 } |
| 19293 case Token::kSHR: { | 19340 case Token::kSHR: { |
| 19294 const intptr_t shift_amount = | 19341 const intptr_t shift_amount = |
| 19295 (right_value >= kBitsPerWord) ? (kBitsPerWord - 1) : right_value; | 19342 (right_value >= kBitsPerWord) ? (kBitsPerWord - 1) : right_value; |
| 19296 result = left_value >> shift_amount; | 19343 result = left_value >> shift_amount; |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19698 ASSERT(!digits_.IsNull()); | 19745 ASSERT(!digits_.IsNull()); |
| 19699 set_digits(digits_); | 19746 set_digits(digits_); |
| 19700 } else { | 19747 } else { |
| 19701 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); | 19748 ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current())); |
| 19702 } | 19749 } |
| 19703 return true; | 19750 return true; |
| 19704 } | 19751 } |
| 19705 | 19752 |
| 19706 | 19753 |
| 19707 RawBigint* Bigint::New(Heap::Space space) { | 19754 RawBigint* Bigint::New(Heap::Space space) { |
| 19755 // TODO(alexmarkov): Throw error or assert in --truncate-ints-to-64-bits mode. | |
| 19708 Thread* thread = Thread::Current(); | 19756 Thread* thread = Thread::Current(); |
| 19709 Zone* zone = thread->zone(); | 19757 Zone* zone = thread->zone(); |
| 19710 Isolate* isolate = thread->isolate(); | 19758 Isolate* isolate = thread->isolate(); |
| 19711 ASSERT(isolate->object_store()->bigint_class() != Class::null()); | 19759 ASSERT(isolate->object_store()->bigint_class() != Class::null()); |
| 19712 Bigint& result = Bigint::Handle(zone); | 19760 Bigint& result = Bigint::Handle(zone); |
| 19713 { | 19761 { |
| 19714 RawObject* raw = | 19762 RawObject* raw = |
| 19715 Object::Allocate(Bigint::kClassId, Bigint::InstanceSize(), space); | 19763 Object::Allocate(Bigint::kClassId, Bigint::InstanceSize(), space); |
| 19716 NoSafepointScope no_safepoint; | 19764 NoSafepointScope no_safepoint; |
| 19717 result ^= raw; | 19765 result ^= raw; |
| 19718 } | 19766 } |
| 19719 result.SetNeg(false); | 19767 result.SetNeg(false); |
| 19720 result.SetUsed(0); | 19768 result.SetUsed(0); |
| 19721 result.set_digits( | 19769 result.set_digits( |
| 19722 TypedData::Handle(zone, TypedData::EmptyUint32Array(thread))); | 19770 TypedData::Handle(zone, TypedData::EmptyUint32Array(thread))); |
| 19723 return result.raw(); | 19771 return result.raw(); |
| 19724 } | 19772 } |
| 19725 | 19773 |
| 19726 | 19774 |
| 19727 RawBigint* Bigint::New(bool neg, | 19775 RawBigint* Bigint::New(bool neg, |
| 19728 intptr_t used, | 19776 intptr_t used, |
| 19729 const TypedData& digits, | 19777 const TypedData& digits, |
| 19730 Heap::Space space) { | 19778 Heap::Space space) { |
| 19779 // TODO(alexmarkov): Throw error or assert in --truncate-ints-to-64-bits mode. | |
| 19731 ASSERT((used == 0) || | 19780 ASSERT((used == 0) || |
| 19732 (!digits.IsNull() && (digits.Length() >= (used + (used & 1))))); | 19781 (!digits.IsNull() && (digits.Length() >= (used + (used & 1))))); |
| 19733 Thread* thread = Thread::Current(); | 19782 Thread* thread = Thread::Current(); |
| 19734 Zone* zone = thread->zone(); | 19783 Zone* zone = thread->zone(); |
| 19735 Isolate* isolate = thread->isolate(); | 19784 Isolate* isolate = thread->isolate(); |
| 19736 ASSERT(isolate->object_store()->bigint_class() != Class::null()); | 19785 ASSERT(isolate->object_store()->bigint_class() != Class::null()); |
| 19737 Bigint& result = Bigint::Handle(zone); | 19786 Bigint& result = Bigint::Handle(zone); |
| 19738 { | 19787 { |
| 19739 RawObject* raw = | 19788 RawObject* raw = |
| 19740 Object::Allocate(Bigint::kClassId, Bigint::InstanceSize(), space); | 19789 Object::Allocate(Bigint::kClassId, Bigint::InstanceSize(), space); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 19760 } | 19809 } |
| 19761 result.SetNeg(neg); | 19810 result.SetNeg(neg); |
| 19762 result.SetUsed(used); | 19811 result.SetUsed(used); |
| 19763 return result.raw(); | 19812 return result.raw(); |
| 19764 } | 19813 } |
| 19765 | 19814 |
| 19766 | 19815 |
| 19767 RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) { | 19816 RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) { |
| 19768 // Currently only used to convert Smi or Mint to hex String, therefore do | 19817 // Currently only used to convert Smi or Mint to hex String, therefore do |
| 19769 // not throw RangeError if --limit-ints-to-64-bits. | 19818 // not throw RangeError if --limit-ints-to-64-bits. |
| 19819 // TODO(alexmarkov): Throw error or assert in --truncate-ints-to-64-bits mode. | |
| 19770 const TypedData& digits = TypedData::Handle(NewDigits(2, space)); | 19820 const TypedData& digits = TypedData::Handle(NewDigits(2, space)); |
| 19771 bool neg; | 19821 bool neg; |
| 19772 uint64_t abs_value; | 19822 uint64_t abs_value; |
| 19773 if (value < 0) { | 19823 if (value < 0) { |
| 19774 neg = true; | 19824 neg = true; |
| 19775 abs_value = -value; | 19825 abs_value = -value; |
| 19776 } else { | 19826 } else { |
| 19777 neg = false; | 19827 neg = false; |
| 19778 abs_value = value; | 19828 abs_value = value; |
| 19779 } | 19829 } |
| 19780 SetDigitAt(digits, 0, static_cast<uint32_t>(abs_value)); | 19830 SetDigitAt(digits, 0, static_cast<uint32_t>(abs_value)); |
| 19781 SetDigitAt(digits, 1, static_cast<uint32_t>(abs_value >> 32)); | 19831 SetDigitAt(digits, 1, static_cast<uint32_t>(abs_value >> 32)); |
| 19782 return New(neg, 2, digits, space); | 19832 return New(neg, 2, digits, space); |
| 19783 } | 19833 } |
| 19784 | 19834 |
| 19785 | 19835 |
| 19786 RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) { | 19836 RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) { |
| 19837 // TODO(alexmarkov): Throw error or assert in --truncate-ints-to-64-bits mode. | |
| 19787 if (FLAG_limit_ints_to_64_bits) { | 19838 if (FLAG_limit_ints_to_64_bits) { |
| 19788 Exceptions::ThrowRangeErrorMsg( | 19839 Exceptions::ThrowRangeErrorMsg( |
| 19789 "Integer operand requires conversion to Bigint"); | 19840 "Integer operand requires conversion to Bigint"); |
| 19790 } | 19841 } |
| 19791 const TypedData& digits = TypedData::Handle(NewDigits(2, space)); | 19842 const TypedData& digits = TypedData::Handle(NewDigits(2, space)); |
| 19792 SetDigitAt(digits, 0, static_cast<uint32_t>(value)); | 19843 SetDigitAt(digits, 0, static_cast<uint32_t>(value)); |
| 19793 SetDigitAt(digits, 1, static_cast<uint32_t>(value >> 32)); | 19844 SetDigitAt(digits, 1, static_cast<uint32_t>(value >> 32)); |
| 19794 return New(false, 2, digits, space); | 19845 return New(false, 2, digits, space); |
| 19795 } | 19846 } |
| 19796 | 19847 |
| 19797 | 19848 |
| 19798 RawBigint* Bigint::NewFromShiftedInt64(int64_t value, | 19849 RawBigint* Bigint::NewFromShiftedInt64(int64_t value, |
| 19799 intptr_t shift, | 19850 intptr_t shift, |
| 19800 Heap::Space space) { | 19851 Heap::Space space) { |
| 19852 // TODO(alexmarkov): Throw error or assert in --truncate-ints-to-64-bits mode. | |
| 19801 if (FLAG_limit_ints_to_64_bits) { | 19853 if (FLAG_limit_ints_to_64_bits) { |
| 19802 // The allocated Bigint value is not necessarily out of range, but it may | 19854 // The allocated Bigint value is not necessarily out of range, but it may |
| 19803 // be used as an operand in an operation resulting in a Bigint. | 19855 // be used as an operand in an operation resulting in a Bigint. |
| 19804 Exceptions::ThrowRangeErrorMsg( | 19856 Exceptions::ThrowRangeErrorMsg( |
| 19805 "Integer operand requires conversion to Bigint"); | 19857 "Integer operand requires conversion to Bigint"); |
| 19806 } | 19858 } |
| 19807 ASSERT(kBitsPerDigit == 32); | 19859 ASSERT(kBitsPerDigit == 32); |
| 19808 ASSERT(shift >= 0); | 19860 ASSERT(shift >= 0); |
| 19809 const intptr_t digit_shift = shift / kBitsPerDigit; | 19861 const intptr_t digit_shift = shift / kBitsPerDigit; |
| 19810 const intptr_t bit_shift = shift % kBitsPerDigit; | 19862 const intptr_t bit_shift = shift % kBitsPerDigit; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 19828 static_cast<uint32_t>(abs_value >> (32 - bit_shift))); | 19880 static_cast<uint32_t>(abs_value >> (32 - bit_shift))); |
| 19829 SetDigitAt(digits, 2 + digit_shift, | 19881 SetDigitAt(digits, 2 + digit_shift, |
| 19830 (bit_shift == 0) ? 0 : static_cast<uint32_t>(abs_value >> | 19882 (bit_shift == 0) ? 0 : static_cast<uint32_t>(abs_value >> |
| 19831 (64 - bit_shift))); | 19883 (64 - bit_shift))); |
| 19832 return New(neg, used, digits, space); | 19884 return New(neg, used, digits, space); |
| 19833 } | 19885 } |
| 19834 | 19886 |
| 19835 | 19887 |
| 19836 RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) { | 19888 RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) { |
| 19837 // Allow parser to scan Bigint literal, even with --limit-ints-to-64-bits. | 19889 // Allow parser to scan Bigint literal, even with --limit-ints-to-64-bits. |
| 19890 // TODO(alexmarkov): Throw error or assert in --truncate-ints-to-64-bits mode. | |
| 19838 ASSERT(str != NULL); | 19891 ASSERT(str != NULL); |
| 19839 bool neg = false; | 19892 bool neg = false; |
| 19840 TypedData& digits = TypedData::Handle(); | 19893 TypedData& digits = TypedData::Handle(); |
| 19841 if (str[0] == '-') { | 19894 if (str[0] == '-') { |
| 19842 ASSERT(str[1] != '-'); | 19895 ASSERT(str[1] != '-'); |
| 19843 neg = true; | 19896 neg = true; |
| 19844 str++; | 19897 str++; |
| 19845 } | 19898 } |
| 19846 intptr_t used; | 19899 intptr_t used; |
| 19847 const intptr_t str_length = strlen(str); | 19900 const intptr_t str_length = strlen(str); |
| 19848 if ((str_length >= 2) && (str[0] == '0') && | 19901 if ((str_length >= 2) && (str[0] == '0') && |
| 19849 ((str[1] == 'x') || (str[1] == 'X'))) { | 19902 ((str[1] == 'x') || (str[1] == 'X'))) { |
| 19850 digits = NewDigitsFromHexCString(&str[2], &used, space); | 19903 digits = NewDigitsFromHexCString(&str[2], &used, space); |
| 19851 } else { | 19904 } else { |
| 19852 digits = NewDigitsFromDecCString(str, &used, space); | 19905 digits = NewDigitsFromDecCString(str, &used, space); |
| 19853 } | 19906 } |
| 19854 return New(neg, used, digits, space); | 19907 return New(neg, used, digits, space); |
| 19855 } | 19908 } |
| 19856 | 19909 |
| 19857 | 19910 |
| 19858 RawBigint* Bigint::NewCanonical(const String& str) { | 19911 RawBigint* Bigint::NewCanonical(const String& str) { |
| 19859 // Allow parser to scan Bigint literal, even with --limit-ints-to-64-bits. | 19912 // Allow parser to scan Bigint literal, even with --limit-ints-to-64-bits. |
| 19913 // TODO(alexmarkov): Throw error or assert in --truncate-ints-to-64-bits mode. | |
| 19860 Thread* thread = Thread::Current(); | 19914 Thread* thread = Thread::Current(); |
| 19861 Zone* zone = thread->zone(); | 19915 Zone* zone = thread->zone(); |
| 19862 Isolate* isolate = thread->isolate(); | 19916 Isolate* isolate = thread->isolate(); |
| 19863 const Bigint& value = | 19917 const Bigint& value = |
| 19864 Bigint::Handle(zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld)); | 19918 Bigint::Handle(zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld)); |
| 19865 const Class& cls = | 19919 const Class& cls = |
| 19866 Class::Handle(zone, isolate->object_store()->bigint_class()); | 19920 Class::Handle(zone, isolate->object_store()->bigint_class()); |
| 19867 intptr_t index = 0; | 19921 intptr_t index = 0; |
| 19868 Bigint& canonical_value = Bigint::Handle(zone); | 19922 Bigint& canonical_value = Bigint::Handle(zone); |
| 19869 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index); | 19923 canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index); |
| (...skipping 3766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 23636 return UserTag::null(); | 23690 return UserTag::null(); |
| 23637 } | 23691 } |
| 23638 | 23692 |
| 23639 | 23693 |
| 23640 const char* UserTag::ToCString() const { | 23694 const char* UserTag::ToCString() const { |
| 23641 const String& tag_label = String::Handle(label()); | 23695 const String& tag_label = String::Handle(label()); |
| 23642 return tag_label.ToCString(); | 23696 return tag_label.ToCString(); |
| 23643 } | 23697 } |
| 23644 | 23698 |
| 23645 } // namespace dart | 23699 } // namespace dart |
| OLD | NEW |