| 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/bootstrap_natives.h" | 5 #include "vm/bootstrap_natives.h" |
| 6 | 6 |
| 7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/exceptions.h" | 9 #include "vm/exceptions.h" |
| 10 #include "vm/native_entry.h" | 10 #include "vm/native_entry.h" |
| 11 #include "vm/object.h" | 11 #include "vm/object.h" |
| 12 | 12 |
| 13 namespace dart { | 13 namespace dart { |
| 14 | 14 |
| 15 DEFINE_FLAG(bool, trace_intrinsified_natives, false, | 15 DEFINE_FLAG(bool, trace_intrinsified_natives, false, |
| 16 "Report if any of the intrinsified natives are called"); | 16 "Report if any of the intrinsified natives are called"); |
| 17 | 17 |
| 18 // Smi natives. | 18 // Smi natives. |
| 19 | 19 |
| 20 static bool Are64bitOperands(const Integer& op1, const Integer& op2) { | |
| 21 return !op1.IsBigint() && !op2.IsBigint(); | |
| 22 } | |
| 23 | |
| 24 | |
| 25 static RawInteger* IntegerBitOperation(Token::Kind kind, | |
| 26 const Integer& op1_int, | |
| 27 const Integer& op2_int) { | |
| 28 if (op1_int.IsSmi() && op2_int.IsSmi()) { | |
| 29 Smi& op1 = Smi::Handle(); | |
| 30 Smi& op2 = Smi::Handle(); | |
| 31 op1 ^= op1_int.raw(); | |
| 32 op2 ^= op2_int.raw(); | |
| 33 intptr_t result = 0; | |
| 34 switch (kind) { | |
| 35 case Token::kBIT_AND: | |
| 36 result = op1.Value() & op2.Value(); | |
| 37 break; | |
| 38 case Token::kBIT_OR: | |
| 39 result = op1.Value() | op2.Value(); | |
| 40 break; | |
| 41 case Token::kBIT_XOR: | |
| 42 result = op1.Value() ^ op2.Value(); | |
| 43 break; | |
| 44 default: | |
| 45 UNIMPLEMENTED(); | |
| 46 } | |
| 47 ASSERT(Smi::IsValid(result)); | |
| 48 return Smi::New(result); | |
| 49 } else if (Are64bitOperands(op1_int, op2_int)) { | |
| 50 int64_t a = op1_int.AsInt64Value(); | |
| 51 int64_t b = op2_int.AsInt64Value(); | |
| 52 switch (kind) { | |
| 53 case Token::kBIT_AND: | |
| 54 return Integer::New(a & b); | |
| 55 case Token::kBIT_OR: | |
| 56 return Integer::New(a | b); | |
| 57 case Token::kBIT_XOR: | |
| 58 return Integer::New(a ^ b); | |
| 59 default: | |
| 60 UNIMPLEMENTED(); | |
| 61 } | |
| 62 } else { | |
| 63 Bigint& op1 = Bigint::Handle(op1_int.AsBigint()); | |
| 64 Bigint& op2 = Bigint::Handle(op2_int.AsBigint()); | |
| 65 switch (kind) { | |
| 66 case Token::kBIT_AND: | |
| 67 return BigintOperations::BitAnd(op1, op2); | |
| 68 case Token::kBIT_OR: | |
| 69 return BigintOperations::BitOr(op1, op2); | |
| 70 case Token::kBIT_XOR: | |
| 71 return BigintOperations::BitXor(op1, op2); | |
| 72 default: | |
| 73 UNIMPLEMENTED(); | |
| 74 } | |
| 75 } | |
| 76 return Integer::null(); | |
| 77 } | |
| 78 | |
| 79 | |
| 80 // Returns false if integer is in wrong representation, e.g., as is a Bigint | 20 // Returns false if integer is in wrong representation, e.g., as is a Bigint |
| 81 // when it could have been a Smi. | 21 // when it could have been a Smi. |
| 82 static bool CheckInteger(const Integer& i) { | 22 static bool CheckInteger(const Integer& i) { |
| 83 if (i.IsBigint()) { | 23 if (i.IsBigint()) { |
| 84 Bigint& bigint = Bigint::Handle(); | 24 Bigint& bigint = Bigint::Handle(); |
| 85 bigint ^= i.raw(); | 25 bigint ^= i.raw(); |
| 86 return !BigintOperations::FitsIntoSmi(bigint) && | 26 return !BigintOperations::FitsIntoSmi(bigint) && |
| 87 !BigintOperations::FitsIntoMint(bigint); | 27 !BigintOperations::FitsIntoMint(bigint); |
| 88 } | 28 } |
| 89 if (i.IsMint()) { | 29 if (i.IsMint()) { |
| 90 Mint& mint = Mint::Handle(); | 30 Mint& mint = Mint::Handle(); |
| 91 mint ^= i.raw(); | 31 mint ^= i.raw(); |
| 92 return !Smi::IsValid64(mint.value()); | 32 return !Smi::IsValid64(mint.value()); |
| 93 } | 33 } |
| 94 return true; | 34 return true; |
| 95 } | 35 } |
| 96 | 36 |
| 97 | 37 |
| 98 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { | 38 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { |
| 99 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 39 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 100 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 40 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 101 ASSERT(CheckInteger(right)); | 41 ASSERT(CheckInteger(right)); |
| 102 ASSERT(CheckInteger(left)); | 42 ASSERT(CheckInteger(left)); |
| 103 if (FLAG_trace_intrinsified_natives) { | 43 if (FLAG_trace_intrinsified_natives) { |
| 104 OS::Print("Integer_bitAndFromInteger %s & %s\n", | 44 OS::Print("Integer_bitAndFromInteger %s & %s\n", |
| 105 right.ToCString(), left.ToCString()); | 45 right.ToCString(), left.ToCString()); |
| 106 } | 46 } |
| 107 Integer& result = Integer::Handle( | 47 Integer& result = |
| 108 IntegerBitOperation(Token::kBIT_AND, left, right)); | 48 Integer::Handle(left.BitOp(Token::kBIT_AND, right)); |
| 109 return result.AsInteger(); | 49 return result.AsInteger(); |
| 110 } | 50 } |
| 111 | 51 |
| 112 | 52 |
| 113 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { | 53 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { |
| 114 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 54 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 115 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 55 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 116 ASSERT(CheckInteger(right)); | 56 ASSERT(CheckInteger(right)); |
| 117 ASSERT(CheckInteger(left)); | 57 ASSERT(CheckInteger(left)); |
| 118 if (FLAG_trace_intrinsified_natives) { | 58 if (FLAG_trace_intrinsified_natives) { |
| 119 OS::Print("Integer_bitOrFromInteger %s | %s\n", | 59 OS::Print("Integer_bitOrFromInteger %s | %s\n", |
| 120 left.ToCString(), right.ToCString()); | 60 left.ToCString(), right.ToCString()); |
| 121 } | 61 } |
| 122 Integer& result = Integer::Handle( | 62 Integer& result = |
| 123 IntegerBitOperation(Token::kBIT_OR, left, right)); | 63 Integer::Handle(left.BitOp(Token::kBIT_OR, right)); |
| 124 return result.AsInteger(); | 64 return result.AsInteger(); |
| 125 } | 65 } |
| 126 | 66 |
| 127 | 67 |
| 128 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { | 68 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { |
| 129 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 69 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 130 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 70 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 131 ASSERT(CheckInteger(right)); | 71 ASSERT(CheckInteger(right)); |
| 132 ASSERT(CheckInteger(left)); | 72 ASSERT(CheckInteger(left)); |
| 133 if (FLAG_trace_intrinsified_natives) { | 73 if (FLAG_trace_intrinsified_natives) { |
| 134 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", | 74 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", |
| 135 left.ToCString(), right.ToCString()); | 75 left.ToCString(), right.ToCString()); |
| 136 } | 76 } |
| 137 Integer& result = Integer::Handle( | 77 Integer& result = |
| 138 IntegerBitOperation(Token::kBIT_XOR, left, right)); | 78 Integer::Handle(left.BitOp(Token::kBIT_XOR, right)); |
| 139 return result.AsInteger(); | 79 return result.AsInteger(); |
| 140 } | 80 } |
| 141 | 81 |
| 142 | 82 |
| 143 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { | 83 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { |
| 144 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 84 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 145 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 85 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 146 ASSERT(CheckInteger(right_int)); | 86 ASSERT(CheckInteger(right_int)); |
| 147 ASSERT(CheckInteger(left_int)); | 87 ASSERT(CheckInteger(left_int)); |
| 148 if (FLAG_trace_intrinsified_natives) { | 88 if (FLAG_trace_intrinsified_natives) { |
| 149 OS::Print("Integer_addFromInteger %s + %s\n", | 89 OS::Print("Integer_addFromInteger %s + %s\n", |
| 150 left_int.ToCString(), right_int.ToCString()); | 90 left_int.ToCString(), right_int.ToCString()); |
| 151 } | 91 } |
| 152 return left_int.BinaryOp(Token::kADD, right_int); | 92 return left_int.ArithmeticOp(Token::kADD, right_int); |
| 153 } | 93 } |
| 154 | 94 |
| 155 | 95 |
| 156 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { | 96 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { |
| 157 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 97 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 158 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 98 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 159 ASSERT(CheckInteger(right_int)); | 99 ASSERT(CheckInteger(right_int)); |
| 160 ASSERT(CheckInteger(left_int)); | 100 ASSERT(CheckInteger(left_int)); |
| 161 if (FLAG_trace_intrinsified_natives) { | 101 if (FLAG_trace_intrinsified_natives) { |
| 162 OS::Print("Integer_subFromInteger %s - %s\n", | 102 OS::Print("Integer_subFromInteger %s - %s\n", |
| 163 left_int.ToCString(), right_int.ToCString()); | 103 left_int.ToCString(), right_int.ToCString()); |
| 164 } | 104 } |
| 165 return left_int.BinaryOp(Token::kSUB, right_int); | 105 return left_int.ArithmeticOp(Token::kSUB, right_int); |
| 166 } | 106 } |
| 167 | 107 |
| 168 | 108 |
| 169 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { | 109 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { |
| 170 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 110 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 171 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 111 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 172 ASSERT(CheckInteger(right_int)); | 112 ASSERT(CheckInteger(right_int)); |
| 173 ASSERT(CheckInteger(left_int)); | 113 ASSERT(CheckInteger(left_int)); |
| 174 if (FLAG_trace_intrinsified_natives) { | 114 if (FLAG_trace_intrinsified_natives) { |
| 175 OS::Print("Integer_mulFromInteger %s * %s\n", | 115 OS::Print("Integer_mulFromInteger %s * %s\n", |
| 176 left_int.ToCString(), right_int.ToCString()); | 116 left_int.ToCString(), right_int.ToCString()); |
| 177 } | 117 } |
| 178 return left_int.BinaryOp(Token::kMUL, right_int); | 118 return left_int.ArithmeticOp(Token::kMUL, right_int); |
| 179 } | 119 } |
| 180 | 120 |
| 181 | 121 |
| 182 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { | 122 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { |
| 183 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 123 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 184 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 124 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 185 ASSERT(CheckInteger(right_int)); | 125 ASSERT(CheckInteger(right_int)); |
| 186 ASSERT(CheckInteger(left_int)); | 126 ASSERT(CheckInteger(left_int)); |
| 187 ASSERT(!right_int.IsZero()); | 127 ASSERT(!right_int.IsZero()); |
| 188 return left_int.BinaryOp(Token::kTRUNCDIV, right_int); | 128 return left_int.ArithmeticOp(Token::kTRUNCDIV, right_int); |
| 189 } | 129 } |
| 190 | 130 |
| 191 | 131 |
| 192 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { | 132 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { |
| 193 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 133 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 194 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 134 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 195 ASSERT(CheckInteger(right_int)); | 135 ASSERT(CheckInteger(right_int)); |
| 196 ASSERT(CheckInteger(right_int)); | 136 ASSERT(CheckInteger(right_int)); |
| 197 if (FLAG_trace_intrinsified_natives) { | 137 if (FLAG_trace_intrinsified_natives) { |
| 198 OS::Print("Integer_moduloFromInteger %s mod %s\n", | 138 OS::Print("Integer_moduloFromInteger %s mod %s\n", |
| 199 left_int.ToCString(), right_int.ToCString()); | 139 left_int.ToCString(), right_int.ToCString()); |
| 200 } | 140 } |
| 201 if (right_int.IsZero()) { | 141 if (right_int.IsZero()) { |
| 202 // Should have been caught before calling into runtime. | 142 // Should have been caught before calling into runtime. |
| 203 UNIMPLEMENTED(); | 143 UNIMPLEMENTED(); |
| 204 } | 144 } |
| 205 return left_int.BinaryOp(Token::kMOD, right_int); | 145 return left_int.ArithmeticOp(Token::kMOD, right_int); |
| 206 } | 146 } |
| 207 | 147 |
| 208 | 148 |
| 209 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { | 149 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { |
| 210 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 150 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 211 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 151 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 212 ASSERT(CheckInteger(right)); | 152 ASSERT(CheckInteger(right)); |
| 213 ASSERT(CheckInteger(left)); | 153 ASSERT(CheckInteger(left)); |
| 214 if (FLAG_trace_intrinsified_natives) { | 154 if (FLAG_trace_intrinsified_natives) { |
| 215 OS::Print("Integer_greaterThanFromInteger %s > %s\n", | 155 OS::Print("Integer_greaterThanFromInteger %s > %s\n", |
| 216 left.ToCString(), right.ToCString()); | 156 left.ToCString(), right.ToCString()); |
| 217 } | 157 } |
| 218 return Bool::Get(left.CompareWith(right) == 1); | 158 return Bool::Get(left.CompareWith(right) == 1); |
| 219 } | 159 } |
| 220 | 160 |
| 221 | 161 |
| 222 DEFINE_NATIVE_ENTRY(Integer_equalToInteger, 2) { | 162 DEFINE_NATIVE_ENTRY(Integer_equalToInteger, 2) { |
| 223 const Integer& left = Integer::CheckedHandle(arguments->At(0)); | 163 const Integer& left = Integer::CheckedHandle(arguments->At(0)); |
| 224 GET_NATIVE_ARGUMENT(Integer, right, arguments->At(1)); | 164 GET_NATIVE_ARGUMENT(Integer, right, arguments->At(1)); |
| 225 ASSERT(CheckInteger(left)); | 165 ASSERT(CheckInteger(left)); |
| 226 ASSERT(CheckInteger(right)); | 166 ASSERT(CheckInteger(right)); |
| 227 if (FLAG_trace_intrinsified_natives) { | 167 if (FLAG_trace_intrinsified_natives) { |
| 228 OS::Print("Integer_equalToInteger %s == %s\n", | 168 OS::Print("Integer_equalToInteger %s == %s\n", |
| 229 left.ToCString(), right.ToCString()); | 169 left.ToCString(), right.ToCString()); |
| 230 } | 170 } |
| 231 return Bool::Get(left.CompareWith(right) == 0); | 171 return Bool::Get(left.CompareWith(right) == 0); |
| 232 } | 172 } |
| 233 | 173 |
| 234 | 174 |
| 235 static int HighestBit(int64_t v) { | |
| 236 uint64_t t = static_cast<uint64_t>((v > 0) ? v : -v); | |
| 237 int count = 0; | |
| 238 while ((t >>= 1) != 0) { | |
| 239 count++; | |
| 240 } | |
| 241 return count; | |
| 242 } | |
| 243 | |
| 244 | |
| 245 // TODO(srdjan): Clarify handling of negative right operand in a shift op. | |
| 246 static RawInteger* SmiShiftOperation(Token::Kind kind, | |
| 247 const Smi& left, | |
| 248 const Smi& right) { | |
| 249 intptr_t result = 0; | |
| 250 const intptr_t left_value = left.Value(); | |
| 251 const intptr_t right_value = right.Value(); | |
| 252 ASSERT(right_value >= 0); | |
| 253 switch (kind) { | |
| 254 case Token::kSHL: { | |
| 255 if ((left_value == 0) || (right_value == 0)) { | |
| 256 return left.raw(); | |
| 257 } | |
| 258 { // Check for overflow. | |
| 259 int cnt = HighestBit(left_value); | |
| 260 if ((cnt + right_value) >= Smi::kBits) { | |
| 261 if ((cnt + right_value) >= Mint::kBits) { | |
| 262 return BigintOperations::ShiftLeft( | |
| 263 Bigint::Handle(left.AsBigint()), right_value); | |
| 264 } else { | |
| 265 int64_t left_64 = left_value; | |
| 266 return Integer::New(left_64 << right_value); | |
| 267 } | |
| 268 } | |
| 269 } | |
| 270 result = left_value << right_value; | |
| 271 break; | |
| 272 } | |
| 273 case Token::kSHR: { | |
| 274 const intptr_t shift_amount = | |
| 275 (right_value >= kBitsPerWord) ? (kBitsPerWord - 1) : right_value; | |
| 276 result = left_value >> shift_amount; | |
| 277 break; | |
| 278 } | |
| 279 default: | |
| 280 UNIMPLEMENTED(); | |
| 281 } | |
| 282 ASSERT(Smi::IsValid(result)); | |
| 283 return Smi::New(result); | |
| 284 } | |
| 285 | |
| 286 | |
| 287 static RawInteger* ShiftOperationHelper(Token::Kind kind, | 175 static RawInteger* ShiftOperationHelper(Token::Kind kind, |
| 288 const Integer& value, | 176 const Integer& value, |
| 289 const Smi& amount) { | 177 const Smi& amount) { |
| 290 if (amount.Value() < 0) { | 178 if (amount.Value() < 0) { |
| 291 GrowableArray<const Object*> args; | 179 GrowableArray<const Object*> args; |
| 292 args.Add(&amount); | 180 args.Add(&amount); |
| 293 Exceptions::ThrowByType(Exceptions::kIllegalArgument, args); | 181 Exceptions::ThrowByType(Exceptions::kIllegalArgument, args); |
| 294 } | 182 } |
| 295 if (value.IsSmi()) { | 183 if (value.IsSmi()) { |
| 296 Smi& smi_value = Smi::Handle(); | 184 Smi& smi_value = Smi::Handle(); |
| 297 smi_value ^= value.raw(); | 185 smi_value ^= value.raw(); |
| 298 return SmiShiftOperation(kind, smi_value, amount); | 186 return smi_value.ShiftOp(kind, amount); |
| 299 } | 187 } |
| 300 Bigint& big_value = Bigint::Handle(); | 188 Bigint& big_value = Bigint::Handle(); |
| 301 if (value.IsMint()) { | 189 if (value.IsMint()) { |
| 302 const int64_t mint_value = value.AsInt64Value(); | 190 const int64_t mint_value = value.AsInt64Value(); |
| 303 const int count = HighestBit(mint_value); | 191 const int count = Utils::HighestBit(mint_value); |
| 304 if ((count + amount.Value()) < Mint::kBits) { | 192 if ((count + amount.Value()) < Mint::kBits) { |
| 305 switch (kind) { | 193 switch (kind) { |
| 306 case Token::kSHL: | 194 case Token::kSHL: |
| 307 return Integer::New(mint_value << amount.Value()); | 195 return Integer::New(mint_value << amount.Value()); |
| 308 case Token::kSHR: | 196 case Token::kSHR: |
| 309 return Integer::New(mint_value >> amount.Value()); | 197 return Integer::New(mint_value >> amount.Value()); |
| 310 default: | 198 default: |
| 311 UNIMPLEMENTED(); | 199 UNIMPLEMENTED(); |
| 312 } | 200 } |
| 313 } else { | 201 } else { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 | 271 |
| 384 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { | 272 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { |
| 385 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); | 273 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); |
| 386 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); | 274 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); |
| 387 ASSERT(CheckInteger(value)); | 275 ASSERT(CheckInteger(value)); |
| 388 ASSERT(CheckInteger(result)); | 276 ASSERT(CheckInteger(result)); |
| 389 return result.AsInteger(); | 277 return result.AsInteger(); |
| 390 } | 278 } |
| 391 | 279 |
| 392 } // namespace dart | 280 } // namespace dart |
| OLD | NEW |