| 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 // Return the most compact presentation of an integer. |
| 21 static RawInteger* AsInteger(const Integer& value) { |
| 22 if (value.IsSmi()) return value.raw(); |
| 23 if (value.IsMint()) { |
| 24 Mint& mint = Mint::Handle(); |
| 25 mint ^= value.raw(); |
| 26 if (Smi::IsValid64(mint.value())) { |
| 27 return Smi::New(mint.value()); |
| 28 } else { |
| 29 return value.raw(); |
| 30 } |
| 31 } |
| 32 ASSERT(value.IsBigint()); |
| 33 Bigint& big_value = Bigint::Handle(); |
| 34 big_value ^= value.raw(); |
| 35 if (BigintOperations::FitsIntoSmi(big_value)) { |
| 36 return BigintOperations::ToSmi(big_value); |
| 37 } else if (BigintOperations::FitsIntoMint(big_value)) { |
| 38 return Mint::New(BigintOperations::ToMint(big_value)); |
| 39 } else { |
| 40 return big_value.raw(); |
| 41 } |
| 42 } |
| 43 |
| 44 |
| 45 // Returns value in form of a RawBigint. |
| 46 static RawBigint* AsBigint(const Integer& value) { |
| 47 ASSERT(!value.IsNull()); |
| 48 if (value.IsSmi()) { |
| 49 Smi& smi = Smi::Handle(); |
| 50 smi ^= value.raw(); |
| 51 return BigintOperations::NewFromSmi(smi); |
| 52 } else if (value.IsMint()) { |
| 53 Mint& mint = Mint::Handle(); |
| 54 mint ^= value.raw(); |
| 55 return BigintOperations::NewFromInt64(mint.value()); |
| 56 } else { |
| 57 ASSERT(value.IsBigint()); |
| 58 Bigint& big = Bigint::Handle(); |
| 59 big ^= value.raw(); |
| 60 ASSERT(!BigintOperations::FitsIntoSmi(big)); |
| 61 return big.raw(); |
| 62 } |
| 63 } |
| 64 |
| 65 |
| 20 static bool Are64bitOperands(const Integer& op1, const Integer& op2) { | 66 static bool Are64bitOperands(const Integer& op1, const Integer& op2) { |
| 21 return !op1.IsBigint() && !op2.IsBigint(); | 67 return !op1.IsBigint() && !op2.IsBigint(); |
| 22 } | 68 } |
| 23 | 69 |
| 24 | 70 |
| 25 static RawInteger* IntegerBitOperation(Token::Kind kind, | 71 static RawInteger* IntegerBitOperation(Token::Kind kind, |
| 26 const Integer& op1_int, | 72 const Integer& op1_int, |
| 27 const Integer& op2_int) { | 73 const Integer& op2_int) { |
| 28 if (op1_int.IsSmi() && op2_int.IsSmi()) { | 74 if (op1_int.IsSmi() && op2_int.IsSmi()) { |
| 29 Smi& op1 = Smi::Handle(); | 75 Smi& op1 = Smi::Handle(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 53 case Token::kBIT_AND: | 99 case Token::kBIT_AND: |
| 54 return Integer::New(a & b); | 100 return Integer::New(a & b); |
| 55 case Token::kBIT_OR: | 101 case Token::kBIT_OR: |
| 56 return Integer::New(a | b); | 102 return Integer::New(a | b); |
| 57 case Token::kBIT_XOR: | 103 case Token::kBIT_XOR: |
| 58 return Integer::New(a ^ b); | 104 return Integer::New(a ^ b); |
| 59 default: | 105 default: |
| 60 UNIMPLEMENTED(); | 106 UNIMPLEMENTED(); |
| 61 } | 107 } |
| 62 } else { | 108 } else { |
| 63 Bigint& op1 = Bigint::Handle(Bigint::AsBigint(op1_int)); | 109 Bigint& op1 = Bigint::Handle(AsBigint(op1_int)); |
| 64 Bigint& op2 = Bigint::Handle(Bigint::AsBigint(op2_int)); | 110 Bigint& op2 = Bigint::Handle(AsBigint(op2_int)); |
| 65 switch (kind) { | 111 switch (kind) { |
| 66 case Token::kBIT_AND: | 112 case Token::kBIT_AND: |
| 67 return BigintOperations::BitAnd(op1, op2); | 113 return BigintOperations::BitAnd(op1, op2); |
| 68 case Token::kBIT_OR: | 114 case Token::kBIT_OR: |
| 69 return BigintOperations::BitOr(op1, op2); | 115 return BigintOperations::BitOr(op1, op2); |
| 70 case Token::kBIT_XOR: | 116 case Token::kBIT_XOR: |
| 71 return BigintOperations::BitXor(op1, op2); | 117 return BigintOperations::BitXor(op1, op2); |
| 72 default: | 118 default: |
| 73 UNIMPLEMENTED(); | 119 UNIMPLEMENTED(); |
| 74 } | 120 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 99 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 145 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 100 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 146 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 101 ASSERT(CheckInteger(right)); | 147 ASSERT(CheckInteger(right)); |
| 102 ASSERT(CheckInteger(left)); | 148 ASSERT(CheckInteger(left)); |
| 103 if (FLAG_trace_intrinsified_natives) { | 149 if (FLAG_trace_intrinsified_natives) { |
| 104 OS::Print("Integer_bitAndFromInteger %s & %s\n", | 150 OS::Print("Integer_bitAndFromInteger %s & %s\n", |
| 105 right.ToCString(), left.ToCString()); | 151 right.ToCString(), left.ToCString()); |
| 106 } | 152 } |
| 107 Integer& result = Integer::Handle( | 153 Integer& result = Integer::Handle( |
| 108 IntegerBitOperation(Token::kBIT_AND, left, right)); | 154 IntegerBitOperation(Token::kBIT_AND, left, right)); |
| 109 return Integer::AsInteger(result); | 155 return AsInteger(result); |
| 110 } | 156 } |
| 111 | 157 |
| 112 | 158 |
| 113 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { | 159 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { |
| 114 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 160 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 115 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 161 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 116 ASSERT(CheckInteger(right)); | 162 ASSERT(CheckInteger(right)); |
| 117 ASSERT(CheckInteger(left)); | 163 ASSERT(CheckInteger(left)); |
| 118 if (FLAG_trace_intrinsified_natives) { | 164 if (FLAG_trace_intrinsified_natives) { |
| 119 OS::Print("Integer_bitOrFromInteger %s | %s\n", | 165 OS::Print("Integer_bitOrFromInteger %s | %s\n", |
| 120 left.ToCString(), right.ToCString()); | 166 left.ToCString(), right.ToCString()); |
| 121 } | 167 } |
| 122 Integer& result = Integer::Handle( | 168 Integer& result = Integer::Handle( |
| 123 IntegerBitOperation(Token::kBIT_OR, left, right)); | 169 IntegerBitOperation(Token::kBIT_OR, left, right)); |
| 124 return Integer::AsInteger(result); | 170 return AsInteger(result); |
| 125 } | 171 } |
| 126 | 172 |
| 127 | 173 |
| 128 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { | 174 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { |
| 129 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 175 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 130 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 176 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 131 ASSERT(CheckInteger(right)); | 177 ASSERT(CheckInteger(right)); |
| 132 ASSERT(CheckInteger(left)); | 178 ASSERT(CheckInteger(left)); |
| 133 if (FLAG_trace_intrinsified_natives) { | 179 if (FLAG_trace_intrinsified_natives) { |
| 134 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", | 180 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", |
| 135 left.ToCString(), right.ToCString()); | 181 left.ToCString(), right.ToCString()); |
| 136 } | 182 } |
| 137 Integer& result = Integer::Handle( | 183 Integer& result = Integer::Handle( |
| 138 IntegerBitOperation(Token::kBIT_XOR, left, right)); | 184 IntegerBitOperation(Token::kBIT_XOR, left, right)); |
| 139 return Integer::AsInteger(result); | 185 return AsInteger(result); |
| 140 } | 186 } |
| 141 | 187 |
| 142 | 188 |
| 189 static RawBigint* BinaryOpWithTwoBigints(Token::Kind operation, |
| 190 const Bigint& left, |
| 191 const Bigint& right) { |
| 192 switch (operation) { |
| 193 case Token::kADD: |
| 194 return BigintOperations::Add(left, right); |
| 195 case Token::kSUB: |
| 196 return BigintOperations::Subtract(left, right); |
| 197 case Token::kMUL: |
| 198 return BigintOperations::Multiply(left, right); |
| 199 case Token::kTRUNCDIV: |
| 200 return BigintOperations::Divide(left, right); |
| 201 case Token::kMOD: |
| 202 return BigintOperations::Modulo(left, right); |
| 203 default: |
| 204 UNIMPLEMENTED(); |
| 205 return Bigint::null(); |
| 206 } |
| 207 } |
| 208 |
| 209 |
| 210 static RawInteger* IntegerBinopHelper(Token::Kind operation, |
| 211 const Integer& left_int, |
| 212 const Integer& right_int) { |
| 213 // In 32-bit mode, the result of any operation between two Smis will fit in a |
| 214 // 32-bit signed result, except the product of two Smis, which will be 64-bit. |
| 215 // In 64-bit mode, the result of any operation between two Smis will fit in a |
| 216 // 64-bit signed result, except the product of two Smis (unless the Smis are |
| 217 // 32-bit or less). |
| 218 if (left_int.IsSmi() && right_int.IsSmi()) { |
| 219 Smi& left_smi = Smi::Handle(); |
| 220 Smi& right_smi = Smi::Handle(); |
| 221 left_smi ^= left_int.raw(); |
| 222 right_smi ^= right_int.raw(); |
| 223 const intptr_t left_value = left_smi.Value(); |
| 224 const intptr_t right_value = right_smi.Value(); |
| 225 switch (operation) { |
| 226 case Token::kADD: |
| 227 return Integer::New(left_value + right_value); |
| 228 case Token::kSUB: |
| 229 return Integer::New(left_value - right_value); |
| 230 case Token::kMUL: { |
| 231 if (Smi::kBits < 32) { |
| 232 // In 32-bit mode, the product of two Smis fits in a 64-bit result. |
| 233 return Integer::New(static_cast<int64_t>(left_value) * |
| 234 static_cast<int64_t>(right_value)); |
| 235 } else { |
| 236 // In 64-bit mode, the product of two 32-bit signed integers fits in a |
| 237 // 64-bit result. |
| 238 ASSERT(sizeof(intptr_t) == sizeof(int64_t)); |
| 239 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { |
| 240 return Integer::New(left_value * right_value); |
| 241 } |
| 242 } |
| 243 // Perform a Bigint multiplication below. |
| 244 break; |
| 245 } |
| 246 case Token::kTRUNCDIV: |
| 247 return Integer::New(left_value / right_value); |
| 248 case Token::kMOD: { |
| 249 const intptr_t remainder = left_value % right_value; |
| 250 if (remainder < 0) { |
| 251 if (right_value < 0) { |
| 252 return Integer::New(remainder - right_value); |
| 253 } else { |
| 254 return Integer::New(remainder + right_value); |
| 255 } |
| 256 } |
| 257 return Integer::New(remainder); |
| 258 } |
| 259 default: |
| 260 UNIMPLEMENTED(); |
| 261 } |
| 262 } |
| 263 // In 32-bit mode, the result of any operation between two 63-bit signed |
| 264 // integers (or 32-bit for multiplication) will fit in a 64-bit signed result. |
| 265 // In 64-bit mode, 63-bit signed integers are Smis, already processed above. |
| 266 if ((Smi::kBits < 32) && !left_int.IsBigint() && !right_int.IsBigint()) { |
| 267 const int64_t left_value = left_int.AsInt64Value(); |
| 268 if (Utils::IsInt(63, left_value)) { |
| 269 const int64_t right_value = right_int.AsInt64Value(); |
| 270 if (Utils::IsInt(63, right_value)) { |
| 271 switch (operation) { |
| 272 case Token::kADD: |
| 273 return Integer::New(left_value + right_value); |
| 274 case Token::kSUB: |
| 275 return Integer::New(left_value - right_value); |
| 276 case Token::kMUL: { |
| 277 if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) { |
| 278 return Integer::New(left_value * right_value); |
| 279 } |
| 280 // Perform a Bigint multiplication below. |
| 281 break; |
| 282 } |
| 283 case Token::kTRUNCDIV: |
| 284 return Integer::New(left_value / right_value); |
| 285 case Token::kMOD: { |
| 286 const int64_t remainder = left_value % right_value; |
| 287 if (remainder < 0) { |
| 288 if (right_value < 0) { |
| 289 return Integer::New(remainder - right_value); |
| 290 } else { |
| 291 return Integer::New(remainder + right_value); |
| 292 } |
| 293 } |
| 294 return Integer::New(remainder); |
| 295 } |
| 296 default: |
| 297 UNIMPLEMENTED(); |
| 298 } |
| 299 } |
| 300 } |
| 301 } |
| 302 const Bigint& left_big = Bigint::Handle(AsBigint(left_int)); |
| 303 const Bigint& right_big = Bigint::Handle(AsBigint(right_int)); |
| 304 const Bigint& result = |
| 305 Bigint::Handle(BinaryOpWithTwoBigints(operation, left_big, right_big)); |
| 306 return Integer::Handle(AsInteger(result)).raw(); |
| 307 } |
| 308 |
| 309 |
| 143 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { | 310 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { |
| 144 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 311 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 145 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 312 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 146 ASSERT(CheckInteger(right_int)); | 313 ASSERT(CheckInteger(right_int)); |
| 147 ASSERT(CheckInteger(left_int)); | 314 ASSERT(CheckInteger(left_int)); |
| 148 if (FLAG_trace_intrinsified_natives) { | 315 if (FLAG_trace_intrinsified_natives) { |
| 149 OS::Print("Integer_addFromInteger %s + %s\n", | 316 OS::Print("Integer_addFromInteger %s + %s\n", |
| 150 left_int.ToCString(), right_int.ToCString()); | 317 left_int.ToCString(), right_int.ToCString()); |
| 151 } | 318 } |
| 152 return Integer::BinaryOp(Token::kADD, left_int, right_int); | 319 return IntegerBinopHelper(Token::kADD, left_int, right_int); |
| 153 } | 320 } |
| 154 | 321 |
| 155 | 322 |
| 156 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { | 323 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { |
| 157 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 324 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 158 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 325 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 159 ASSERT(CheckInteger(right_int)); | 326 ASSERT(CheckInteger(right_int)); |
| 160 ASSERT(CheckInteger(left_int)); | 327 ASSERT(CheckInteger(left_int)); |
| 161 if (FLAG_trace_intrinsified_natives) { | 328 if (FLAG_trace_intrinsified_natives) { |
| 162 OS::Print("Integer_subFromInteger %s - %s\n", | 329 OS::Print("Integer_subFromInteger %s - %s\n", |
| 163 left_int.ToCString(), right_int.ToCString()); | 330 left_int.ToCString(), right_int.ToCString()); |
| 164 } | 331 } |
| 165 return Integer::BinaryOp(Token::kSUB, left_int, right_int); | 332 return IntegerBinopHelper(Token::kSUB, left_int, right_int); |
| 166 } | 333 } |
| 167 | 334 |
| 168 | 335 |
| 169 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { | 336 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { |
| 170 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 337 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 171 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 338 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 172 ASSERT(CheckInteger(right_int)); | 339 ASSERT(CheckInteger(right_int)); |
| 173 ASSERT(CheckInteger(left_int)); | 340 ASSERT(CheckInteger(left_int)); |
| 174 if (FLAG_trace_intrinsified_natives) { | 341 if (FLAG_trace_intrinsified_natives) { |
| 175 OS::Print("Integer_mulFromInteger %s * %s\n", | 342 OS::Print("Integer_mulFromInteger %s * %s\n", |
| 176 left_int.ToCString(), right_int.ToCString()); | 343 left_int.ToCString(), right_int.ToCString()); |
| 177 } | 344 } |
| 178 return Integer::BinaryOp(Token::kMUL, left_int, right_int); | 345 return IntegerBinopHelper(Token::kMUL, left_int, right_int); |
| 179 } | 346 } |
| 180 | 347 |
| 181 | 348 |
| 182 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { | 349 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { |
| 183 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 350 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 184 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 351 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 185 ASSERT(CheckInteger(right_int)); | 352 ASSERT(CheckInteger(right_int)); |
| 186 ASSERT(CheckInteger(left_int)); | 353 ASSERT(CheckInteger(left_int)); |
| 187 ASSERT(!right_int.IsZero()); | 354 ASSERT(!right_int.IsZero()); |
| 188 return Integer::BinaryOp(Token::kTRUNCDIV, left_int, right_int); | 355 return IntegerBinopHelper(Token::kTRUNCDIV, left_int, right_int); |
| 189 } | 356 } |
| 190 | 357 |
| 191 | 358 |
| 192 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { | 359 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { |
| 193 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); | 360 const Integer& right_int = Integer::CheckedHandle(arguments->At(0)); |
| 194 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); | 361 GET_NATIVE_ARGUMENT(Integer, left_int, arguments->At(1)); |
| 195 ASSERT(CheckInteger(right_int)); | 362 ASSERT(CheckInteger(right_int)); |
| 196 ASSERT(CheckInteger(right_int)); | 363 ASSERT(CheckInteger(right_int)); |
| 197 if (FLAG_trace_intrinsified_natives) { | 364 if (FLAG_trace_intrinsified_natives) { |
| 198 OS::Print("Integer_moduloFromInteger %s mod %s\n", | 365 OS::Print("Integer_moduloFromInteger %s mod %s\n", |
| 199 left_int.ToCString(), right_int.ToCString()); | 366 left_int.ToCString(), right_int.ToCString()); |
| 200 } | 367 } |
| 201 if (right_int.IsZero()) { | 368 if (right_int.IsZero()) { |
| 202 // Should have been caught before calling into runtime. | 369 // Should have been caught before calling into runtime. |
| 203 UNIMPLEMENTED(); | 370 UNIMPLEMENTED(); |
| 204 } | 371 } |
| 205 return Integer::BinaryOp(Token::kMOD, left_int, right_int); | 372 return IntegerBinopHelper(Token::kMOD, left_int, right_int); |
| 206 } | 373 } |
| 207 | 374 |
| 208 | 375 |
| 209 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { | 376 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { |
| 210 const Integer& right = Integer::CheckedHandle(arguments->At(0)); | 377 const Integer& right = Integer::CheckedHandle(arguments->At(0)); |
| 211 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); | 378 GET_NATIVE_ARGUMENT(Integer, left, arguments->At(1)); |
| 212 ASSERT(CheckInteger(right)); | 379 ASSERT(CheckInteger(right)); |
| 213 ASSERT(CheckInteger(left)); | 380 ASSERT(CheckInteger(left)); |
| 214 if (FLAG_trace_intrinsified_natives) { | 381 if (FLAG_trace_intrinsified_natives) { |
| 215 OS::Print("Integer_greaterThanFromInteger %s > %s\n", | 382 OS::Print("Integer_greaterThanFromInteger %s > %s\n", |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 switch (kind) { | 420 switch (kind) { |
| 254 case Token::kSHL: { | 421 case Token::kSHL: { |
| 255 if ((left_value == 0) || (right_value == 0)) { | 422 if ((left_value == 0) || (right_value == 0)) { |
| 256 return left.raw(); | 423 return left.raw(); |
| 257 } | 424 } |
| 258 { // Check for overflow. | 425 { // Check for overflow. |
| 259 int cnt = HighestBit(left_value); | 426 int cnt = HighestBit(left_value); |
| 260 if ((cnt + right_value) >= Smi::kBits) { | 427 if ((cnt + right_value) >= Smi::kBits) { |
| 261 if ((cnt + right_value) >= Mint::kBits) { | 428 if ((cnt + right_value) >= Mint::kBits) { |
| 262 return BigintOperations::ShiftLeft( | 429 return BigintOperations::ShiftLeft( |
| 263 Bigint::Handle(Bigint::AsBigint(left)), right_value); | 430 Bigint::Handle(AsBigint(left)), right_value); |
| 264 } else { | 431 } else { |
| 265 int64_t left_64 = left_value; | 432 int64_t left_64 = left_value; |
| 266 return Integer::New(left_64 << right_value); | 433 return Integer::New(left_64 << right_value); |
| 267 } | 434 } |
| 268 } | 435 } |
| 269 } | 436 } |
| 270 result = left_value << right_value; | 437 result = left_value << right_value; |
| 271 break; | 438 break; |
| 272 } | 439 } |
| 273 case Token::kSHR: { | 440 case Token::kSHR: { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 } | 497 } |
| 331 | 498 |
| 332 | 499 |
| 333 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { | 500 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { |
| 334 const Smi& amount = Smi::CheckedHandle(arguments->At(0)); | 501 const Smi& amount = Smi::CheckedHandle(arguments->At(0)); |
| 335 GET_NATIVE_ARGUMENT(Integer, value, arguments->At(1)); | 502 GET_NATIVE_ARGUMENT(Integer, value, arguments->At(1)); |
| 336 ASSERT(CheckInteger(amount)); | 503 ASSERT(CheckInteger(amount)); |
| 337 ASSERT(CheckInteger(value)); | 504 ASSERT(CheckInteger(value)); |
| 338 Integer& result = Integer::Handle( | 505 Integer& result = Integer::Handle( |
| 339 ShiftOperationHelper(Token::kSHR, value, amount)); | 506 ShiftOperationHelper(Token::kSHR, value, amount)); |
| 340 return Integer::AsInteger(result); | 507 return AsInteger(result); |
| 341 } | 508 } |
| 342 | 509 |
| 343 | 510 |
| 344 | 511 |
| 345 DEFINE_NATIVE_ENTRY(Smi_shlFromInt, 2) { | 512 DEFINE_NATIVE_ENTRY(Smi_shlFromInt, 2) { |
| 346 const Smi& amount = Smi::CheckedHandle(arguments->At(0)); | 513 const Smi& amount = Smi::CheckedHandle(arguments->At(0)); |
| 347 GET_NATIVE_ARGUMENT(Integer, value, arguments->At(1)); | 514 GET_NATIVE_ARGUMENT(Integer, value, arguments->At(1)); |
| 348 ASSERT(CheckInteger(amount)); | 515 ASSERT(CheckInteger(amount)); |
| 349 ASSERT(CheckInteger(value)); | 516 ASSERT(CheckInteger(value)); |
| 350 if (FLAG_trace_intrinsified_natives) { | 517 if (FLAG_trace_intrinsified_natives) { |
| 351 OS::Print("Smi_shlFromInt: %s << %s\n", | 518 OS::Print("Smi_shlFromInt: %s << %s\n", |
| 352 value.ToCString(), amount.ToCString()); | 519 value.ToCString(), amount.ToCString()); |
| 353 } | 520 } |
| 354 Integer& result = Integer::Handle( | 521 Integer& result = Integer::Handle( |
| 355 ShiftOperationHelper(Token::kSHL, value, amount)); | 522 ShiftOperationHelper(Token::kSHL, value, amount)); |
| 356 return Integer::AsInteger(result); | 523 return AsInteger(result); |
| 357 } | 524 } |
| 358 | 525 |
| 359 | 526 |
| 360 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) { | 527 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) { |
| 361 const Smi& operand = Smi::CheckedHandle(arguments->At(0)); | 528 const Smi& operand = Smi::CheckedHandle(arguments->At(0)); |
| 362 if (FLAG_trace_intrinsified_natives) { | 529 if (FLAG_trace_intrinsified_natives) { |
| 363 OS::Print("Smi_bitNegate: %s\n", operand.ToCString()); | 530 OS::Print("Smi_bitNegate: %s\n", operand.ToCString()); |
| 364 } | 531 } |
| 365 intptr_t result = ~operand.Value(); | 532 intptr_t result = ~operand.Value(); |
| 366 ASSERT(Smi::IsValid(result)); | 533 ASSERT(Smi::IsValid(result)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 379 return Integer::New(result); | 546 return Integer::New(result); |
| 380 } | 547 } |
| 381 | 548 |
| 382 // Bigint natives. | 549 // Bigint natives. |
| 383 | 550 |
| 384 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { | 551 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { |
| 385 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); | 552 const Bigint& value = Bigint::CheckedHandle(arguments->At(0)); |
| 386 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); | 553 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); |
| 387 ASSERT(CheckInteger(value)); | 554 ASSERT(CheckInteger(value)); |
| 388 ASSERT(CheckInteger(result)); | 555 ASSERT(CheckInteger(result)); |
| 389 return Integer::AsInteger(result); | 556 return AsInteger(result); |
| 390 } | 557 } |
| 391 | 558 |
| 392 } // namespace dart | 559 } // namespace dart |
| OLD | NEW |