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 "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "vm/bigint_operations.h" | |
9 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
10 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
11 #include "vm/exceptions.h" | 10 #include "vm/exceptions.h" |
12 #include "vm/isolate.h" | 11 #include "vm/isolate.h" |
13 #include "vm/native_entry.h" | 12 #include "vm/native_entry.h" |
14 #include "vm/object.h" | 13 #include "vm/object.h" |
15 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
16 #include "vm/symbols.h" | 15 #include "vm/symbols.h" |
17 | 16 |
18 namespace dart { | 17 namespace dart { |
19 | 18 |
20 DEFINE_FLAG(bool, trace_intrinsified_natives, false, | 19 DEFINE_FLAG(bool, trace_intrinsified_natives, false, |
21 "Report if any of the intrinsified natives are called"); | 20 "Report if any of the intrinsified natives are called"); |
22 | 21 |
23 // Smi natives. | 22 // Smi natives. |
24 | 23 |
25 // 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 |
26 // when it could have been a Smi. | 25 // when it could have been a Smi. |
27 static bool CheckInteger(const Integer& i) { | 26 static bool CheckInteger(const Integer& i) { |
28 if (i.IsBigint()) { | 27 if (i.IsBigint()) { |
29 const Bigint& bigint = Bigint::Cast(i); | 28 const Bigint& bigint = Bigint::Cast(i); |
30 return !BigintOperations::FitsIntoSmi(bigint) && | 29 return !bigint.FitsIntoSmi() && !bigint.FitsIntoInt64(); |
31 !BigintOperations::FitsIntoInt64(bigint); | |
32 } | 30 } |
33 if (i.IsMint()) { | 31 if (i.IsMint()) { |
34 const Mint& mint = Mint::Cast(i); | 32 const Mint& mint = Mint::Cast(i); |
35 return !Smi::IsValid(mint.value()); | 33 return !Smi::IsValid(mint.value()); |
36 } | 34 } |
37 return true; | 35 return true; |
38 } | 36 } |
39 | 37 |
40 | 38 |
41 static int BitLengthInt64(int64_t value) { | 39 static int BitLengthInt64(int64_t value) { |
42 value ^= value >> (8 * sizeof(value) - 1); // flip bits if negative. | 40 value ^= value >> (8 * sizeof(value) - 1); // flip bits if negative. |
| 41 // TODO(regis): Utils::HighestBit handles negative values. Why the above? |
43 return value == 0 ? 0 : Utils::HighestBit(value) + 1; | 42 return value == 0 ? 0 : Utils::HighestBit(value) + 1; |
44 } | 43 } |
45 | 44 |
46 | 45 |
47 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { | 46 DEFINE_NATIVE_ENTRY(Integer_bitAndFromInteger, 2) { |
48 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 47 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
49 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 48 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
50 ASSERT(CheckInteger(right)); | 49 ASSERT(CheckInteger(right)); |
51 ASSERT(CheckInteger(left)); | 50 ASSERT(CheckInteger(left)); |
52 if (FLAG_trace_intrinsified_natives) { | 51 if (FLAG_trace_intrinsified_natives) { |
53 OS::Print("Integer_bitAndFromInteger %s & %s\n", | 52 OS::Print("Integer_bitAndFromInteger %s & %s\n", |
54 right.ToCString(), left.ToCString()); | 53 right.ToCString(), left.ToCString()); |
55 } | 54 } |
56 const Integer& result = | 55 const Integer& result = Integer::Handle(left.BitOp(Token::kBIT_AND, right)); |
57 Integer::Handle(left.BitOp(Token::kBIT_AND, right)); | 56 // A null result indicates that a bigint operation is required. |
58 return result.AsValidInteger(); | 57 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
59 } | 58 } |
60 | 59 |
61 | 60 |
62 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { | 61 DEFINE_NATIVE_ENTRY(Integer_bitOrFromInteger, 2) { |
63 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 62 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
64 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 63 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
65 ASSERT(CheckInteger(right)); | 64 ASSERT(CheckInteger(right)); |
66 ASSERT(CheckInteger(left)); | 65 ASSERT(CheckInteger(left)); |
67 if (FLAG_trace_intrinsified_natives) { | 66 if (FLAG_trace_intrinsified_natives) { |
68 OS::Print("Integer_bitOrFromInteger %s | %s\n", | 67 OS::Print("Integer_bitOrFromInteger %s | %s\n", |
69 left.ToCString(), right.ToCString()); | 68 left.ToCString(), right.ToCString()); |
70 } | 69 } |
71 const Integer& result = | 70 const Integer& result = Integer::Handle(left.BitOp(Token::kBIT_OR, right)); |
72 Integer::Handle(left.BitOp(Token::kBIT_OR, right)); | 71 // A null result indicates that a bigint operation is required. |
73 return result.AsValidInteger(); | 72 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
74 } | 73 } |
75 | 74 |
76 | 75 |
77 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { | 76 DEFINE_NATIVE_ENTRY(Integer_bitXorFromInteger, 2) { |
78 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 77 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
79 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 78 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
80 ASSERT(CheckInteger(right)); | 79 ASSERT(CheckInteger(right)); |
81 ASSERT(CheckInteger(left)); | 80 ASSERT(CheckInteger(left)); |
82 if (FLAG_trace_intrinsified_natives) { | 81 if (FLAG_trace_intrinsified_natives) { |
83 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", | 82 OS::Print("Integer_bitXorFromInteger %s ^ %s\n", |
84 left.ToCString(), right.ToCString()); | 83 left.ToCString(), right.ToCString()); |
85 } | 84 } |
86 const Integer& result = | 85 const Integer& result = Integer::Handle(left.BitOp(Token::kBIT_XOR, right)); |
87 Integer::Handle(left.BitOp(Token::kBIT_XOR, right)); | 86 // A null result indicates that a bigint operation is required. |
88 return result.AsValidInteger(); | 87 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
89 } | 88 } |
90 | 89 |
91 | 90 |
92 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { | 91 DEFINE_NATIVE_ENTRY(Integer_addFromInteger, 2) { |
93 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 92 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
94 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 93 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
95 ASSERT(CheckInteger(right_int)); | 94 ASSERT(CheckInteger(right_int)); |
96 ASSERT(CheckInteger(left_int)); | 95 ASSERT(CheckInteger(left_int)); |
97 if (FLAG_trace_intrinsified_natives) { | 96 if (FLAG_trace_intrinsified_natives) { |
98 OS::Print("Integer_addFromInteger %s + %s\n", | 97 OS::Print("Integer_addFromInteger %s + %s\n", |
99 left_int.ToCString(), right_int.ToCString()); | 98 left_int.ToCString(), right_int.ToCString()); |
100 } | 99 } |
101 const Integer& result = | 100 const Integer& result = |
102 Integer::Handle(left_int.ArithmeticOp(Token::kADD, right_int)); | 101 Integer::Handle(left_int.ArithmeticOp(Token::kADD, right_int)); |
103 return result.AsValidInteger(); | 102 // A null result indicates that a bigint operation is required. |
| 103 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
104 } | 104 } |
105 | 105 |
106 | 106 |
107 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { | 107 DEFINE_NATIVE_ENTRY(Integer_subFromInteger, 2) { |
108 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 108 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
109 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 109 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
110 ASSERT(CheckInteger(right_int)); | 110 ASSERT(CheckInteger(right_int)); |
111 ASSERT(CheckInteger(left_int)); | 111 ASSERT(CheckInteger(left_int)); |
112 if (FLAG_trace_intrinsified_natives) { | 112 if (FLAG_trace_intrinsified_natives) { |
113 OS::Print("Integer_subFromInteger %s - %s\n", | 113 OS::Print("Integer_subFromInteger %s - %s\n", |
114 left_int.ToCString(), right_int.ToCString()); | 114 left_int.ToCString(), right_int.ToCString()); |
115 } | 115 } |
116 const Integer& result = | 116 const Integer& result = |
117 Integer::Handle(left_int.ArithmeticOp(Token::kSUB, right_int)); | 117 Integer::Handle(left_int.ArithmeticOp(Token::kSUB, right_int)); |
118 return result.AsValidInteger(); | 118 // A null result indicates that a bigint operation is required. |
| 119 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
119 } | 120 } |
120 | 121 |
121 | 122 |
122 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { | 123 DEFINE_NATIVE_ENTRY(Integer_mulFromInteger, 2) { |
123 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 124 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
124 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 125 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
125 ASSERT(CheckInteger(right_int)); | 126 ASSERT(CheckInteger(right_int)); |
126 ASSERT(CheckInteger(left_int)); | 127 ASSERT(CheckInteger(left_int)); |
127 if (FLAG_trace_intrinsified_natives) { | 128 if (FLAG_trace_intrinsified_natives) { |
128 OS::Print("Integer_mulFromInteger %s * %s\n", | 129 OS::Print("Integer_mulFromInteger %s * %s\n", |
129 left_int.ToCString(), right_int.ToCString()); | 130 left_int.ToCString(), right_int.ToCString()); |
130 } | 131 } |
131 const Integer& result = | 132 const Integer& result = |
132 Integer::Handle(left_int.ArithmeticOp(Token::kMUL, right_int)); | 133 Integer::Handle(left_int.ArithmeticOp(Token::kMUL, right_int)); |
133 return result.AsValidInteger(); | 134 // A null result indicates that a bigint operation is required. |
| 135 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
134 } | 136 } |
135 | 137 |
136 | 138 |
137 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { | 139 DEFINE_NATIVE_ENTRY(Integer_truncDivFromInteger, 2) { |
138 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 140 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
139 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 141 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
140 ASSERT(CheckInteger(right_int)); | 142 ASSERT(CheckInteger(right_int)); |
141 ASSERT(CheckInteger(left_int)); | 143 ASSERT(CheckInteger(left_int)); |
142 ASSERT(!right_int.IsZero()); | 144 ASSERT(!right_int.IsZero()); |
143 const Integer& result = | 145 const Integer& result = |
144 Integer::Handle(left_int.ArithmeticOp(Token::kTRUNCDIV, right_int)); | 146 Integer::Handle(left_int.ArithmeticOp(Token::kTRUNCDIV, right_int)); |
145 return result.AsValidInteger(); | 147 // A null result indicates that a bigint operation is required. |
| 148 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
146 } | 149 } |
147 | 150 |
148 | 151 |
149 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { | 152 DEFINE_NATIVE_ENTRY(Integer_moduloFromInteger, 2) { |
150 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 153 const Integer& right_int = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
151 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); | 154 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left_int, arguments->NativeArgAt(1)); |
152 ASSERT(CheckInteger(right_int)); | 155 ASSERT(CheckInteger(right_int)); |
153 ASSERT(CheckInteger(right_int)); | 156 ASSERT(CheckInteger(right_int)); |
154 if (FLAG_trace_intrinsified_natives) { | 157 if (FLAG_trace_intrinsified_natives) { |
155 OS::Print("Integer_moduloFromInteger %s mod %s\n", | 158 OS::Print("Integer_moduloFromInteger %s mod %s\n", |
156 left_int.ToCString(), right_int.ToCString()); | 159 left_int.ToCString(), right_int.ToCString()); |
157 } | 160 } |
158 if (right_int.IsZero()) { | 161 if (right_int.IsZero()) { |
159 // Should have been caught before calling into runtime. | 162 // Should have been caught before calling into runtime. |
160 UNIMPLEMENTED(); | 163 UNIMPLEMENTED(); |
161 } | 164 } |
162 const Integer& result = | 165 const Integer& result = |
163 Integer::Handle(left_int.ArithmeticOp(Token::kMOD, right_int)); | 166 Integer::Handle(left_int.ArithmeticOp(Token::kMOD, right_int)); |
164 return result.AsValidInteger(); | 167 // A null result indicates that a bigint operation is required. |
| 168 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
165 } | 169 } |
166 | 170 |
167 | 171 |
168 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { | 172 DEFINE_NATIVE_ENTRY(Integer_greaterThanFromInteger, 2) { |
169 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 173 const Integer& right = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
170 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); | 174 GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1)); |
171 ASSERT(CheckInteger(right)); | 175 ASSERT(CheckInteger(right)); |
172 ASSERT(CheckInteger(left)); | 176 ASSERT(CheckInteger(left)); |
173 if (FLAG_trace_intrinsified_natives) { | 177 if (FLAG_trace_intrinsified_natives) { |
174 OS::Print("Integer_greaterThanFromInteger %s > %s\n", | 178 OS::Print("Integer_greaterThanFromInteger %s > %s\n", |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 const Integer& value, | 263 const Integer& value, |
260 const Smi& amount, | 264 const Smi& amount, |
261 const bool silent = false) { | 265 const bool silent = false) { |
262 if (amount.Value() < 0) { | 266 if (amount.Value() < 0) { |
263 Exceptions::ThrowArgumentError(amount); | 267 Exceptions::ThrowArgumentError(amount); |
264 } | 268 } |
265 if (value.IsSmi()) { | 269 if (value.IsSmi()) { |
266 const Smi& smi_value = Smi::Cast(value); | 270 const Smi& smi_value = Smi::Cast(value); |
267 return smi_value.ShiftOp(kind, amount, silent); | 271 return smi_value.ShiftOp(kind, amount, silent); |
268 } | 272 } |
269 Bigint& big_value = Bigint::Handle(); | |
270 if (value.IsMint()) { | 273 if (value.IsMint()) { |
271 const int64_t mint_value = value.AsInt64Value(); | 274 const int64_t mint_value = value.AsInt64Value(); |
272 const int count = Utils::HighestBit(mint_value); | 275 const int count = Utils::HighestBit(mint_value); |
273 intptr_t shift_count = amount.Value(); | 276 intptr_t shift_count = amount.Value(); |
274 if (kind == Token::kSHR) { | 277 if (kind == Token::kSHR) { |
275 shift_count = -shift_count; | 278 shift_count = -shift_count; |
276 } | 279 } |
277 if ((count + shift_count) < Mint::kBits) { | 280 if ((count + shift_count) < Mint::kBits) { |
278 switch (kind) { | 281 switch (kind) { |
279 case Token::kSHL: | 282 case Token::kSHL: |
280 return Integer::New(mint_value << shift_count, Heap::kNew, silent); | 283 return Integer::New(mint_value << shift_count, Heap::kNew, silent); |
281 case Token::kSHR: | 284 case Token::kSHR: |
282 return Integer::New(mint_value >> -shift_count, Heap::kNew, silent); | 285 return Integer::New(mint_value >> -shift_count, Heap::kNew, silent); |
283 default: | 286 default: |
284 UNIMPLEMENTED(); | 287 UNIMPLEMENTED(); |
285 } | 288 } |
286 } else { | 289 } else { |
287 // Overflow in shift, use Bigints | 290 // Overflow in shift, use Bigints |
288 big_value = BigintOperations::NewFromInt64(mint_value); | 291 return Integer::null(); |
289 } | 292 } |
290 } else { | 293 } else { |
291 ASSERT(value.IsBigint()); | 294 ASSERT(value.IsBigint()); |
292 big_value = Bigint::Cast(value).raw(); | |
293 } | |
294 switch (kind) { | |
295 case Token::kSHL: | |
296 return BigintOperations::ShiftLeft(big_value, amount.Value()); | |
297 case Token::kSHR: | |
298 return BigintOperations::ShiftRight(big_value, amount.Value()); | |
299 default: | |
300 UNIMPLEMENTED(); | |
301 } | 295 } |
302 return Integer::null(); | 296 return Integer::null(); |
303 } | 297 } |
304 | 298 |
305 | 299 |
306 DEFINE_NATIVE_ENTRY(Integer_leftShiftWithMask32, 3) { | 300 DEFINE_NATIVE_ENTRY(Integer_leftShiftWithMask32, 3) { |
307 const Integer& value = Integer::CheckedHandle(arguments->NativeArgAt(0)); | 301 const Integer& value = Integer::CheckedHandle(arguments->NativeArgAt(0)); |
308 GET_NON_NULL_NATIVE_ARGUMENT(Integer, shift_count, arguments->NativeArgAt(1)); | 302 GET_NON_NULL_NATIVE_ARGUMENT(Integer, shift_count, arguments->NativeArgAt(1)); |
309 GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(2)); | 303 GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(2)); |
310 ASSERT(CheckInteger(value)); | 304 ASSERT(CheckInteger(value)); |
(...skipping 14 matching lines...) Expand all Loading... |
325 } | 319 } |
326 | 320 |
327 | 321 |
328 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { | 322 DEFINE_NATIVE_ENTRY(Smi_shrFromInt, 2) { |
329 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 323 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
330 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); | 324 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); |
331 ASSERT(CheckInteger(amount)); | 325 ASSERT(CheckInteger(amount)); |
332 ASSERT(CheckInteger(value)); | 326 ASSERT(CheckInteger(value)); |
333 const Integer& result = Integer::Handle( | 327 const Integer& result = Integer::Handle( |
334 ShiftOperationHelper(Token::kSHR, value, amount)); | 328 ShiftOperationHelper(Token::kSHR, value, amount)); |
335 return result.AsValidInteger(); | 329 // A null result indicates that a bigint operation is required. |
| 330 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
336 } | 331 } |
337 | 332 |
338 | 333 |
339 | 334 |
340 DEFINE_NATIVE_ENTRY(Smi_shlFromInt, 2) { | 335 DEFINE_NATIVE_ENTRY(Smi_shlFromInt, 2) { |
341 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 336 const Smi& amount = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
342 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); | 337 GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1)); |
343 ASSERT(CheckInteger(amount)); | 338 ASSERT(CheckInteger(amount)); |
344 ASSERT(CheckInteger(value)); | 339 ASSERT(CheckInteger(value)); |
345 if (FLAG_trace_intrinsified_natives) { | 340 if (FLAG_trace_intrinsified_natives) { |
346 OS::Print("Smi_shlFromInt: %s << %s\n", | 341 OS::Print("Smi_shlFromInt: %s << %s\n", |
347 value.ToCString(), amount.ToCString()); | 342 value.ToCString(), amount.ToCString()); |
348 } | 343 } |
349 const Integer& result = Integer::Handle( | 344 const Integer& result = Integer::Handle( |
350 ShiftOperationHelper(Token::kSHL, value, amount)); | 345 ShiftOperationHelper(Token::kSHL, value, amount)); |
351 return result.AsValidInteger(); | 346 // A null result indicates that a bigint operation is required. |
| 347 return result.IsNull() ? result.raw() : result.AsValidInteger(); |
352 } | 348 } |
353 | 349 |
354 | 350 |
355 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) { | 351 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) { |
356 const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0)); | 352 const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0)); |
357 if (FLAG_trace_intrinsified_natives) { | 353 if (FLAG_trace_intrinsified_natives) { |
358 OS::Print("Smi_bitNegate: %s\n", operand.ToCString()); | 354 OS::Print("Smi_bitNegate: %s\n", operand.ToCString()); |
359 } | 355 } |
360 intptr_t result = ~operand.Value(); | 356 intptr_t result = ~operand.Value(); |
361 ASSERT(Smi::IsValid(result)); | 357 ASSERT(Smi::IsValid(result)); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 const Instance& exception = | 403 const Instance& exception = |
408 Instance::Handle(isolate->object_store()->out_of_memory()); | 404 Instance::Handle(isolate->object_store()->out_of_memory()); |
409 Exceptions::Throw(isolate, exception); | 405 Exceptions::Throw(isolate, exception); |
410 UNREACHABLE(); | 406 UNREACHABLE(); |
411 return 0; | 407 return 0; |
412 } | 408 } |
413 | 409 |
414 | 410 |
415 // Bigint natives. | 411 // Bigint natives. |
416 | 412 |
417 DEFINE_NATIVE_ENTRY(Bigint_bitNegate, 1) { | 413 DEFINE_NATIVE_ENTRY(Bigint_getNeg, 1) { |
418 const Bigint& value = Bigint::CheckedHandle(arguments->NativeArgAt(0)); | 414 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
419 const Bigint& result = Bigint::Handle(BigintOperations::BitNot(value)); | 415 return bigint.neg(); |
420 ASSERT(CheckInteger(value)); | |
421 ASSERT(CheckInteger(result)); | |
422 return result.AsValidInteger(); | |
423 } | 416 } |
424 | 417 |
425 | 418 |
426 DEFINE_NATIVE_ENTRY(Bigint_bitLength, 1) { | 419 DEFINE_NATIVE_ENTRY(Bigint_setNeg, 2) { |
427 const Bigint& value = Bigint::CheckedHandle(arguments->NativeArgAt(0)); | 420 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
428 return Integer::New(BigintOperations::BitLength(value)); | 421 const Bool& neg = Bool::CheckedHandle(arguments->NativeArgAt(1)); |
| 422 bigint.set_neg(neg); |
| 423 return Object::null(); |
429 } | 424 } |
430 | 425 |
431 | 426 |
432 DEFINE_NATIVE_ENTRY(Bigint_shlFromInt, 2) { | 427 DEFINE_NATIVE_ENTRY(Bigint_getUsed, 1) { |
433 // Use the preallocated out of memory exception to avoid calling | 428 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
434 // into dart code or allocating any code. | 429 return bigint.used(); |
435 const Instance& exception = | 430 } |
436 Instance::Handle(isolate->object_store()->out_of_memory()); | 431 |
437 Exceptions::Throw(isolate, exception); | 432 |
438 UNREACHABLE(); | 433 DEFINE_NATIVE_ENTRY(Bigint_setUsed, 2) { |
439 return 0; | 434 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
| 435 const Smi& used = Smi::CheckedHandle(arguments->NativeArgAt(1)); |
| 436 bigint.set_used(used); |
| 437 return Object::null(); |
| 438 } |
| 439 |
| 440 |
| 441 DEFINE_NATIVE_ENTRY(Bigint_getDigits, 1) { |
| 442 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
| 443 return bigint.digits(); |
| 444 } |
| 445 |
| 446 |
| 447 DEFINE_NATIVE_ENTRY(Bigint_setDigits, 2) { |
| 448 const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0)); |
| 449 const TypedData& digits = TypedData::CheckedHandle(arguments->NativeArgAt(1)); |
| 450 bigint.set_digits(digits); |
| 451 return Object::null(); |
| 452 } |
| 453 |
| 454 |
| 455 DEFINE_NATIVE_ENTRY(Bigint_allocate, 1) { |
| 456 // Argument is null type arguments, since class Bigint is not parameterized. |
| 457 return Bigint::New(); |
440 } | 458 } |
441 | 459 |
442 } // namespace dart | 460 } // namespace dart |
OLD | NEW |