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/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 #include "vm/symbols.h" | 12 #include "vm/symbols.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 DEFINE_FLAG(bool, throw_on_53bit_overflow, false, | |
| 17 "Throw an exception when integer arithmetic exceeds 53 bits."); | |
| 18 | |
| 16 DEFINE_FLAG(bool, trace_intrinsified_natives, false, | 19 DEFINE_FLAG(bool, trace_intrinsified_natives, false, |
| 17 "Report if any of the intrinsified natives are called"); | 20 "Report if any of the intrinsified natives are called"); |
| 18 | 21 |
| 19 // Smi natives. | 22 // Smi natives. |
| 20 | 23 |
| 21 // Returns false if integer is in wrong representation, e.g., as is a Bigint | 24 // Returns false if integer is in wrong representation, e.g., as is a Bigint |
| 22 // when it could have been a Smi. | 25 // when it could have been a Smi. |
| 23 static bool CheckInteger(const Integer& i) { | 26 static bool CheckInteger(const Integer& i) { |
| 24 if (i.IsBigint()) { | 27 if (i.IsBigint()) { |
| 25 const Bigint& bigint = Bigint::Cast(i); | 28 const Bigint& bigint = Bigint::Cast(i); |
| 26 return !BigintOperations::FitsIntoSmi(bigint) && | 29 return !BigintOperations::FitsIntoSmi(bigint) && |
| 27 !BigintOperations::FitsIntoInt64(bigint); | 30 !BigintOperations::FitsIntoInt64(bigint); |
| 28 } | 31 } |
| 29 if (i.IsMint()) { | 32 if (i.IsMint()) { |
| 30 const Mint& mint = Mint::Cast(i); | 33 const Mint& mint = Mint::Cast(i); |
| 31 return !Smi::IsValid64(mint.value()); | 34 return !Smi::IsValid64(mint.value()); |
| 32 } | 35 } |
| 33 return true; | 36 return true; |
| 34 } | 37 } |
| 35 | 38 |
| 36 | 39 |
| 40 // Throw kFiftyThreeBitOverflow if the result of an operation overflows | |
| 41 // 53 bits. | |
| 42 static void ThrowExceptionOnOverflow(const Integer& i, const char* msg) { | |
|
siva
2013/05/23 01:28:22
The name ThrowExceptionOnOverflow seems like a gen
zra
2013/05/23 15:59:07
Done.
| |
| 43 if (i.FitsIn53Bits()) return; | |
| 44 const Array& exc_args = Array::Handle(Array::New(1)); | |
| 45 exc_args.SetAt(0, Object::Handle(String::New(msg))); | |
| 46 Exceptions::ThrowByType(Exceptions::kFiftyThreeBitOverflowError, exc_args); | |
| 47 return; | |
| 48 } | |
| 49 | |
| 50 | |
| 37 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { | 51 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { |
| 38 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 52 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 39 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 53 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
| 40 ASSERT(CheckInteger(right)); | 54 ASSERT(CheckInteger(right)); |
| 41 ASSERT(CheckInteger(left)); | 55 ASSERT(CheckInteger(left)); |
| 42 if (FLAG_trace_intrinsified_natives) { | 56 if (FLAG_trace_intrinsified_natives) { |
| 43 OS::Print("Integer_bitAndFromInteger %s & %s\n", | 57 OS::Print("Integer_bitAndFromInteger %s & %s\n", |
| 44 right.ToCString(), left.ToCString()); | 58 right.ToCString(), left.ToCString()); |
| 45 } | 59 } |
| 46 const Integer& result = | 60 const Integer& result = |
| 47 Integer::Handle(left.BitOp(Token::kBIT_AND, right)); | 61 Integer::Handle(left.BitOp(Token::kBIT_AND, right)); |
| 62 if (FLAG_throw_on_53bit_overflow) { | |
| 63 ThrowExceptionOnOverflow(result, "Integer_bitAndFromInteger"); | |
| 64 } | |
| 48 return result.AsValidInteger(); | 65 return result.AsValidInteger(); |
| 49 } | 66 } |
| 50 | 67 |
| 51 | 68 |
| 52 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { | 69 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { |
| 53 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 70 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 54 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 71 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
| 55 ASSERT(CheckInteger(right)); | 72 ASSERT(CheckInteger(right)); |
| 56 ASSERT(CheckInteger(left)); | 73 ASSERT(CheckInteger(left)); |
| 57 if (FLAG_trace_intrinsified_natives) { | 74 if (FLAG_trace_intrinsified_natives) { |
| 58 OS::Print("Integer_bitOrFromInteger %s | %s\n", | 75 OS::Print("Integer_bitOrFromInteger %s | %s\n", |
| 59 left.ToCString(), right.ToCString()); | 76 left.ToCString(), right.ToCString()); |
| 60 } | 77 } |
| 61 const Integer& result = | 78 const Integer& result = |
| 62 Integer::Handle(left.BitOp(Token::kBIT_OR, right)); | 79 Integer::Handle(left.BitOp(Token::kBIT_OR, right)); |
| 80 if (FLAG_throw_on_53bit_overflow) { | |
| 81 ThrowExceptionOnOverflow(result, "Integer_bitOrFromInteger"); | |
| 82 } | |
| 63 return result.AsValidInteger(); | 83 return result.AsValidInteger(); |
| 64 } | 84 } |
| 65 | 85 |
| 66 | 86 |
| 67 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { | 87 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { |
| 68 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 88 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 69 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 89 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
| 70 ASSERT(CheckInteger(right)); | 90 ASSERT(CheckInteger(right)); |
| 71 ASSERT(CheckInteger(left)); | 91 ASSERT(CheckInteger(left)); |
| 72 if (FLAG_trace_intrinsified_natives) { | 92 if (FLAG_trace_intrinsified_natives) { |
| 73 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", | 93 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", |
| 74 left.ToCString(), right.ToCString()); | 94 left.ToCString(), right.ToCString()); |
| 75 } | 95 } |
| 76 const Integer& result = | 96 const Integer& result = |
| 77 Integer::Handle(left.BitOp(Token::kBIT_XOR, right)); | 97 Integer::Handle(left.BitOp(Token::kBIT_XOR, right)); |
| 98 if (FLAG_throw_on_53bit_overflow) { | |
| 99 ThrowExceptionOnOverflow(result, "Integer_bitXorFromInteger"); | |
| 100 } | |
| 78 return result.AsValidInteger(); | 101 return result.AsValidInteger(); |
| 79 } | 102 } |
| 80 | 103 |
| 81 | 104 |
| 82 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { | 105 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { |
| 83 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 106 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 84 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 107 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
| 85 ASSERT(CheckInteger(right_int)); | 108 ASSERT(CheckInteger(right_int)); |
| 86 ASSERT(CheckInteger(left_int)); | 109 ASSERT(CheckInteger(left_int)); |
| 87 if (FLAG_trace_intrinsified_natives) { | 110 if (FLAG_trace_intrinsified_natives) { |
| 88 OS::Print("Integer_addFromInteger %s + %s\n", | 111 OS::Print("Integer_addFromInteger %s + %s\n", |
| 89 left_int.ToCString(), right_int.ToCString()); | 112 left_int.ToCString(), right_int.ToCString()); |
| 90 } | 113 } |
| 91 const Integer& result = | 114 const Integer& result = |
| 92 Integer::Handle(left_int.ArithmeticOp(Token::kADD, right_int)); | 115 Integer::Handle(left_int.ArithmeticOp(Token::kADD, right_int)); |
| 116 if (FLAG_throw_on_53bit_overflow) { | |
| 117 ThrowExceptionOnOverflow(result, "Integer_addFromInteger"); | |
| 118 } | |
| 93 return result.AsValidInteger(); | 119 return result.AsValidInteger(); |
| 94 } | 120 } |
| 95 | 121 |
| 96 | 122 |
| 97 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { | 123 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { |
| 98 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 124 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 99 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 125 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
| 100 ASSERT(CheckInteger(right_int)); | 126 ASSERT(CheckInteger(right_int)); |
| 101 ASSERT(CheckInteger(left_int)); | 127 ASSERT(CheckInteger(left_int)); |
| 102 if (FLAG_trace_intrinsified_natives) { | 128 if (FLAG_trace_intrinsified_natives) { |
| 103 OS::Print("Integer_subFromInteger %s - %s\n", | 129 OS::Print("Integer_subFromInteger %s - %s\n", |
| 104 left_int.ToCString(), right_int.ToCString()); | 130 left_int.ToCString(), right_int.ToCString()); |
| 105 } | 131 } |
| 106 const Integer& result = | 132 const Integer& result = |
| 107 Integer::Handle(left_int.ArithmeticOp(Token::kSUB, right_int)); | 133 Integer::Handle(left_int.ArithmeticOp(Token::kSUB, right_int)); |
| 134 if (FLAG_throw_on_53bit_overflow) { | |
| 135 ThrowExceptionOnOverflow(result, "Integer_subFromInteger"); | |
| 136 } | |
| 108 return result.AsValidInteger(); | 137 return result.AsValidInteger(); |
| 109 } | 138 } |
| 110 | 139 |
| 111 | 140 |
| 112 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { | 141 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { |
| 113 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 142 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 114 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 143 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
| 115 ASSERT(CheckInteger(right_int)); | 144 ASSERT(CheckInteger(right_int)); |
| 116 ASSERT(CheckInteger(left_int)); | 145 ASSERT(CheckInteger(left_int)); |
| 117 if (FLAG_trace_intrinsified_natives) { | 146 if (FLAG_trace_intrinsified_natives) { |
| 118 OS::Print("Integer_mulFromInteger %s * %s\n", | 147 OS::Print("Integer_mulFromInteger %s * %s\n", |
| 119 left_int.ToCString(), right_int.ToCString()); | 148 left_int.ToCString(), right_int.ToCString()); |
| 120 } | 149 } |
| 121 const Integer& result = | 150 const Integer& result = |
| 122 Integer::Handle(left_int.ArithmeticOp(Token::kMUL, right_int)); | 151 Integer::Handle(left_int.ArithmeticOp(Token::kMUL, right_int)); |
| 152 if (FLAG_throw_on_53bit_overflow) { | |
| 153 ThrowExceptionOnOverflow(result, "Integer_mulFromInteger"); | |
| 154 } | |
| 123 return result.AsValidInteger(); | 155 return result.AsValidInteger(); |
| 124 } | 156 } |
| 125 | 157 |
| 126 | 158 |
| 127 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { | 159 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { |
| 128 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 160 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 129 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 161 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
| 130 ASSERT(CheckInteger(right_int)); | 162 ASSERT(CheckInteger(right_int)); |
| 131 ASSERT(CheckInteger(left_int)); | 163 ASSERT(CheckInteger(left_int)); |
| 132 ASSERT(!right_int.IsZero()); | 164 ASSERT(!right_int.IsZero()); |
| 133 const Integer& result = | 165 const Integer& result = |
| 134 Integer::Handle(left_int.ArithmeticOp(Token::kTRUNCDIV, right_int)); | 166 Integer::Handle(left_int.ArithmeticOp(Token::kTRUNCDIV, right_int)); |
| 167 if (FLAG_throw_on_53bit_overflow) { | |
| 168 ThrowExceptionOnOverflow(result, "Integer_trucDivFromInteger"); | |
| 169 } | |
| 135 return result.AsValidInteger(); | 170 return result.AsValidInteger(); |
| 136 } | 171 } |
| 137 | 172 |
| 138 | 173 |
| 139 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { | 174 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { |
| 140 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 175 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 141 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 176 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
| 142 ASSERT(CheckInteger(right_int)); | 177 ASSERT(CheckInteger(right_int)); |
| 143 ASSERT(CheckInteger(right_int)); | 178 ASSERT(CheckInteger(right_int)); |
| 144 if (FLAG_trace_intrinsified_natives) { | 179 if (FLAG_trace_intrinsified_natives) { |
| 145 OS::Print("Integer_moduloFromInteger %s mod %s\n", | 180 OS::Print("Integer_moduloFromInteger %s mod %s\n", |
| 146 left_int.ToCString(), right_int.ToCString()); | 181 left_int.ToCString(), right_int.ToCString()); |
| 147 } | 182 } |
| 148 if (right_int.IsZero()) { | 183 if (right_int.IsZero()) { |
| 149 // Should have been caught before calling into runtime. | 184 // Should have been caught before calling into runtime. |
| 150 UNIMPLEMENTED(); | 185 UNIMPLEMENTED(); |
| 151 } | 186 } |
| 152 const Integer& result = | 187 const Integer& result = |
| 153 Integer::Handle(left_int.ArithmeticOp(Token::kMOD, right_int)); | 188 Integer::Handle(left_int.ArithmeticOp(Token::kMOD, right_int)); |
| 189 if (FLAG_throw_on_53bit_overflow) { | |
| 190 ThrowExceptionOnOverflow(result, "Integer_moduloFromInteger"); | |
| 191 } | |
| 154 return result.AsValidInteger(); | 192 return result.AsValidInteger(); |
| 155 } | 193 } |
| 156 | 194 |
| 157 | 195 |
| 158 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { | 196 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { |
| 159 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 197 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
| 160 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 198 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
| 161 ASSERT(CheckInteger(right)); | 199 ASSERT(CheckInteger(right)); |
| 162 ASSERT(CheckInteger(left)); | 200 ASSERT(CheckInteger(left)); |
| 163 if (FLAG_trace_intrinsified_natives) { | 201 if (FLAG_trace_intrinsified_natives) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 186 if (value.IsOneByteString()) { | 224 if (value.IsOneByteString()) { |
| 187 // Quick conversion for unpadded integers in strings. | 225 // Quick conversion for unpadded integers in strings. |
| 188 const intptr_t len = value.Length(); | 226 const intptr_t len = value.Length(); |
| 189 if (len > 0) { | 227 if (len > 0) { |
| 190 const char* cstr = value.ToCString(); | 228 const char* cstr = value.ToCString(); |
| 191 ASSERT(cstr != NULL); | 229 ASSERT(cstr != NULL); |
| 192 char* p_end = NULL; | 230 char* p_end = NULL; |
| 193 const int64_t int_value = strtoll(cstr, &p_end, 10); | 231 const int64_t int_value = strtoll(cstr, &p_end, 10); |
| 194 if (p_end == (cstr + len)) { | 232 if (p_end == (cstr + len)) { |
| 195 if ((int_value != LLONG_MIN) && (int_value != LLONG_MAX)) { | 233 if ((int_value != LLONG_MIN) && (int_value != LLONG_MAX)) { |
| 196 return Integer::New(int_value); | 234 const Integer& i = Integer::Handle(Integer::New(int_value)); |
| 235 if (FLAG_throw_on_53bit_overflow) { | |
| 236 ThrowExceptionOnOverflow(i, "Integer_parse"); | |
| 237 } | |
| 238 return i.AsValidInteger(); | |
| 197 } | 239 } |
| 198 } | 240 } |
| 199 } | 241 } |
| 200 } | 242 } |
| 201 | 243 |
| 202 Scanner scanner(value, Symbols::Empty()); | 244 Scanner scanner(value, Symbols::Empty()); |
| 203 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); | 245 const Scanner::GrowableTokenStream& tokens = scanner.GetStream(); |
| 204 String* int_string; | 246 String* int_string; |
| 205 bool is_positive; | 247 bool is_positive; |
| 206 if (Scanner::IsValidLiteral(tokens, | 248 if (Scanner::IsValidLiteral(tokens, |
| 207 Token::kINTEGER, | 249 Token::kINTEGER, |
| 208 &is_positive, | 250 &is_positive, |
| 209 &int_string)) { | 251 &int_string)) { |
| 210 if (is_positive) { | 252 if (is_positive) { |
| 211 return Integer::New(*int_string); | 253 return Integer::New(*int_string); |
| 212 } | 254 } |
| 213 String& temp = String::Handle(); | 255 String& temp = String::Handle(); |
| 214 temp = String::Concat(Symbols::Dash(), *int_string); | 256 temp = String::Concat(Symbols::Dash(), *int_string); |
| 215 return Integer::New(temp); | 257 const Integer& i = Integer::Handle(Integer::New(temp)); |
| 258 if (FLAG_throw_on_53bit_overflow) { | |
| 259 ThrowExceptionOnOverflow(i, "Integer_parse"); | |
| 260 } | |
| 261 return i.AsValidInteger(); | |
| 216 } | 262 } |
| 217 | 263 |
| 218 const Array& args = Array::Handle(Array::New(1)); | 264 const Array& args = Array::Handle(Array::New(1)); |
| 219 args.SetAt(0, value); | 265 args.SetAt(0, value); |
| 220 Exceptions::ThrowByType(Exceptions::kFormat, args); | 266 Exceptions::ThrowByType(Exceptions::kFormat, args); |
| 221 return Object::null(); | 267 return Object::null(); |
| 222 } | 268 } |
| 223 | 269 |
| 224 | 270 |
| 225 static RawInteger* ShiftOperationHelper(Token::Kind kind, | 271 static RawInteger* ShiftOperationHelper(Token::Kind kind, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 } | 313 } |
| 268 | 314 |
| 269 | 315 |
| 270 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { | 316 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { |
| 271 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 317 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
| 272 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); | 318 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); |
| 273 ASSERT(CheckInteger(amount)); | 319 ASSERT(CheckInteger(amount)); |
| 274 ASSERT(CheckInteger(value)); | 320 ASSERT(CheckInteger(value)); |
| 275 const Integer& result = Integer::Handle( | 321 const Integer& result = Integer::Handle( |
| 276 ShiftOperationHelper(Token::kSHR, value, amount)); | 322 ShiftOperationHelper(Token::kSHR, value, amount)); |
| 323 if (FLAG_throw_on_53bit_overflow) { | |
| 324 ThrowExceptionOnOverflow(result, "Smi_shrFromInt"); | |
| 325 } | |
| 277 return result.AsValidInteger(); | 326 return result.AsValidInteger(); |
| 278 } | 327 } |
| 279 | 328 |
| 280 | 329 |
| 281 | 330 |
| 282 DEFINE_NATIVE_ENTRY(Smi_shlFromInt, 2) { | 331 DEFINE_NATIVE_ENTRY(Smi_shlFromInt, 2) { |
| 283 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 332 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
| 284 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); | 333 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); |
| 285 ASSERT(CheckInteger(amount)); | 334 ASSERT(CheckInteger(amount)); |
| 286 ASSERT(CheckInteger(value)); | 335 ASSERT(CheckInteger(value)); |
| 287 if (FLAG_trace_intrinsified_natives) { | 336 if (FLAG_trace_intrinsified_natives) { |
| 288 OS::Print("Smi_shlFromInt: %s << %s\n", | 337 OS::Print("Smi_shlFromInt: %s << %s\n", |
| 289 value.ToCString(), amount.ToCString()); | 338 value.ToCString(), amount.ToCString()); |
| 290 } | 339 } |
| 291 const Integer& result = Integer::Handle( | 340 const Integer& result = Integer::Handle( |
| 292 ShiftOperationHelper(Token::kSHL, value, amount)); | 341 ShiftOperationHelper(Token::kSHL, value, amount)); |
| 342 if (FLAG_throw_on_53bit_overflow) { | |
| 343 ThrowExceptionOnOverflow(result, "Smi_shlFromInt"); | |
| 344 } | |
| 293 return result.AsValidInteger(); | 345 return result.AsValidInteger(); |
| 294 } | 346 } |
| 295 | 347 |
| 296 | 348 |
| 297 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) { | 349 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) { |
| 298 const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 350 const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
| 299 if (FLAG_trace_intrinsified_natives) { | 351 if (FLAG_trace_intrinsified_natives) { |
| 300 OS::Print("Smi_bitNegate: %s\n", operand.ToCString()); | 352 OS::Print("Smi_bitNegate: %s\n", operand.ToCString()); |
| 301 } | 353 } |
| 302 intptr_t result = ~operand.Value(); | 354 intptr_t result = ~operand.Value(); |
| 303 ASSERT(Smi::IsValid(result)); | 355 ASSERT(Smi::IsValid(result)); |
| 304 return Smi::New(result); | 356 return Smi::New(result); |
| 305 } | 357 } |
| 306 | 358 |
| 307 // Mint natives. | 359 // Mint natives. |
| 308 | 360 |
| 309 DEFINE_NATIVE_ENTRY(Mint_bitNegate, 1) { | 361 DEFINE_NATIVE_ENTRY(Mint_bitNegate, 1) { |
| 310 const Mint& operand = Mint::CheckedHandle(arguments->NativeArgAt(0)); | 362 const Mint& operand = Mint::CheckedHandle(arguments->NativeArgAt(0)); |
| 311 ASSERT(CheckInteger(operand)); | 363 ASSERT(CheckInteger(operand)); |
| 312 if (FLAG_trace_intrinsified_natives) { | 364 if (FLAG_trace_intrinsified_natives) { |
| 313 OS::Print("Mint_bitNegate: %s\n", operand.ToCString()); | 365 OS::Print("Mint_bitNegate: %s\n", operand.ToCString()); |
| 314 } | 366 } |
| 315 int64_t result = ~operand.value(); | 367 int64_t result = ~operand.value(); |
| 316 return Integer::New(result); | 368 const Integer& i = Integer::Handle(Integer::New(result)); |
| 369 if (FLAG_throw_on_53bit_overflow) { | |
| 370 ThrowExceptionOnOverflow(i, "Integer_bitAndFromInteger"); | |
| 371 } | |
| 372 return i.AsValidInteger(); | |
|
siva
2013/05/23 01:28:22
Ditto question about the need for AsValidInteger.
zra
2013/05/23 15:59:07
Done.
| |
| 317 } | 373 } |
| 318 | 374 |
| 319 // Bigint natives. | 375 // Bigint natives. |
| 320 | 376 |
| 321 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { | 377 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { |
| 322 const Bigint& value = Bigint::CheckedHandle(arguments->NativeArgAt(0)); | 378 const Bigint& value = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
| 323 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); | 379 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); |
| 324 ASSERT(CheckInteger(value)); | 380 ASSERT(CheckInteger(value)); |
| 325 ASSERT(CheckInteger(result)); | 381 ASSERT(CheckInteger(result)); |
| 326 return result.AsValidInteger(); | 382 return result.AsValidInteger(); |
| 327 } | 383 } |
| 328 | 384 |
| 329 } // namespace dart | 385 } // namespace dart |
| OLD | NEW |