| 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" |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 return Integer::New(temp); | 216 return Integer::New(temp); |
| 217 } | 217 } |
| 218 | 218 |
| 219 const Array& args = Array::Handle(Array::New(1)); | 219 const Array& args = Array::Handle(Array::New(1)); |
| 220 args.SetAt(0, value); | 220 args.SetAt(0, value); |
| 221 Exceptions::ThrowByType(Exceptions::kFormat, args); | 221 Exceptions::ThrowByType(Exceptions::kFormat, args); |
| 222 return Object::null(); | 222 return Object::null(); |
| 223 } | 223 } |
| 224 | 224 |
| 225 | 225 |
| 226 // Passing true for 'silent' prevents throwing JavascriptIntegerOverflow. |
| 226 static RawInteger* ShiftOperationHelper(Token::Kind kind, | 227 static RawInteger* ShiftOperationHelper(Token::Kind kind, |
| 227 const Integer& value, | 228 const Integer& value, |
| 228 const Smi& amount) { | 229 const Smi& amount, |
| 230 const bool silent = false) { |
| 229 if (amount.Value() < 0) { | 231 if (amount.Value() < 0) { |
| 230 const Array& args = Array::Handle(Array::New(1)); | 232 const Array& args = Array::Handle(Array::New(1)); |
| 231 args.SetAt(0, amount); | 233 args.SetAt(0, amount); |
| 232 Exceptions::ThrowByType(Exceptions::kArgument, args); | 234 Exceptions::ThrowByType(Exceptions::kArgument, args); |
| 233 } | 235 } |
| 234 if (value.IsSmi()) { | 236 if (value.IsSmi()) { |
| 235 const Smi& smi_value = Smi::Cast(value); | 237 const Smi& smi_value = Smi::Cast(value); |
| 236 return smi_value.ShiftOp(kind, amount); | 238 return smi_value.ShiftOp(kind, amount, silent); |
| 237 } | 239 } |
| 238 Bigint& big_value = Bigint::Handle(); | 240 Bigint& big_value = Bigint::Handle(); |
| 239 if (value.IsMint()) { | 241 if (value.IsMint()) { |
| 240 const int64_t mint_value = value.AsInt64Value(); | 242 const int64_t mint_value = value.AsInt64Value(); |
| 241 const int count = Utils::HighestBit(mint_value); | 243 const int count = Utils::HighestBit(mint_value); |
| 242 if ((count + amount.Value()) < Mint::kBits) { | 244 if ((count + amount.Value()) < Mint::kBits) { |
| 243 switch (kind) { | 245 switch (kind) { |
| 244 case Token::kSHL: | 246 case Token::kSHL: |
| 245 return Integer::New(mint_value << amount.Value()); | 247 return Integer::New(mint_value << amount.Value(), Heap::kNew, silent); |
| 246 case Token::kSHR: | 248 case Token::kSHR: |
| 247 return Integer::New(mint_value >> amount.Value()); | 249 return Integer::New(mint_value >> amount.Value(), Heap::kNew, silent); |
| 248 default: | 250 default: |
| 249 UNIMPLEMENTED(); | 251 UNIMPLEMENTED(); |
| 250 } | 252 } |
| 251 } else { | 253 } else { |
| 252 // Overflow in shift, use Bigints | 254 // Overflow in shift, use Bigints |
| 253 big_value = BigintOperations::NewFromInt64(mint_value); | 255 big_value = BigintOperations::NewFromInt64(mint_value); |
| 254 } | 256 } |
| 255 } else { | 257 } else { |
| 256 ASSERT(value.IsBigint()); | 258 ASSERT(value.IsBigint()); |
| 257 big_value = Bigint::Cast(value).raw(); | 259 big_value = Bigint::Cast(value).raw(); |
| 258 } | 260 } |
| 259 switch (kind) { | 261 switch (kind) { |
| 260 case Token::kSHL: | 262 case Token::kSHL: |
| 261 return BigintOperations::ShiftLeft(big_value, amount.Value()); | 263 return BigintOperations::ShiftLeft(big_value, amount.Value()); |
| 262 case Token::kSHR: | 264 case Token::kSHR: |
| 263 return BigintOperations::ShiftRight(big_value, amount.Value()); | 265 return BigintOperations::ShiftRight(big_value, amount.Value()); |
| 264 default: | 266 default: |
| 265 UNIMPLEMENTED(); | 267 UNIMPLEMENTED(); |
| 266 } | 268 } |
| 267 return Integer::null(); | 269 return Integer::null(); |
| 268 } | 270 } |
| 269 | 271 |
| 270 | 272 |
| 273 DEFINE_NATIVE_ENTRY(Integer_leftShiftWithMask32, 3) { |
| 274 const Integer& value = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 275 GET_NON_NULL_NATIVE_ARGUMENT(Integer, shift_count, arguments->NativeArgAt(1)); |
| 276 GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(2)); |
| 277 ASSERT(CheckInteger(value)); |
| 278 ASSERT(CheckInteger(shift_count)); |
| 279 ASSERT(CheckInteger(mask)); |
| 280 if (!shift_count.IsSmi()) { |
| 281 // Shift count is too large.. |
| 282 const Instance& exception = |
| 283 Instance::Handle(isolate->object_store()->out_of_memory()); |
| 284 Exceptions::Throw(exception); |
| 285 } |
| 286 const Smi& smi_shift_count = Smi::Cast(shift_count); |
| 287 const Integer& shift_result = Integer::Handle( |
| 288 ShiftOperationHelper(Token::kSHL, value, smi_shift_count, true)); |
| 289 const Integer& result = |
| 290 Integer::Handle(shift_result.BitOp(Token::kBIT_AND, mask)); |
| 291 return result.AsValidInteger(); |
| 292 } |
| 293 |
| 294 |
| 271 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { | 295 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { |
| 272 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 296 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
| 273 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); | 297 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); |
| 274 ASSERT(CheckInteger(amount)); | 298 ASSERT(CheckInteger(amount)); |
| 275 ASSERT(CheckInteger(value)); | 299 ASSERT(CheckInteger(value)); |
| 276 const Integer& result = Integer::Handle( | 300 const Integer& result = Integer::Handle( |
| 277 ShiftOperationHelper(Token::kSHR, value, amount)); | 301 ShiftOperationHelper(Token::kSHR, value, amount)); |
| 278 return result.AsValidInteger(); | 302 return result.AsValidInteger(); |
| 279 } | 303 } |
| 280 | 304 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // Use the preallocated out of memory exception to avoid calling | 369 // Use the preallocated out of memory exception to avoid calling |
| 346 // into dart code or allocating any code. | 370 // into dart code or allocating any code. |
| 347 const Instance& exception = | 371 const Instance& exception = |
| 348 Instance::Handle(isolate->object_store()->out_of_memory()); | 372 Instance::Handle(isolate->object_store()->out_of_memory()); |
| 349 Exceptions::Throw(exception); | 373 Exceptions::Throw(exception); |
| 350 UNREACHABLE(); | 374 UNREACHABLE(); |
| 351 return 0; | 375 return 0; |
| 352 } | 376 } |
| 353 | 377 |
| 354 } // namespace dart | 378 } // namespace dart |
| OLD | NEW |