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

Side by Side Diff: runtime/vm/object.cc

Issue 2974633003: Option to truncate integers to 64 bits, part 1 (core VM changes) (Closed)
Patch Set: Created 3 years, 5 months 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
OLDNEW
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
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.
regis 2017/07/07 20:10:30 I think you should throw now or it will be difficu
alexmarkov 2017/07/07 20:46:39 Throwing error will require modifying parser and l
regis 2017/07/07 21:46:53 OK.
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.
regis 2017/07/07 20:10:30 ditto
alexmarkov 2017/07/07 20:46:39 Acknowledged.
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.
regis 2017/07/07 20:10:30 ditto
alexmarkov 2017/07/07 20:46:39 Acknowledged.
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
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
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
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.
regis 2017/07/07 20:10:30 We will keep these constructors for the future Big
alexmarkov 2017/07/07 20:46:39 Acknowledged.
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.
regis 2017/07/07 20:10:30 ditto here and for all instances below.
alexmarkov 2017/07/07 20:46:39 Acknowledged.
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
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
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
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
OLDNEW
« runtime/vm/intermediate_language.h ('K') | « runtime/vm/intermediate_language_x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698