Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: runtime/lib/integers.cc

Issue 10968058: Support constant folding of instructions with constant smi values. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/platform/utils.h » ('j') | runtime/vm/flow_graph_optimizer.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/platform/utils.h » ('j') | runtime/vm/flow_graph_optimizer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698