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

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month 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
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/bootstrap.h" 8 #include "vm/bootstrap.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/constant_propagator.h" 10 #include "vm/constant_propagator.h"
(...skipping 11 matching lines...) Expand all
22 #include "vm/regexp_assembler_ir.h" 22 #include "vm/regexp_assembler_ir.h"
23 #include "vm/resolver.h" 23 #include "vm/resolver.h"
24 #include "vm/scopes.h" 24 #include "vm/scopes.h"
25 #include "vm/stub_code.h" 25 #include "vm/stub_code.h"
26 #include "vm/symbols.h" 26 #include "vm/symbols.h"
27 27
28 #include "vm/il_printer.h" 28 #include "vm/il_printer.h"
29 29
30 namespace dart { 30 namespace dart {
31 31
32 DEFINE_FLAG(bool, propagate_ic_data, true, 32 DEFINE_FLAG(bool,
33 "Propagate IC data from unoptimized to optimized IC calls."); 33 propagate_ic_data,
34 DEFINE_FLAG(bool, two_args_smi_icd, true, 34 true,
35 "Generate special IC stubs for two args Smi operations"); 35 "Propagate IC data from unoptimized to optimized IC calls.");
36 DEFINE_FLAG(bool, unbox_numeric_fields, !USING_DBC, 36 DEFINE_FLAG(bool,
37 "Support unboxed double and float32x4 fields."); 37 two_args_smi_icd,
38 true,
39 "Generate special IC stubs for two args Smi operations");
40 DEFINE_FLAG(bool,
41 unbox_numeric_fields,
42 !USING_DBC,
43 "Support unboxed double and float32x4 fields.");
38 DECLARE_FLAG(bool, eliminate_type_checks); 44 DECLARE_FLAG(bool, eliminate_type_checks);
39 DECLARE_FLAG(bool, support_externalizable_strings); 45 DECLARE_FLAG(bool, support_externalizable_strings);
40 46
41 47
42 #if defined(DEBUG) 48 #if defined(DEBUG)
43 void Instruction::CheckField(const Field& field) const { 49 void Instruction::CheckField(const Field& field) const {
44 ASSERT(field.IsZoneHandle()); 50 ASSERT(field.IsZoneHandle());
45 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal()); 51 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal());
46 } 52 }
47 #endif // DEBUG 53 #endif // DEBUG
48 54
49 55
50 Definition::Definition(intptr_t deopt_id) 56 Definition::Definition(intptr_t deopt_id)
51 : Instruction(deopt_id), 57 : Instruction(deopt_id),
52 range_(NULL), 58 range_(NULL),
53 type_(NULL), 59 type_(NULL),
54 temp_index_(-1), 60 temp_index_(-1),
55 ssa_temp_index_(-1), 61 ssa_temp_index_(-1),
56 input_use_list_(NULL), 62 input_use_list_(NULL),
57 env_use_list_(NULL), 63 env_use_list_(NULL),
58 constant_value_(NULL) { 64 constant_value_(NULL) {}
59 }
60 65
61 66
62 // A value in the constant propagation lattice. 67 // A value in the constant propagation lattice.
63 // - non-constant sentinel 68 // - non-constant sentinel
64 // - a constant (any non-sentinel value) 69 // - a constant (any non-sentinel value)
65 // - unknown sentinel 70 // - unknown sentinel
66 Object& Definition::constant_value() { 71 Object& Definition::constant_value() {
67 if (constant_value_ == NULL) { 72 if (constant_value_ == NULL) {
68 constant_value_ = &Object::ZoneHandle(ConstantPropagator::Unknown()); 73 constant_value_ = &Object::ZoneHandle(ConstantPropagator::Unknown());
69 } 74 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 } 188 }
184 } 189 }
185 return true; 190 return true;
186 } 191 }
187 192
188 193
189 static bool AreAllChecksImmutable(const ICData& checks) { 194 static bool AreAllChecksImmutable(const ICData& checks) {
190 const intptr_t len = checks.NumberOfChecks(); 195 const intptr_t len = checks.NumberOfChecks();
191 for (intptr_t i = 0; i < len; i++) { 196 for (intptr_t i = 0; i < len; i++) {
192 if (checks.IsUsedAt(i)) { 197 if (checks.IsUsedAt(i)) {
193 if (Field::IsExternalizableCid( 198 if (Field::IsExternalizableCid(checks.GetReceiverClassIdAt(i))) {
194 checks.GetReceiverClassIdAt(i))) {
195 return false; 199 return false;
196 } 200 }
197 } 201 }
198 } 202 }
199 return true; 203 return true;
200 } 204 }
201 205
202 206
203 EffectSet CheckClassInstr::Dependencies() const { 207 EffectSet CheckClassInstr::Dependencies() const {
204 // Externalization of strings via the API can change the class-id. 208 // Externalization of strings via the API can change the class-id.
205 return !AreAllChecksImmutable(unary_checks()) ? 209 return !AreAllChecksImmutable(unary_checks()) ? EffectSet::Externalization()
206 EffectSet::Externalization() : EffectSet::None(); 210 : EffectSet::None();
207 } 211 }
208 212
209 213
210 EffectSet CheckClassIdInstr::Dependencies() const { 214 EffectSet CheckClassIdInstr::Dependencies() const {
211 // Externalization of strings via the API can change the class-id. 215 // Externalization of strings via the API can change the class-id.
212 return Field::IsExternalizableCid(cid_) ? 216 return Field::IsExternalizableCid(cid_) ? EffectSet::Externalization()
213 EffectSet::Externalization() : EffectSet::None(); 217 : EffectSet::None();
214 } 218 }
215 219
216 220
217 bool CheckClassInstr::DeoptIfNull() const { 221 bool CheckClassInstr::DeoptIfNull() const {
218 if (unary_checks().NumberOfChecks() != 1) { 222 if (unary_checks().NumberOfChecks() != 1) {
219 return false; 223 return false;
220 } 224 }
221 CompileType* in_type = value()->Type(); 225 CompileType* in_type = value()->Type();
222 const intptr_t cid = unary_checks().GetCidAt(0); 226 const intptr_t cid = unary_checks().GetCidAt(0);
223 // Performance check: use CheckSmiInstr instead. 227 // Performance check: use CheckSmiInstr instead.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 274
271 275
272 bool CheckClassInstr::IsDenseMask(intptr_t mask) { 276 bool CheckClassInstr::IsDenseMask(intptr_t mask) {
273 // Returns true if the mask is a continuos sequence of ones in its binary 277 // Returns true if the mask is a continuos sequence of ones in its binary
274 // representation (i.e. no holes) 278 // representation (i.e. no holes)
275 return mask == -1 || Utils::IsPowerOfTwo(mask + 1); 279 return mask == -1 || Utils::IsPowerOfTwo(mask + 1);
276 } 280 }
277 281
278 282
279 bool LoadFieldInstr::IsUnboxedLoad() const { 283 bool LoadFieldInstr::IsUnboxedLoad() const {
280 return FLAG_unbox_numeric_fields 284 return FLAG_unbox_numeric_fields && (field() != NULL) &&
281 && (field() != NULL) 285 FlowGraphCompiler::IsUnboxedField(*field());
282 && FlowGraphCompiler::IsUnboxedField(*field());
283 } 286 }
284 287
285 288
286 bool LoadFieldInstr::IsPotentialUnboxedLoad() const { 289 bool LoadFieldInstr::IsPotentialUnboxedLoad() const {
287 return FLAG_unbox_numeric_fields 290 return FLAG_unbox_numeric_fields && (field() != NULL) &&
288 && (field() != NULL) 291 FlowGraphCompiler::IsPotentialUnboxedField(*field());
289 && FlowGraphCompiler::IsPotentialUnboxedField(*field());
290 } 292 }
291 293
292 294
293 Representation LoadFieldInstr::representation() const { 295 Representation LoadFieldInstr::representation() const {
294 if (IsUnboxedLoad()) { 296 if (IsUnboxedLoad()) {
295 const intptr_t cid = field()->UnboxedFieldCid(); 297 const intptr_t cid = field()->UnboxedFieldCid();
296 switch (cid) { 298 switch (cid) {
297 case kDoubleCid: 299 case kDoubleCid:
298 return kUnboxedDouble; 300 return kUnboxedDouble;
299 case kFloat32x4Cid: 301 case kFloat32x4Cid:
300 return kUnboxedFloat32x4; 302 return kUnboxedFloat32x4;
301 case kFloat64x2Cid: 303 case kFloat64x2Cid:
302 return kUnboxedFloat64x2; 304 return kUnboxedFloat64x2;
303 default: 305 default:
304 UNREACHABLE(); 306 UNREACHABLE();
305 } 307 }
306 } 308 }
307 return kTagged; 309 return kTagged;
308 } 310 }
309 311
310 312
311 bool StoreInstanceFieldInstr::IsUnboxedStore() const { 313 bool StoreInstanceFieldInstr::IsUnboxedStore() const {
312 return FLAG_unbox_numeric_fields 314 return FLAG_unbox_numeric_fields && !field().IsNull() &&
313 && !field().IsNull() 315 FlowGraphCompiler::IsUnboxedField(field());
314 && FlowGraphCompiler::IsUnboxedField(field());
315 } 316 }
316 317
317 318
318 bool StoreInstanceFieldInstr::IsPotentialUnboxedStore() const { 319 bool StoreInstanceFieldInstr::IsPotentialUnboxedStore() const {
319 return FLAG_unbox_numeric_fields 320 return FLAG_unbox_numeric_fields && !field().IsNull() &&
320 && !field().IsNull() 321 FlowGraphCompiler::IsPotentialUnboxedField(field());
321 && FlowGraphCompiler::IsPotentialUnboxedField(field());
322 } 322 }
323 323
324 324
325 Representation StoreInstanceFieldInstr::RequiredInputRepresentation( 325 Representation StoreInstanceFieldInstr::RequiredInputRepresentation(
326 intptr_t index) const { 326 intptr_t index) const {
327 ASSERT((index == 0) || (index == 1)); 327 ASSERT((index == 0) || (index == 1));
328 if ((index == 1) && IsUnboxedStore()) { 328 if ((index == 1) && IsUnboxedStore()) {
329 const intptr_t cid = field().UnboxedFieldCid(); 329 const intptr_t cid = field().UnboxedFieldCid();
330 switch (cid) { 330 switch (cid) {
331 case kDoubleCid: 331 case kDoubleCid:
332 return kUnboxedDouble; 332 return kUnboxedDouble;
333 case kFloat32x4Cid: 333 case kFloat32x4Cid:
334 return kUnboxedFloat32x4; 334 return kUnboxedFloat32x4;
335 case kFloat64x2Cid: 335 case kFloat64x2Cid:
336 return kUnboxedFloat64x2; 336 return kUnboxedFloat64x2;
(...skipping 21 matching lines...) Expand all
358 // This predicate has to be commutative for DominatorBasedCSE to work. 358 // This predicate has to be commutative for DominatorBasedCSE to work.
359 // TODO(fschneider): Eliminate more asserts with subtype relation. 359 // TODO(fschneider): Eliminate more asserts with subtype relation.
360 return dst_type().raw() == other_assert->dst_type().raw(); 360 return dst_type().raw() == other_assert->dst_type().raw();
361 } 361 }
362 362
363 363
364 bool StrictCompareInstr::AttributesEqual(Instruction* other) const { 364 bool StrictCompareInstr::AttributesEqual(Instruction* other) const {
365 StrictCompareInstr* other_op = other->AsStrictCompare(); 365 StrictCompareInstr* other_op = other->AsStrictCompare();
366 ASSERT(other_op != NULL); 366 ASSERT(other_op != NULL);
367 return ComparisonInstr::AttributesEqual(other) && 367 return ComparisonInstr::AttributesEqual(other) &&
368 (needs_number_check() == other_op->needs_number_check()); 368 (needs_number_check() == other_op->needs_number_check());
369 } 369 }
370 370
371 371
372 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const { 372 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const {
373 MathMinMaxInstr* other_op = other->AsMathMinMax(); 373 MathMinMaxInstr* other_op = other->AsMathMinMax();
374 ASSERT(other_op != NULL); 374 ASSERT(other_op != NULL);
375 return (op_kind() == other_op->op_kind()) && 375 return (op_kind() == other_op->op_kind()) &&
376 (result_cid() == other_op->result_cid()); 376 (result_cid() == other_op->result_cid());
377 } 377 }
378 378
379 379
380 bool BinaryIntegerOpInstr::AttributesEqual(Instruction* other) const { 380 bool BinaryIntegerOpInstr::AttributesEqual(Instruction* other) const {
381 ASSERT(other->tag() == tag()); 381 ASSERT(other->tag() == tag());
382 BinaryIntegerOpInstr* other_op = other->AsBinaryIntegerOp(); 382 BinaryIntegerOpInstr* other_op = other->AsBinaryIntegerOp();
383 return (op_kind() == other_op->op_kind()) && 383 return (op_kind() == other_op->op_kind()) &&
384 (can_overflow() == other_op->can_overflow()) && 384 (can_overflow() == other_op->can_overflow()) &&
385 (is_truncating() == other_op->is_truncating()); 385 (is_truncating() == other_op->is_truncating());
386 } 386 }
387 387
388 388
389 EffectSet LoadFieldInstr::Dependencies() const { 389 EffectSet LoadFieldInstr::Dependencies() const {
390 return immutable_ ? EffectSet::None() : EffectSet::All(); 390 return immutable_ ? EffectSet::None() : EffectSet::All();
391 } 391 }
392 392
393 393
394 bool LoadFieldInstr::AttributesEqual(Instruction* other) const { 394 bool LoadFieldInstr::AttributesEqual(Instruction* other) const {
395 LoadFieldInstr* other_load = other->AsLoadField(); 395 LoadFieldInstr* other_load = other->AsLoadField();
396 ASSERT(other_load != NULL); 396 ASSERT(other_load != NULL);
397 if (field() != NULL) { 397 if (field() != NULL) {
398 return (other_load->field() != NULL) && 398 return (other_load->field() != NULL) &&
399 (field()->raw() == other_load->field()->raw()); 399 (field()->raw() == other_load->field()->raw());
400 } 400 }
401 return (other_load->field() == NULL) && 401 return (other_load->field() == NULL) &&
402 (offset_in_bytes() == other_load->offset_in_bytes()); 402 (offset_in_bytes() == other_load->offset_in_bytes());
403 } 403 }
404 404
405 405
406 Instruction* InitStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) { 406 Instruction* InitStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
407 const bool is_initialized = 407 const bool is_initialized =
408 (field_.StaticValue() != Object::sentinel().raw()) && 408 (field_.StaticValue() != Object::sentinel().raw()) &&
409 (field_.StaticValue() != Object::transition_sentinel().raw()); 409 (field_.StaticValue() != Object::transition_sentinel().raw());
410 // When precompiling, the fact that a field is currently initialized does not 410 // When precompiling, the fact that a field is currently initialized does not
411 // make it safe to omit code that checks if the field needs initialization 411 // make it safe to omit code that checks if the field needs initialization
412 // because the field will be reset so it starts uninitialized in the process 412 // because the field will be reset so it starts uninitialized in the process
413 // running the precompiled code. We must be prepared to reinitialize fields. 413 // running the precompiled code. We must be prepared to reinitialize fields.
414 return is_initialized && !FLAG_fields_may_be_reset ? NULL : this; 414 return is_initialized && !FLAG_fields_may_be_reset ? NULL : this;
415 } 415 }
416 416
417 417
418 EffectSet LoadStaticFieldInstr::Dependencies() const { 418 EffectSet LoadStaticFieldInstr::Dependencies() const {
419 return (StaticField().is_final() && !FLAG_fields_may_be_reset) 419 return (StaticField().is_final() && !FLAG_fields_may_be_reset)
420 ? EffectSet::None() : EffectSet::All(); 420 ? EffectSet::None()
421 : EffectSet::All();
421 } 422 }
422 423
423 424
424 bool LoadStaticFieldInstr::AttributesEqual(Instruction* other) const { 425 bool LoadStaticFieldInstr::AttributesEqual(Instruction* other) const {
425 LoadStaticFieldInstr* other_load = other->AsLoadStaticField(); 426 LoadStaticFieldInstr* other_load = other->AsLoadStaticField();
426 ASSERT(other_load != NULL); 427 ASSERT(other_load != NULL);
427 // Assert that the field is initialized. 428 // Assert that the field is initialized.
428 ASSERT(StaticField().StaticValue() != Object::sentinel().raw()); 429 ASSERT(StaticField().StaticValue() != Object::sentinel().raw());
429 ASSERT(StaticField().StaticValue() != Object::transition_sentinel().raw()); 430 ASSERT(StaticField().StaticValue() != Object::transition_sentinel().raw());
430 return StaticField().raw() == other_load->StaticField().raw(); 431 return StaticField().raw() == other_load->StaticField().raw();
431 } 432 }
432 433
433 434
434 const Field& LoadStaticFieldInstr::StaticField() const { 435 const Field& LoadStaticFieldInstr::StaticField() const {
435 Field& field = Field::ZoneHandle(); 436 Field& field = Field::ZoneHandle();
436 field ^= field_value()->BoundConstant().raw(); 437 field ^= field_value()->BoundConstant().raw();
437 return field; 438 return field;
438 } 439 }
439 440
440 441
441 ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos) 442 ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos)
442 : value_(value), 443 : value_(value), token_pos_(token_pos) {
443 token_pos_(token_pos) {
444 // Check that the value is not an incorrect Integer representation. 444 // Check that the value is not an incorrect Integer representation.
445 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoSmi()); 445 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoSmi());
446 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoInt64()); 446 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoInt64());
447 ASSERT(!value.IsMint() || !Smi::IsValid(Mint::Cast(value).AsInt64Value())); 447 ASSERT(!value.IsMint() || !Smi::IsValid(Mint::Cast(value).AsInt64Value()));
448 ASSERT(!value.IsField() || Field::Cast(value).IsOriginal()); 448 ASSERT(!value.IsField() || Field::Cast(value).IsOriginal());
449 } 449 }
450 450
451 451
452 bool ConstantInstr::AttributesEqual(Instruction* other) const { 452 bool ConstantInstr::AttributesEqual(Instruction* other) const {
453 ConstantInstr* other_constant = other->AsConstant(); 453 ConstantInstr* other_constant = other->AsConstant();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 intptr_t osr_id) 495 intptr_t osr_id)
496 : BlockEntryInstr(0, CatchClauseNode::kInvalidTryIndex), 496 : BlockEntryInstr(0, CatchClauseNode::kInvalidTryIndex),
497 parsed_function_(parsed_function), 497 parsed_function_(parsed_function),
498 normal_entry_(normal_entry), 498 normal_entry_(normal_entry),
499 catch_entries_(), 499 catch_entries_(),
500 indirect_entries_(), 500 indirect_entries_(),
501 initial_definitions_(), 501 initial_definitions_(),
502 osr_id_(osr_id), 502 osr_id_(osr_id),
503 entry_count_(0), 503 entry_count_(0),
504 spill_slot_count_(0), 504 spill_slot_count_(0),
505 fixed_slot_count_(0) { 505 fixed_slot_count_(0) {}
506 }
507 506
508 507
509 ConstantInstr* GraphEntryInstr::constant_null() { 508 ConstantInstr* GraphEntryInstr::constant_null() {
510 ASSERT(initial_definitions_.length() > 0); 509 ASSERT(initial_definitions_.length() > 0);
511 for (intptr_t i = 0; i < initial_definitions_.length(); ++i) { 510 for (intptr_t i = 0; i < initial_definitions_.length(); ++i) {
512 ConstantInstr* defn = initial_definitions_[i]->AsConstant(); 511 ConstantInstr* defn = initial_definitions_[i]->AsConstant();
513 if (defn != NULL && defn->value().IsNull()) return defn; 512 if (defn != NULL && defn->value().IsNull()) return defn;
514 } 513 }
515 UNREACHABLE(); 514 UNREACHABLE();
516 return NULL; 515 return NULL;
(...skipping 11 matching lines...) Expand all
528 527
529 528
530 bool GraphEntryInstr::IsCompiledForOsr() const { 529 bool GraphEntryInstr::IsCompiledForOsr() const {
531 return osr_id_ != Compiler::kNoOSRDeoptId; 530 return osr_id_ != Compiler::kNoOSRDeoptId;
532 } 531 }
533 532
534 533
535 // ==== Support for visiting flow graphs. 534 // ==== Support for visiting flow graphs.
536 535
537 #define DEFINE_ACCEPT(ShortName) \ 536 #define DEFINE_ACCEPT(ShortName) \
538 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ 537 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \
539 visitor->Visit##ShortName(this); \ 538 visitor->Visit##ShortName(this); \
540 } 539 }
541 540
542 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) 541 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT)
543 542
544 #undef DEFINE_ACCEPT 543 #undef DEFINE_ACCEPT
545 544
546 545
547 void Instruction::SetEnvironment(Environment* deopt_env) { 546 void Instruction::SetEnvironment(Environment* deopt_env) {
548 intptr_t use_index = 0; 547 intptr_t use_index = 0;
549 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { 548 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
550 Value* use = it.CurrentValue(); 549 Value* use = it.CurrentValue();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 } 614 }
616 return tail; 615 return tail;
617 } 616 }
618 617
619 618
620 BlockEntryInstr* Instruction::GetBlock() { 619 BlockEntryInstr* Instruction::GetBlock() {
621 // TODO(fschneider): Implement a faster way to get the block of an 620 // TODO(fschneider): Implement a faster way to get the block of an
622 // instruction. 621 // instruction.
623 ASSERT(previous() != NULL); 622 ASSERT(previous() != NULL);
624 Instruction* result = previous(); 623 Instruction* result = previous();
625 while (!result->IsBlockEntry()) result = result->previous(); 624 while (!result->IsBlockEntry())
625 result = result->previous();
626 return result->AsBlockEntry(); 626 return result->AsBlockEntry();
627 } 627 }
628 628
629 629
630 void ForwardInstructionIterator::RemoveCurrentFromGraph() { 630 void ForwardInstructionIterator::RemoveCurrentFromGraph() {
631 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. 631 current_ = current_->RemoveFromGraph(true); // Set current_ to previous.
632 } 632 }
633 633
634 634
635 void BackwardInstructionIterator::RemoveCurrentFromGraph() { 635 void BackwardInstructionIterator::RemoveCurrentFromGraph() {
(...skipping 11 matching lines...) Expand all
647 current_iterator_ = &it; 647 current_iterator_ = &it;
648 for (; !it.Done(); it.Advance()) { 648 for (; !it.Done(); it.Advance()) {
649 it.Current()->Accept(this); 649 it.Current()->Accept(this);
650 } 650 }
651 current_iterator_ = NULL; 651 current_iterator_ = NULL;
652 } 652 }
653 } 653 }
654 654
655 655
656 bool Value::NeedsStoreBuffer() { 656 bool Value::NeedsStoreBuffer() {
657 if (Type()->IsNull() || 657 if (Type()->IsNull() || (Type()->ToNullableCid() == kSmiCid) ||
658 (Type()->ToNullableCid() == kSmiCid) ||
659 (Type()->ToNullableCid() == kBoolCid)) { 658 (Type()->ToNullableCid() == kBoolCid)) {
660 return false; 659 return false;
661 } 660 }
662 661
663 return !BindsToConstant(); 662 return !BindsToConstant();
664 } 663 }
665 664
666 665
667 void JoinEntryInstr::AddPredecessor(BlockEntryInstr* predecessor) { 666 void JoinEntryInstr::AddPredecessor(BlockEntryInstr* predecessor) {
668 // Require the predecessors to be sorted by block_id to make managing 667 // Require the predecessors to be sorted by block_id to make managing
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 it.CurrentValue()->RemoveFromUseList(); 786 it.CurrentValue()->RemoveFromUseList();
788 } 787 }
789 } 788 }
790 789
791 790
792 void Instruction::InheritDeoptTargetAfter(FlowGraph* flow_graph, 791 void Instruction::InheritDeoptTargetAfter(FlowGraph* flow_graph,
793 Definition* call, 792 Definition* call,
794 Definition* result) { 793 Definition* result) {
795 ASSERT(call->env() != NULL); 794 ASSERT(call->env() != NULL);
796 deopt_id_ = Thread::ToDeoptAfter(call->deopt_id_); 795 deopt_id_ = Thread::ToDeoptAfter(call->deopt_id_);
797 call->env()->DeepCopyAfterTo(flow_graph->zone(), 796 call->env()->DeepCopyAfterTo(
798 this, 797 flow_graph->zone(), this, call->ArgumentCount(),
799 call->ArgumentCount(), 798 flow_graph->constant_dead(),
800 flow_graph->constant_dead(), 799 result != NULL ? result : flow_graph->constant_dead());
801 result != NULL ? result
802 : flow_graph->constant_dead());
803 env()->set_deopt_id(deopt_id_); 800 env()->set_deopt_id(deopt_id_);
804 } 801 }
805 802
806 803
807 void Instruction::InheritDeoptTarget(Zone* zone, Instruction* other) { 804 void Instruction::InheritDeoptTarget(Zone* zone, Instruction* other) {
808 ASSERT(other->env() != NULL); 805 ASSERT(other->env() != NULL);
809 CopyDeoptIdFrom(*other); 806 CopyDeoptIdFrom(*other);
810 other->env()->DeepCopyTo(zone, this); 807 other->env()->DeepCopyTo(zone, this);
811 env()->set_deopt_id(deopt_id_); 808 env()->set_deopt_id(deopt_id_);
812 } 809 }
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 // Detect that a block has been visited as part of the current 913 // Detect that a block has been visited as part of the current
917 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block 914 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block
918 // will be 'marked' by (1) having a preorder number in the range of the 915 // will be 'marked' by (1) having a preorder number in the range of the
919 // preorder array and (2) being in the preorder array at that index. 916 // preorder array and (2) being in the preorder array at that index.
920 intptr_t i = block->preorder_number(); 917 intptr_t i = block->preorder_number();
921 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block); 918 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block);
922 } 919 }
923 920
924 921
925 // Base class implementation used for JoinEntry and TargetEntry. 922 // Base class implementation used for JoinEntry and TargetEntry.
926 bool BlockEntryInstr::DiscoverBlock( 923 bool BlockEntryInstr::DiscoverBlock(BlockEntryInstr* predecessor,
927 BlockEntryInstr* predecessor, 924 GrowableArray<BlockEntryInstr*>* preorder,
928 GrowableArray<BlockEntryInstr*>* preorder, 925 GrowableArray<intptr_t>* parent) {
929 GrowableArray<intptr_t>* parent) {
930 // If this block has a predecessor (i.e., is not the graph entry) we can 926 // If this block has a predecessor (i.e., is not the graph entry) we can
931 // assume the preorder array is non-empty. 927 // assume the preorder array is non-empty.
932 ASSERT((predecessor == NULL) || !preorder->is_empty()); 928 ASSERT((predecessor == NULL) || !preorder->is_empty());
933 // Blocks with a single predecessor cannot have been reached before. 929 // Blocks with a single predecessor cannot have been reached before.
934 ASSERT(IsJoinEntry() || !IsMarked(this, preorder)); 930 ASSERT(IsJoinEntry() || !IsMarked(this, preorder));
935 931
936 // 1. If the block has already been reached, add current_block as a 932 // 1. If the block has already been reached, add current_block as a
937 // basic-block predecessor and we are done. 933 // basic-block predecessor and we are done.
938 if (IsMarked(this, preorder)) { 934 if (IsMarked(this, preorder)) {
939 ASSERT(predecessor != NULL); 935 ASSERT(predecessor != NULL);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 1000
1005 GotoInstr* goto_join = new GotoInstr(AsJoinEntry()); 1001 GotoInstr* goto_join = new GotoInstr(AsJoinEntry());
1006 goto_join->CopyDeoptIdFrom(*parent); 1002 goto_join->CopyDeoptIdFrom(*parent);
1007 graph_entry->normal_entry()->LinkTo(goto_join); 1003 graph_entry->normal_entry()->LinkTo(goto_join);
1008 return true; 1004 return true;
1009 } 1005 }
1010 } 1006 }
1011 1007
1012 // Recursively search the successors. 1008 // Recursively search the successors.
1013 for (intptr_t i = instr->SuccessorCount() - 1; i >= 0; --i) { 1009 for (intptr_t i = instr->SuccessorCount() - 1; i >= 0; --i) {
1014 if (instr->SuccessorAt(i)->PruneUnreachable(graph_entry, 1010 if (instr->SuccessorAt(i)->PruneUnreachable(graph_entry, instr, osr_id,
1015 instr,
1016 osr_id,
1017 block_marks)) { 1011 block_marks)) {
1018 return true; 1012 return true;
1019 } 1013 }
1020 } 1014 }
1021 return false; 1015 return false;
1022 } 1016 }
1023 1017
1024 1018
1025 bool BlockEntryInstr::Dominates(BlockEntryInstr* other) const { 1019 bool BlockEntryInstr::Dominates(BlockEntryInstr* other) const {
1026 // TODO(fschneider): Make this faster by e.g. storing dominators for each 1020 // TODO(fschneider): Make this faster by e.g. storing dominators for each
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 if ((join->phis() == NULL) || (old_index == new_index)) return; 1083 if ((join->phis() == NULL) || (old_index == new_index)) return;
1090 // Otherwise, reorder the predecessor uses in each phi. 1084 // Otherwise, reorder the predecessor uses in each phi.
1091 for (PhiIterator it(join); !it.Done(); it.Advance()) { 1085 for (PhiIterator it(join); !it.Done(); it.Advance()) {
1092 PhiInstr* phi = it.Current(); 1086 PhiInstr* phi = it.Current();
1093 ASSERT(phi != NULL); 1087 ASSERT(phi != NULL);
1094 ASSERT(pred_count == phi->InputCount()); 1088 ASSERT(pred_count == phi->InputCount());
1095 // Save the predecessor use. 1089 // Save the predecessor use.
1096 Value* pred_use = phi->InputAt(old_index); 1090 Value* pred_use = phi->InputAt(old_index);
1097 // Move uses between old and new. 1091 // Move uses between old and new.
1098 intptr_t step = (old_index < new_index) ? 1 : -1; 1092 intptr_t step = (old_index < new_index) ? 1 : -1;
1099 for (intptr_t use_idx = old_index; 1093 for (intptr_t use_idx = old_index; use_idx != new_index;
1100 use_idx != new_index;
1101 use_idx += step) { 1094 use_idx += step) {
1102 phi->SetInputAt(use_idx, phi->InputAt(use_idx + step)); 1095 phi->SetInputAt(use_idx, phi->InputAt(use_idx + step));
1103 } 1096 }
1104 // Write the predecessor use. 1097 // Write the predecessor use.
1105 phi->SetInputAt(new_index, pred_use); 1098 phi->SetInputAt(new_index, pred_use);
1106 } 1099 }
1107 } 1100 }
1108 } 1101 }
1109 1102
1110 1103
1111 void BlockEntryInstr::ClearAllInstructions() { 1104 void BlockEntryInstr::ClearAllInstructions() {
1112 JoinEntryInstr* join = this->AsJoinEntry(); 1105 JoinEntryInstr* join = this->AsJoinEntry();
1113 if (join != NULL) { 1106 if (join != NULL) {
1114 for (PhiIterator it(join); !it.Done(); it.Advance()) { 1107 for (PhiIterator it(join); !it.Done(); it.Advance()) {
1115 it.Current()->UnuseAllInputs(); 1108 it.Current()->UnuseAllInputs();
1116 } 1109 }
1117 } 1110 }
1118 UnuseAllInputs(); 1111 UnuseAllInputs();
1119 for (ForwardInstructionIterator it(this); 1112 for (ForwardInstructionIterator it(this); !it.Done(); it.Advance()) {
1120 !it.Done();
1121 it.Advance()) {
1122 it.Current()->UnuseAllInputs(); 1113 it.Current()->UnuseAllInputs();
1123 } 1114 }
1124 } 1115 }
1125 1116
1126 1117
1127 PhiInstr* JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) { 1118 PhiInstr* JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) {
1128 // Lazily initialize the array of phis. 1119 // Lazily initialize the array of phis.
1129 // Currently, phis are stored in a sparse array that holds the phi 1120 // Currently, phis are stored in a sparse array that holds the phi
1130 // for variable with index i at position i. 1121 // for variable with index i at position i.
1131 // TODO(fschneider): Store phis in a more compact way. 1122 // TODO(fschneider): Store phis in a more compact way.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1232 return successor(); 1223 return successor();
1233 } 1224 }
1234 1225
1235 1226
1236 void Instruction::Goto(JoinEntryInstr* entry) { 1227 void Instruction::Goto(JoinEntryInstr* entry) {
1237 LinkTo(new GotoInstr(entry)); 1228 LinkTo(new GotoInstr(entry));
1238 } 1229 }
1239 1230
1240 1231
1241 bool UnboxedIntConverterInstr::CanDeoptimize() const { 1232 bool UnboxedIntConverterInstr::CanDeoptimize() const {
1242 return (to() == kUnboxedInt32) && 1233 return (to() == kUnboxedInt32) && !is_truncating() &&
1243 !is_truncating() && 1234 !RangeUtils::Fits(value()->definition()->range(),
1244 !RangeUtils::Fits(value()->definition()->range(), 1235 RangeBoundary::kRangeBoundaryInt32);
1245 RangeBoundary::kRangeBoundaryInt32);
1246 } 1236 }
1247 1237
1248 1238
1249 bool UnboxInt32Instr::CanDeoptimize() const { 1239 bool UnboxInt32Instr::CanDeoptimize() const {
1250 const intptr_t value_cid = value()->Type()->ToCid(); 1240 const intptr_t value_cid = value()->Type()->ToCid();
1251 if (value_cid == kSmiCid) { 1241 if (value_cid == kSmiCid) {
1252 return (kSmiBits > 32) && 1242 return (kSmiBits > 32) && !is_truncating() &&
1253 !is_truncating() && 1243 !RangeUtils::Fits(value()->definition()->range(),
1254 !RangeUtils::Fits(value()->definition()->range(), 1244 RangeBoundary::kRangeBoundaryInt32);
1255 RangeBoundary::kRangeBoundaryInt32);
1256 } else if (value_cid == kMintCid) { 1245 } else if (value_cid == kMintCid) {
1257 return !is_truncating() && 1246 return !is_truncating() &&
1258 !RangeUtils::Fits(value()->definition()->range(), 1247 !RangeUtils::Fits(value()->definition()->range(),
1259 RangeBoundary::kRangeBoundaryInt32); 1248 RangeBoundary::kRangeBoundaryInt32);
1260 } else if (is_truncating() && value()->definition()->IsBoxInteger()) { 1249 } else if (is_truncating() && value()->definition()->IsBoxInteger()) {
1261 return false; 1250 return false;
1262 } else if ((kSmiBits < 32) && value()->Type()->IsInt()) { 1251 } else if ((kSmiBits < 32) && value()->Type()->IsInt()) {
1263 // Note: we don't support truncation of Bigint values. 1252 // Note: we don't support truncation of Bigint values.
1264 return !RangeUtils::Fits(value()->definition()->range(), 1253 return !RangeUtils::Fits(value()->definition()->range(),
1265 RangeBoundary::kRangeBoundaryInt32); 1254 RangeBoundary::kRangeBoundaryInt32);
1266 } else { 1255 } else {
1267 return true; 1256 return true;
1268 } 1257 }
1269 } 1258 }
(...skipping 16 matching lines...) Expand all
1286 case Token::kBIT_AND: 1275 case Token::kBIT_AND:
1287 case Token::kBIT_OR: 1276 case Token::kBIT_OR:
1288 case Token::kBIT_XOR: 1277 case Token::kBIT_XOR:
1289 return false; 1278 return false;
1290 1279
1291 case Token::kSHR: 1280 case Token::kSHR:
1292 return false; 1281 return false;
1293 1282
1294 case Token::kSHL: 1283 case Token::kSHL:
1295 return can_overflow() || 1284 return can_overflow() ||
1296 !RangeUtils::IsPositive(right()->definition()->range()); 1285 !RangeUtils::IsPositive(right()->definition()->range());
1297 1286
1298 case Token::kMOD: { 1287 case Token::kMOD: {
1299 UNREACHABLE(); 1288 UNREACHABLE();
1300 } 1289 }
1301 1290
1302 default: 1291 default:
1303 return can_overflow(); 1292 return can_overflow();
1304 } 1293 }
1305 } 1294 }
1306 1295
1307 1296
1308 bool BinarySmiOpInstr::CanDeoptimize() const { 1297 bool BinarySmiOpInstr::CanDeoptimize() const {
1309 switch (op_kind()) { 1298 switch (op_kind()) {
1310 case Token::kBIT_AND: 1299 case Token::kBIT_AND:
1311 case Token::kBIT_OR: 1300 case Token::kBIT_OR:
1312 case Token::kBIT_XOR: 1301 case Token::kBIT_XOR:
1313 return false; 1302 return false;
1314 1303
1315 case Token::kSHR: 1304 case Token::kSHR:
1316 return !RangeUtils::IsPositive(right()->definition()->range()); 1305 return !RangeUtils::IsPositive(right()->definition()->range());
1317 1306
1318 case Token::kSHL: 1307 case Token::kSHL:
1319 return can_overflow() || 1308 return can_overflow() ||
1320 !RangeUtils::IsPositive(right()->definition()->range()); 1309 !RangeUtils::IsPositive(right()->definition()->range());
1321 1310
1322 case Token::kMOD: { 1311 case Token::kMOD: {
1323 Range* right_range = this->right()->definition()->range(); 1312 Range* right_range = this->right()->definition()->range();
1324 return (right_range == NULL) || right_range->Overlaps(0, 0); 1313 return (right_range == NULL) || right_range->Overlaps(0, 0);
1325 } 1314 }
1326 default: 1315 default:
1327 return can_overflow(); 1316 return can_overflow();
1328 } 1317 }
1329 } 1318 }
1330 1319
(...skipping 17 matching lines...) Expand all
1348 case kUnboxedMint: 1337 case kUnboxedMint:
1349 return 64; 1338 return 64;
1350 default: 1339 default:
1351 UNREACHABLE(); 1340 UNREACHABLE();
1352 return 0; 1341 return 0;
1353 } 1342 }
1354 } 1343 }
1355 1344
1356 1345
1357 static int64_t RepresentationMask(Representation r) { 1346 static int64_t RepresentationMask(Representation r) {
1358 return static_cast<int64_t>( 1347 return static_cast<int64_t>(static_cast<uint64_t>(-1) >>
1359 static_cast<uint64_t>(-1) >> (64 - RepresentationBits(r))); 1348 (64 - RepresentationBits(r)));
1360 } 1349 }
1361 1350
1362 1351
1363 static bool ToIntegerConstant(Value* value, int64_t* result) { 1352 static bool ToIntegerConstant(Value* value, int64_t* result) {
1364 if (!value->BindsToConstant()) { 1353 if (!value->BindsToConstant()) {
1365 UnboxInstr* unbox = value->definition()->AsUnbox(); 1354 UnboxInstr* unbox = value->definition()->AsUnbox();
1366 if (unbox != NULL) { 1355 if (unbox != NULL) {
1367 switch (unbox->representation()) { 1356 switch (unbox->representation()) {
1368 case kUnboxedDouble: 1357 case kUnboxedDouble:
1369 case kUnboxedMint: 1358 case kUnboxedMint:
(...skipping 26 matching lines...) Expand all
1396 return true; 1385 return true;
1397 } else if (constant.IsMint()) { 1386 } else if (constant.IsMint()) {
1398 *result = Mint::Cast(constant).value(); 1387 *result = Mint::Cast(constant).value();
1399 return true; 1388 return true;
1400 } 1389 }
1401 1390
1402 return false; 1391 return false;
1403 } 1392 }
1404 1393
1405 1394
1406 static Definition* CanonicalizeCommutativeDoubleArithmetic( 1395 static Definition* CanonicalizeCommutativeDoubleArithmetic(Token::Kind op,
1407 Token::Kind op, 1396 Value* left,
1408 Value* left, 1397 Value* right) {
1409 Value* right) {
1410 int64_t left_value; 1398 int64_t left_value;
1411 if (!ToIntegerConstant(left, &left_value)) { 1399 if (!ToIntegerConstant(left, &left_value)) {
1412 return NULL; 1400 return NULL;
1413 } 1401 }
1414 1402
1415 // Can't apply 0.0 * x -> 0.0 equivalence to double operation because 1403 // Can't apply 0.0 * x -> 0.0 equivalence to double operation because
1416 // 0.0 * NaN is NaN not 0.0. 1404 // 0.0 * NaN is NaN not 0.0.
1417 // Can't apply 0.0 + x -> x to double because 0.0 + (-0.0) is 0.0 not -0.0. 1405 // Can't apply 0.0 + x -> x to double because 0.0 + (-0.0) is 0.0 not -0.0.
1418 switch (op) { 1406 switch (op) {
1419 case Token::kMUL: 1407 case Token::kMUL:
(...skipping 15 matching lines...) Expand all
1435 1423
1436 return NULL; 1424 return NULL;
1437 } 1425 }
1438 1426
1439 1427
1440 Definition* DoubleToFloatInstr::Canonicalize(FlowGraph* flow_graph) { 1428 Definition* DoubleToFloatInstr::Canonicalize(FlowGraph* flow_graph) {
1441 #ifdef DEBUG 1429 #ifdef DEBUG
1442 // Must only be used in Float32 StoreIndexedInstr or FloatToDoubleInstr or 1430 // Must only be used in Float32 StoreIndexedInstr or FloatToDoubleInstr or
1443 // Phis introduce by load forwarding. 1431 // Phis introduce by load forwarding.
1444 ASSERT(env_use_list() == NULL); 1432 ASSERT(env_use_list() == NULL);
1445 for (Value* use = input_use_list(); 1433 for (Value* use = input_use_list(); use != NULL; use = use->next_use()) {
1446 use != NULL;
1447 use = use->next_use()) {
1448 ASSERT(use->instruction()->IsPhi() || 1434 ASSERT(use->instruction()->IsPhi() ||
1449 use->instruction()->IsFloatToDouble() || 1435 use->instruction()->IsFloatToDouble() ||
1450 (use->instruction()->IsStoreIndexed() && 1436 (use->instruction()->IsStoreIndexed() &&
1451 (use->instruction()->AsStoreIndexed()->class_id() == 1437 (use->instruction()->AsStoreIndexed()->class_id() ==
1452 kTypedDataFloat32ArrayCid))); 1438 kTypedDataFloat32ArrayCid)));
1453 } 1439 }
1454 #endif 1440 #endif
1455 if (!HasUses()) return NULL; 1441 if (!HasUses()) return NULL;
1456 if (value()->definition()->IsFloatToDouble()) { 1442 if (value()->definition()->IsFloatToDouble()) {
1457 // F2D(D2F(v)) == v. 1443 // F2D(D2F(v)) == v.
(...skipping 18 matching lines...) Expand all
1476 return result; 1462 return result;
1477 } 1463 }
1478 1464
1479 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), right(), left()); 1465 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), right(), left());
1480 if (result != NULL) { 1466 if (result != NULL) {
1481 return result; 1467 return result;
1482 } 1468 }
1483 1469
1484 if ((op_kind() == Token::kMUL) && 1470 if ((op_kind() == Token::kMUL) &&
1485 (left()->definition() == right()->definition())) { 1471 (left()->definition() == right()->definition())) {
1486 MathUnaryInstr* math_unary = 1472 MathUnaryInstr* math_unary = new MathUnaryInstr(
1487 new MathUnaryInstr(MathUnaryInstr::kDoubleSquare, 1473 MathUnaryInstr::kDoubleSquare, new Value(left()->definition()),
1488 new Value(left()->definition()), 1474 DeoptimizationTarget());
1489 DeoptimizationTarget());
1490 flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue); 1475 flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue);
1491 return math_unary; 1476 return math_unary;
1492 } 1477 }
1493 1478
1494 return this; 1479 return this;
1495 } 1480 }
1496 1481
1497 1482
1498 Definition* DoubleTestOpInstr::Canonicalize(FlowGraph* flow_graph) { 1483 Definition* DoubleTestOpInstr::Canonicalize(FlowGraph* flow_graph) {
1499 return HasUses() ? this : NULL; 1484 return HasUses() ? this : NULL;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 } 1610 }
1626 1611
1627 1612
1628 RawInteger* UnaryIntegerOpInstr::Evaluate(const Integer& value) const { 1613 RawInteger* UnaryIntegerOpInstr::Evaluate(const Integer& value) const {
1629 Thread* thread = Thread::Current(); 1614 Thread* thread = Thread::Current();
1630 Zone* zone = thread->zone(); 1615 Zone* zone = thread->zone();
1631 Integer& result = Integer::Handle(zone); 1616 Integer& result = Integer::Handle(zone);
1632 1617
1633 switch (op_kind()) { 1618 switch (op_kind()) {
1634 case Token::kNEGATE: 1619 case Token::kNEGATE:
1635 result = value.ArithmeticOp(Token::kMUL, 1620 result = value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)),
1636 Smi::Handle(zone, Smi::New(-1)),
1637 Heap::kOld); 1621 Heap::kOld);
1638 break; 1622 break;
1639 1623
1640 case Token::kBIT_NOT: 1624 case Token::kBIT_NOT:
1641 if (value.IsSmi()) { 1625 if (value.IsSmi()) {
1642 result = Integer::New(~Smi::Cast(value).Value()); 1626 result = Integer::New(~Smi::Cast(value).Value());
1643 } else if (value.IsMint()) { 1627 } else if (value.IsMint()) {
1644 result = Integer::New(~Mint::Cast(value).value()); 1628 result = Integer::New(~Mint::Cast(value).value());
1645 } 1629 }
1646 break; 1630 break;
(...skipping 23 matching lines...) Expand all
1670 Zone* zone = thread->zone(); 1654 Zone* zone = thread->zone();
1671 Integer& result = Integer::Handle(zone); 1655 Integer& result = Integer::Handle(zone);
1672 1656
1673 switch (op_kind()) { 1657 switch (op_kind()) {
1674 case Token::kTRUNCDIV: 1658 case Token::kTRUNCDIV:
1675 case Token::kMOD: 1659 case Token::kMOD:
1676 // Check right value for zero. 1660 // Check right value for zero.
1677 if (right.IsSmi() && right.AsInt64Value() == 0) { 1661 if (right.IsSmi() && right.AsInt64Value() == 0) {
1678 break; // Will throw. 1662 break; // Will throw.
1679 } 1663 }
1680 // Fall through. 1664 // Fall through.
1681 case Token::kADD: 1665 case Token::kADD:
1682 case Token::kSUB: 1666 case Token::kSUB:
1683 case Token::kMUL: { 1667 case Token::kMUL: {
1684 result = left.ArithmeticOp(op_kind(), right, Heap::kOld); 1668 result = left.ArithmeticOp(op_kind(), right, Heap::kOld);
1685 break; 1669 break;
1686 } 1670 }
1687 case Token::kSHL: 1671 case Token::kSHL:
1688 case Token::kSHR: 1672 case Token::kSHR:
1689 if (left.IsSmi() && right.IsSmi() && (Smi::Cast(right).Value() >= 0)) { 1673 if (left.IsSmi() && right.IsSmi() && (Smi::Cast(right).Value() >= 0)) {
1690 result = Smi::Cast(left).ShiftOp(op_kind(), 1674 result =
1691 Smi::Cast(right), 1675 Smi::Cast(left).ShiftOp(op_kind(), Smi::Cast(right), Heap::kOld);
1692 Heap::kOld);
1693 } 1676 }
1694 break; 1677 break;
1695 case Token::kBIT_AND: 1678 case Token::kBIT_AND:
1696 case Token::kBIT_OR: 1679 case Token::kBIT_OR:
1697 case Token::kBIT_XOR: { 1680 case Token::kBIT_XOR: {
1698 result = left.BitOp(op_kind(), right, Heap::kOld); 1681 result = left.BitOp(op_kind(), right, Heap::kOld);
1699 break; 1682 break;
1700 } 1683 }
1701 case Token::kDIV: 1684 case Token::kDIV:
1702 break; 1685 break;
(...skipping 18 matching lines...) Expand all
1721 } 1704 }
1722 1705
1723 return result.raw(); 1706 return result.raw();
1724 } 1707 }
1725 1708
1726 1709
1727 Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph, 1710 Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph,
1728 const Integer& result) { 1711 const Integer& result) {
1729 Definition* result_defn = flow_graph->GetConstant(result); 1712 Definition* result_defn = flow_graph->GetConstant(result);
1730 if (representation() != kTagged) { 1713 if (representation() != kTagged) {
1731 result_defn = UnboxInstr::Create(representation(), 1714 result_defn = UnboxInstr::Create(representation(), new Value(result_defn),
1732 new Value(result_defn),
1733 GetDeoptId()); 1715 GetDeoptId());
1734 flow_graph->InsertBefore(this, result_defn, env(), FlowGraph::kValue); 1716 flow_graph->InsertBefore(this, result_defn, env(), FlowGraph::kValue);
1735 } 1717 }
1736 return result_defn; 1718 return result_defn;
1737 } 1719 }
1738 1720
1739 1721
1740 Definition* CheckedSmiOpInstr::Canonicalize(FlowGraph* flow_graph) { 1722 Definition* CheckedSmiOpInstr::Canonicalize(FlowGraph* flow_graph) {
1741 if ((left()->Type()->ToCid() == kSmiCid) && 1723 if ((left()->Type()->ToCid() == kSmiCid) &&
1742 (right()->Type()->ToCid() == kSmiCid)) { 1724 (right()->Type()->ToCid() == kSmiCid)) {
1743 Definition* replacement = NULL; 1725 Definition* replacement = NULL;
1744 // Operations that can't deoptimize are specialized here: These include 1726 // Operations that can't deoptimize are specialized here: These include
1745 // bit-wise operators and comparisons. Other arithmetic operations can 1727 // bit-wise operators and comparisons. Other arithmetic operations can
1746 // overflow or divide by 0 and can't be specialized unless we have extra 1728 // overflow or divide by 0 and can't be specialized unless we have extra
1747 // range information. 1729 // range information.
1748 switch (op_kind()) { 1730 switch (op_kind()) {
1749 case Token::kBIT_AND: 1731 case Token::kBIT_AND:
1750 case Token::kBIT_OR: 1732 case Token::kBIT_OR:
1751 case Token::kBIT_XOR: 1733 case Token::kBIT_XOR:
1752 replacement = 1734 replacement = new BinarySmiOpInstr(
1753 new BinarySmiOpInstr(op_kind(), 1735 op_kind(), new Value(left()->definition()),
1754 new Value(left()->definition()), 1736 new Value(right()->definition()), Thread::kNoDeoptId);
1755 new Value(right()->definition()),
1756 Thread::kNoDeoptId);
1757 default: 1737 default:
1758 break; 1738 break;
1759 } 1739 }
1760 if (replacement != NULL) { 1740 if (replacement != NULL) {
1761 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); 1741 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
1762 return replacement; 1742 return replacement;
1763 } 1743 }
1764 } 1744 }
1765 return this; 1745 return this;
1766 } 1746 }
1767 1747
1768 1748
1769 ComparisonInstr* CheckedSmiComparisonInstr::CopyWithNewOperands( 1749 ComparisonInstr* CheckedSmiComparisonInstr::CopyWithNewOperands(Value* left,
1770 Value* left, Value* right) { 1750 Value* right) {
1771 UNREACHABLE(); 1751 UNREACHABLE();
1772 return NULL; 1752 return NULL;
1773 } 1753 }
1774 1754
1775 1755
1776 Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) { 1756 Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) {
1777 if ((left()->Type()->ToCid() == kSmiCid) && 1757 if ((left()->Type()->ToCid() == kSmiCid) &&
1778 (right()->Type()->ToCid() == kSmiCid)) { 1758 (right()->Type()->ToCid() == kSmiCid)) {
1779 Definition* replacement = NULL; 1759 Definition* replacement = NULL;
1780 if (Token::IsRelationalOperator(kind())) { 1760 if (Token::IsRelationalOperator(kind())) {
1781 replacement = new RelationalOpInstr(token_pos(), kind(), 1761 replacement = new RelationalOpInstr(
1782 new Value(left()->definition()), 1762 token_pos(), kind(), new Value(left()->definition()),
1783 new Value(right()->definition()), 1763 new Value(right()->definition()), kSmiCid, Thread::kNoDeoptId);
1784 kSmiCid,
1785 Thread::kNoDeoptId);
1786 } else if (Token::IsEqualityOperator(kind())) { 1764 } else if (Token::IsEqualityOperator(kind())) {
1787 replacement = new EqualityCompareInstr(token_pos(), kind(), 1765 replacement = new EqualityCompareInstr(
1788 new Value(left()->definition()), 1766 token_pos(), kind(), new Value(left()->definition()),
1789 new Value(right()->definition()), 1767 new Value(right()->definition()), kSmiCid, Thread::kNoDeoptId);
1790 kSmiCid,
1791 Thread::kNoDeoptId);
1792 } 1768 }
1793 if (replacement != NULL) { 1769 if (replacement != NULL) {
1794 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); 1770 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
1795 return replacement; 1771 return replacement;
1796 } 1772 }
1797 } 1773 }
1798 return this; 1774 return this;
1799 } 1775 }
1800 1776
1801 1777
1802 Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) { 1778 Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
1803 // If both operands are constants evaluate this expression. Might 1779 // If both operands are constants evaluate this expression. Might
1804 // occur due to load forwarding after constant propagation pass 1780 // occur due to load forwarding after constant propagation pass
1805 // have already been run. 1781 // have already been run.
1806 if (left()->BindsToConstant() && 1782 if (left()->BindsToConstant() && left()->BoundConstant().IsInteger() &&
1807 left()->BoundConstant().IsInteger() && 1783 right()->BindsToConstant() && right()->BoundConstant().IsInteger()) {
1808 right()->BindsToConstant() && 1784 const Integer& result =
1809 right()->BoundConstant().IsInteger()) { 1785 Integer::Handle(Evaluate(Integer::Cast(left()->BoundConstant()),
1810 const Integer& result = Integer::Handle( 1786 Integer::Cast(right()->BoundConstant())));
1811 Evaluate(Integer::Cast(left()->BoundConstant()),
1812 Integer::Cast(right()->BoundConstant())));
1813 if (!result.IsNull()) { 1787 if (!result.IsNull()) {
1814 return CreateConstantResult(flow_graph, result); 1788 return CreateConstantResult(flow_graph, result);
1815 } 1789 }
1816 } 1790 }
1817 1791
1818 if (left()->BindsToConstant() && 1792 if (left()->BindsToConstant() && !right()->BindsToConstant() &&
1819 !right()->BindsToConstant() &&
1820 IsCommutative(op_kind())) { 1793 IsCommutative(op_kind())) {
1821 Value* l = left(); 1794 Value* l = left();
1822 Value* r = right(); 1795 Value* r = right();
1823 SetInputAt(0, r); 1796 SetInputAt(0, r);
1824 SetInputAt(1, l); 1797 SetInputAt(1, l);
1825 } 1798 }
1826 1799
1827 int64_t rhs; 1800 int64_t rhs;
1828 if (!ToIntegerConstant(right(), &rhs)) { 1801 if (!ToIntegerConstant(right(), &rhs)) {
1829 return this; 1802 return this;
(...skipping 17 matching lines...) Expand all
1847 1820
1848 switch (op_kind()) { 1821 switch (op_kind()) {
1849 case Token::kMUL: 1822 case Token::kMUL:
1850 if (rhs == 1) { 1823 if (rhs == 1) {
1851 return left()->definition(); 1824 return left()->definition();
1852 } else if (rhs == 0) { 1825 } else if (rhs == 0) {
1853 return right()->definition(); 1826 return right()->definition();
1854 } else if (rhs == 2) { 1827 } else if (rhs == 2) {
1855 ConstantInstr* constant_1 = 1828 ConstantInstr* constant_1 =
1856 flow_graph->GetConstant(Smi::Handle(Smi::New(1))); 1829 flow_graph->GetConstant(Smi::Handle(Smi::New(1)));
1857 BinaryIntegerOpInstr* shift = 1830 BinaryIntegerOpInstr* shift = BinaryIntegerOpInstr::Make(
1858 BinaryIntegerOpInstr::Make(representation(), 1831 representation(), Token::kSHL, left()->CopyWithType(),
1859 Token::kSHL, 1832 new Value(constant_1), GetDeoptId(), can_overflow(),
1860 left()->CopyWithType(), 1833 is_truncating(), range());
1861 new Value(constant_1),
1862 GetDeoptId(),
1863 can_overflow(),
1864 is_truncating(),
1865 range());
1866 if (shift != NULL) { 1834 if (shift != NULL) {
1867 flow_graph->InsertBefore(this, shift, env(), FlowGraph::kValue); 1835 flow_graph->InsertBefore(this, shift, env(), FlowGraph::kValue);
1868 return shift; 1836 return shift;
1869 } 1837 }
1870 } 1838 }
1871 1839
1872 break; 1840 break;
1873 case Token::kADD: 1841 case Token::kADD:
1874 if (rhs == 0) { 1842 if (rhs == 0) {
1875 return left()->definition(); 1843 return left()->definition();
(...skipping 10 matching lines...) Expand all
1886 if (rhs == 0) { 1854 if (rhs == 0) {
1887 return left()->definition(); 1855 return left()->definition();
1888 } else if (rhs == range_mask) { 1856 } else if (rhs == range_mask) {
1889 return right()->definition(); 1857 return right()->definition();
1890 } 1858 }
1891 break; 1859 break;
1892 case Token::kBIT_XOR: 1860 case Token::kBIT_XOR:
1893 if (rhs == 0) { 1861 if (rhs == 0) {
1894 return left()->definition(); 1862 return left()->definition();
1895 } else if (rhs == range_mask) { 1863 } else if (rhs == range_mask) {
1896 UnaryIntegerOpInstr* bit_not = 1864 UnaryIntegerOpInstr* bit_not = UnaryIntegerOpInstr::Make(
1897 UnaryIntegerOpInstr::Make(representation(), 1865 representation(), Token::kBIT_NOT, left()->CopyWithType(),
1898 Token::kBIT_NOT, 1866 GetDeoptId(), range());
1899 left()->CopyWithType(),
1900 GetDeoptId(),
1901 range());
1902 if (bit_not != NULL) { 1867 if (bit_not != NULL) {
1903 flow_graph->InsertBefore(this, bit_not, env(), FlowGraph::kValue); 1868 flow_graph->InsertBefore(this, bit_not, env(), FlowGraph::kValue);
1904 return bit_not; 1869 return bit_not;
1905 } 1870 }
1906 } 1871 }
1907 break; 1872 break;
1908 1873
1909 case Token::kSUB: 1874 case Token::kSUB:
1910 if (rhs == 0) { 1875 if (rhs == 0) {
1911 return left()->definition(); 1876 return left()->definition();
1912 } 1877 }
1913 break; 1878 break;
1914 1879
1915 case Token::kTRUNCDIV: 1880 case Token::kTRUNCDIV:
1916 if (rhs == 1) { 1881 if (rhs == 1) {
1917 return left()->definition(); 1882 return left()->definition();
1918 } else if (rhs == -1) { 1883 } else if (rhs == -1) {
1919 UnaryIntegerOpInstr* negation = 1884 UnaryIntegerOpInstr* negation = UnaryIntegerOpInstr::Make(
1920 UnaryIntegerOpInstr::Make(representation(), 1885 representation(), Token::kNEGATE, left()->CopyWithType(),
1921 Token::kNEGATE, 1886 GetDeoptId(), range());
1922 left()->CopyWithType(),
1923 GetDeoptId(),
1924 range());
1925 if (negation != NULL) { 1887 if (negation != NULL) {
1926 flow_graph->InsertBefore(this, negation, env(), FlowGraph::kValue); 1888 flow_graph->InsertBefore(this, negation, env(), FlowGraph::kValue);
1927 return negation; 1889 return negation;
1928 } 1890 }
1929 } 1891 }
1930 break; 1892 break;
1931 1893
1932 case Token::kSHR: 1894 case Token::kSHR:
1933 if (rhs == 0) { 1895 if (rhs == 0) {
1934 return left()->definition(); 1896 return left()->definition();
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
2088 value()->Type()->IsAssignableTo(dst_type())) { 2050 value()->Type()->IsAssignableTo(dst_type())) {
2089 return value()->definition(); 2051 return value()->definition();
2090 } 2052 }
2091 2053
2092 // For uninstantiated target types: If the instantiator type arguments 2054 // For uninstantiated target types: If the instantiator type arguments
2093 // are constant, instantiate the target type here. 2055 // are constant, instantiate the target type here.
2094 if (dst_type().IsInstantiated()) return this; 2056 if (dst_type().IsInstantiated()) return this;
2095 2057
2096 ConstantInstr* constant_type_args = 2058 ConstantInstr* constant_type_args =
2097 instantiator_type_arguments()->definition()->AsConstant(); 2059 instantiator_type_arguments()->definition()->AsConstant();
2098 if (constant_type_args != NULL && 2060 if (constant_type_args != NULL && !constant_type_args->value().IsNull() &&
2099 !constant_type_args->value().IsNull() &&
2100 constant_type_args->value().IsTypeArguments()) { 2061 constant_type_args->value().IsTypeArguments()) {
2101 const TypeArguments& instantiator_type_args = 2062 const TypeArguments& instantiator_type_args =
2102 TypeArguments::Cast(constant_type_args->value()); 2063 TypeArguments::Cast(constant_type_args->value());
2103 Error& bound_error = Error::Handle(); 2064 Error& bound_error = Error::Handle();
2104 AbstractType& new_dst_type = AbstractType::Handle( 2065 AbstractType& new_dst_type =
2105 dst_type().InstantiateFrom( 2066 AbstractType::Handle(dst_type().InstantiateFrom(
2106 instantiator_type_args, &bound_error, NULL, NULL, Heap::kOld)); 2067 instantiator_type_args, &bound_error, NULL, NULL, Heap::kOld));
2107 if (new_dst_type.IsMalformedOrMalbounded() || !bound_error.IsNull()) { 2068 if (new_dst_type.IsMalformedOrMalbounded() || !bound_error.IsNull()) {
2108 return this; 2069 return this;
2109 } 2070 }
2110 if (new_dst_type.IsTypeRef()) { 2071 if (new_dst_type.IsTypeRef()) {
2111 new_dst_type = TypeRef::Cast(new_dst_type).type(); 2072 new_dst_type = TypeRef::Cast(new_dst_type).type();
2112 } 2073 }
2113 new_dst_type = new_dst_type.Canonicalize(); 2074 new_dst_type = new_dst_type.Canonicalize();
2114 set_dst_type(new_dst_type); 2075 set_dst_type(new_dst_type);
2115 2076
2116 if (new_dst_type.IsDynamicType() || 2077 if (new_dst_type.IsDynamicType() || new_dst_type.IsObjectType() ||
2117 new_dst_type.IsObjectType() ||
2118 (FLAG_eliminate_type_checks && 2078 (FLAG_eliminate_type_checks &&
2119 value()->Type()->IsAssignableTo(new_dst_type))) { 2079 value()->Type()->IsAssignableTo(new_dst_type))) {
2120 return value()->definition(); 2080 return value()->definition();
2121 } 2081 }
2122 2082
2123 ConstantInstr* null_constant = flow_graph->constant_null(); 2083 ConstantInstr* null_constant = flow_graph->constant_null();
2124 instantiator_type_arguments()->BindTo(null_constant); 2084 instantiator_type_arguments()->BindTo(null_constant);
2125 } 2085 }
2126 return this; 2086 return this;
2127 } 2087 }
2128 2088
2129 2089
2130 Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) { 2090 Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) {
2131 return (Isolate::Current()->type_checks() || HasUses()) ? this : NULL; 2091 return (Isolate::Current()->type_checks() || HasUses()) ? this : NULL;
2132 } 2092 }
2133 2093
2134 2094
2135 LocationSummary* DebugStepCheckInstr::MakeLocationSummary(Zone* zone, 2095 LocationSummary* DebugStepCheckInstr::MakeLocationSummary(Zone* zone,
2136 bool opt) const { 2096 bool opt) const {
2137 const intptr_t kNumInputs = 0; 2097 const intptr_t kNumInputs = 0;
2138 const intptr_t kNumTemps = 0; 2098 const intptr_t kNumTemps = 0;
2139 LocationSummary* locs = new(zone) LocationSummary( 2099 LocationSummary* locs = new (zone)
2140 zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2100 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2141 return locs; 2101 return locs;
2142 } 2102 }
2143 2103
2144 2104
2145 Instruction* DebugStepCheckInstr::Canonicalize(FlowGraph* flow_graph) { 2105 Instruction* DebugStepCheckInstr::Canonicalize(FlowGraph* flow_graph) {
2146 return NULL; 2106 return NULL;
2147 } 2107 }
2148 2108
2149 2109
2150 static bool HasTryBlockUse(Value* use_list) { 2110 static bool HasTryBlockUse(Value* use_list) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2211 break; 2171 break;
2212 case kUnboxedUint32: 2172 case kUnboxedUint32:
2213 replacement = new BoxUint32Instr(conv->value()->CopyWithType()); 2173 replacement = new BoxUint32Instr(conv->value()->CopyWithType());
2214 break; 2174 break;
2215 default: 2175 default:
2216 UNREACHABLE(); 2176 UNREACHABLE();
2217 break; 2177 break;
2218 } 2178 }
2219 2179
2220 if (replacement != this) { 2180 if (replacement != this) {
2221 flow_graph->InsertBefore(this, 2181 flow_graph->InsertBefore(this, replacement, NULL, FlowGraph::kValue);
2222 replacement,
2223 NULL,
2224 FlowGraph::kValue);
2225 } 2182 }
2226 2183
2227 return replacement; 2184 return replacement;
2228 } 2185 }
2229 2186
2230 return this; 2187 return this;
2231 } 2188 }
2232 2189
2233 2190
2234 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) { 2191 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) {
2235 if (!HasUses() && !CanDeoptimize()) return NULL; 2192 if (!HasUses() && !CanDeoptimize()) return NULL;
2236 2193
2237 // Fold away Unbox<rep>(Box<rep>(v)). 2194 // Fold away Unbox<rep>(Box<rep>(v)).
2238 BoxInstr* box_defn = value()->definition()->AsBox(); 2195 BoxInstr* box_defn = value()->definition()->AsBox();
2239 if ((box_defn != NULL) && 2196 if ((box_defn != NULL) &&
2240 (box_defn->from_representation() == representation())) { 2197 (box_defn->from_representation() == representation())) {
2241 return box_defn->value()->definition(); 2198 return box_defn->value()->definition();
2242 } 2199 }
2243 2200
2244 if ((representation() == kUnboxedDouble) && value()->BindsToConstant()) { 2201 if ((representation() == kUnboxedDouble) && value()->BindsToConstant()) {
2245 UnboxedConstantInstr* uc = NULL; 2202 UnboxedConstantInstr* uc = NULL;
2246 2203
2247 const Object& val = value()->BoundConstant(); 2204 const Object& val = value()->BoundConstant();
2248 if (val.IsSmi()) { 2205 if (val.IsSmi()) {
2249 const Double& double_val = Double::ZoneHandle(flow_graph->zone(), 2206 const Double& double_val = Double::ZoneHandle(
2207 flow_graph->zone(),
2250 Double::NewCanonical(Smi::Cast(val).AsDoubleValue())); 2208 Double::NewCanonical(Smi::Cast(val).AsDoubleValue()));
2251 uc = new UnboxedConstantInstr(double_val, kUnboxedDouble); 2209 uc = new UnboxedConstantInstr(double_val, kUnboxedDouble);
2252 } else if (val.IsDouble()) { 2210 } else if (val.IsDouble()) {
2253 uc = new UnboxedConstantInstr(val, kUnboxedDouble); 2211 uc = new UnboxedConstantInstr(val, kUnboxedDouble);
2254 } 2212 }
2255 2213
2256 if (uc != NULL) { 2214 if (uc != NULL) {
2257 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); 2215 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
2258 return uc; 2216 return uc;
2259 } 2217 }
2260 } 2218 }
2261 2219
2262 return this; 2220 return this;
2263 } 2221 }
2264 2222
2265 2223
2266 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { 2224 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
2267 if (!HasUses() && !CanDeoptimize()) return NULL; 2225 if (!HasUses() && !CanDeoptimize()) return NULL;
2268 2226
2269 // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)). 2227 // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)).
2270 BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger(); 2228 BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger();
2271 if (box_defn != NULL) { 2229 if (box_defn != NULL) {
2272 Representation from_representation = 2230 Representation from_representation =
2273 box_defn->value()->definition()->representation(); 2231 box_defn->value()->definition()->representation();
2274 if (from_representation == representation()) { 2232 if (from_representation == representation()) {
2275 return box_defn->value()->definition(); 2233 return box_defn->value()->definition();
2276 } else { 2234 } else {
2277 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( 2235 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
2278 from_representation, 2236 from_representation, representation(),
2279 representation(),
2280 box_defn->value()->CopyWithType(), 2237 box_defn->value()->CopyWithType(),
2281 (representation() == kUnboxedInt32) ? 2238 (representation() == kUnboxedInt32) ? GetDeoptId()
2282 GetDeoptId() : Thread::kNoDeoptId); 2239 : Thread::kNoDeoptId);
2283 // TODO(vegorov): marking resulting converter as truncating when 2240 // TODO(vegorov): marking resulting converter as truncating when
2284 // unboxing can't deoptimize is a workaround for the missing 2241 // unboxing can't deoptimize is a workaround for the missing
2285 // deoptimization environment when we insert converter after 2242 // deoptimization environment when we insert converter after
2286 // EliminateEnvironments and there is a mismatch between predicates 2243 // EliminateEnvironments and there is a mismatch between predicates
2287 // UnboxIntConverterInstr::CanDeoptimize and UnboxInt32::CanDeoptimize. 2244 // UnboxIntConverterInstr::CanDeoptimize and UnboxInt32::CanDeoptimize.
2288 if ((representation() == kUnboxedInt32) && 2245 if ((representation() == kUnboxedInt32) &&
2289 (is_truncating() || !CanDeoptimize())) { 2246 (is_truncating() || !CanDeoptimize())) {
2290 converter->mark_truncating(); 2247 converter->mark_truncating();
2291 } 2248 }
2292 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); 2249 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
2293 return converter; 2250 return converter;
2294 } 2251 }
2295 } 2252 }
2296 2253
2297 return this; 2254 return this;
2298 } 2255 }
2299 2256
2300 2257
2301 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) { 2258 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
2302 Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph); 2259 Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph);
2303 if (replacement != this) { 2260 if (replacement != this) {
2304 return replacement; 2261 return replacement;
2305 } 2262 }
2306 2263
2307 ConstantInstr* c = value()->definition()->AsConstant(); 2264 ConstantInstr* c = value()->definition()->AsConstant();
2308 if ((c != NULL) && c->value().IsSmi()) { 2265 if ((c != NULL) && c->value().IsSmi()) {
2309 if (!is_truncating() && (kSmiBits > 32)) { 2266 if (!is_truncating() && (kSmiBits > 32)) {
2310 // Check that constant fits into 32-bit integer. 2267 // Check that constant fits into 32-bit integer.
2311 const int64_t value = 2268 const int64_t value = static_cast<int64_t>(Smi::Cast(c->value()).Value());
2312 static_cast<int64_t>(Smi::Cast(c->value()).Value());
2313 if (!Utils::IsInt(32, value)) { 2269 if (!Utils::IsInt(32, value)) {
2314 return this; 2270 return this;
2315 } 2271 }
2316 } 2272 }
2317 2273
2318 UnboxedConstantInstr* uc = 2274 UnboxedConstantInstr* uc =
2319 new UnboxedConstantInstr(c->value(), kUnboxedInt32); 2275 new UnboxedConstantInstr(c->value(), kUnboxedInt32);
2320 if (c->range() != NULL) { 2276 if (c->range() != NULL) {
2321 uc->set_range(*c->range()); 2277 uc->set_range(*c->range());
2322 } 2278 }
2323 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); 2279 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
2324 return uc; 2280 return uc;
2325 } 2281 }
2326 2282
2327 return this; 2283 return this;
2328 } 2284 }
2329 2285
2330 2286
2331 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { 2287 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
2332 if (!HasUses()) return NULL; 2288 if (!HasUses()) return NULL;
2333 2289
2334 UnboxedIntConverterInstr* box_defn = 2290 UnboxedIntConverterInstr* box_defn =
2335 value()->definition()->AsUnboxedIntConverter(); 2291 value()->definition()->AsUnboxedIntConverter();
2336 if ((box_defn != NULL) && (box_defn->representation() == from())) { 2292 if ((box_defn != NULL) && (box_defn->representation() == from())) {
2337 if (box_defn->from() == to()) { 2293 if (box_defn->from() == to()) {
2338 return box_defn->value()->definition(); 2294 return box_defn->value()->definition();
2339 } 2295 }
2340 2296
2341 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( 2297 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
2342 box_defn->from(), 2298 box_defn->from(), representation(), box_defn->value()->CopyWithType(),
2343 representation(),
2344 box_defn->value()->CopyWithType(),
2345 (to() == kUnboxedInt32) ? GetDeoptId() : Thread::kNoDeoptId); 2299 (to() == kUnboxedInt32) ? GetDeoptId() : Thread::kNoDeoptId);
2346 if ((representation() == kUnboxedInt32) && is_truncating()) { 2300 if ((representation() == kUnboxedInt32) && is_truncating()) {
2347 converter->mark_truncating(); 2301 converter->mark_truncating();
2348 } 2302 }
2349 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); 2303 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
2350 return converter; 2304 return converter;
2351 } 2305 }
2352 2306
2353 UnboxInt64Instr* unbox_defn = value()->definition()->AsUnboxInt64(); 2307 UnboxInt64Instr* unbox_defn = value()->definition()->AsUnboxInt64();
2354 if (unbox_defn != NULL && 2308 if (unbox_defn != NULL && (from() == kUnboxedMint) &&
2355 (from() == kUnboxedMint) && 2309 (to() == kUnboxedInt32) && unbox_defn->HasOnlyInputUse(value())) {
2356 (to() == kUnboxedInt32) &&
2357 unbox_defn->HasOnlyInputUse(value())) {
2358 // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter 2310 // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter
2359 // and code path that unboxes Mint into Int32. We should just schedule 2311 // and code path that unboxes Mint into Int32. We should just schedule
2360 // these instructions close to each other instead of fusing them. 2312 // these instructions close to each other instead of fusing them.
2361 Definition* replacement = 2313 Definition* replacement =
2362 new UnboxInt32Instr(is_truncating() ? UnboxInt32Instr::kTruncate 2314 new UnboxInt32Instr(is_truncating() ? UnboxInt32Instr::kTruncate
2363 : UnboxInt32Instr::kNoTruncation, 2315 : UnboxInt32Instr::kNoTruncation,
2364 unbox_defn->value()->CopyWithType(), 2316 unbox_defn->value()->CopyWithType(), GetDeoptId());
2365 GetDeoptId()); 2317 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
2366 flow_graph->InsertBefore(this,
2367 replacement,
2368 env(),
2369 FlowGraph::kValue);
2370 return replacement; 2318 return replacement;
2371 } 2319 }
2372 2320
2373 return this; 2321 return this;
2374 } 2322 }
2375 2323
2376 2324
2377 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { 2325 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) {
2378 Definition* defn = value()->definition(); 2326 Definition* defn = value()->definition();
2379 if (defn->IsComparison() && 2327 if (defn->IsComparison() && defn->HasOnlyUse(value()) &&
2380 defn->HasOnlyUse(value()) &&
2381 defn->Type()->ToCid() == kBoolCid) { 2328 defn->Type()->ToCid() == kBoolCid) {
2382 defn->AsComparison()->NegateComparison(); 2329 defn->AsComparison()->NegateComparison();
2383 return defn; 2330 return defn;
2384 } 2331 }
2385 return this; 2332 return this;
2386 } 2333 }
2387 2334
2388 2335
2389 static bool MayBeBoxableNumber(intptr_t cid) { 2336 static bool MayBeBoxableNumber(intptr_t cid) {
2390 return (cid == kDynamicCid) || 2337 return (cid == kDynamicCid) || (cid == kMintCid) || (cid == kBigintCid) ||
2391 (cid == kMintCid) ||
2392 (cid == kBigintCid) ||
2393 (cid == kDoubleCid); 2338 (cid == kDoubleCid);
2394 } 2339 }
2395 2340
2396 2341
2397 static bool MaybeNumber(CompileType* type) { 2342 static bool MaybeNumber(CompileType* type) {
2398 ASSERT(Type::Handle(Type::Number()).IsMoreSpecificThan( 2343 ASSERT(Type::Handle(Type::Number())
2399 Type::Handle(Type::Number()), NULL, NULL, Heap::kOld)); 2344 .IsMoreSpecificThan(Type::Handle(Type::Number()), NULL, NULL,
2400 return type->ToAbstractType()->IsDynamicType() 2345 Heap::kOld));
2401 || type->ToAbstractType()->IsObjectType() 2346 return type->ToAbstractType()->IsDynamicType() ||
2402 || type->ToAbstractType()->IsTypeParameter() 2347 type->ToAbstractType()->IsObjectType() ||
2403 || type->IsMoreSpecificThan(Type::Handle(Type::Number())); 2348 type->ToAbstractType()->IsTypeParameter() ||
2349 type->IsMoreSpecificThan(Type::Handle(Type::Number()));
2404 } 2350 }
2405 2351
2406 2352
2407 // Returns a replacement for a strict comparison and signals if the result has 2353 // Returns a replacement for a strict comparison and signals if the result has
2408 // to be negated. 2354 // to be negated.
2409 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare, 2355 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare,
2410 bool* negated, 2356 bool* negated,
2411 bool is_branch) { 2357 bool is_branch) {
2412 // Use propagated cid and type information to eliminate number checks. 2358 // Use propagated cid and type information to eliminate number checks.
2413 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or 2359 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or
2414 // is not a subtype of num, no need for number checks. 2360 // is not a subtype of num, no need for number checks.
2415 if (compare->needs_number_check()) { 2361 if (compare->needs_number_check()) {
2416 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) || 2362 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) ||
2417 !MayBeBoxableNumber(compare->right()->Type()->ToCid())) { 2363 !MayBeBoxableNumber(compare->right()->Type()->ToCid())) {
2418 compare->set_needs_number_check(false); 2364 compare->set_needs_number_check(false);
2419 } else if (!MaybeNumber(compare->left()->Type()) || 2365 } else if (!MaybeNumber(compare->left()->Type()) ||
2420 !MaybeNumber(compare->right()->Type())) { 2366 !MaybeNumber(compare->right()->Type())) {
2421 compare->set_needs_number_check(false); 2367 compare->set_needs_number_check(false);
2422 } 2368 }
2423 } 2369 }
2424 *negated = false; 2370 *negated = false;
2425 PassiveObject& constant = PassiveObject::Handle(); 2371 PassiveObject& constant = PassiveObject::Handle();
2426 Value* other = NULL; 2372 Value* other = NULL;
2427 if (compare->right()->BindsToConstant()) { 2373 if (compare->right()->BindsToConstant()) {
2428 constant = compare->right()->BoundConstant().raw(); 2374 constant = compare->right()->BoundConstant().raw();
2429 other = compare->left(); 2375 other = compare->left();
2430 } else if (compare->left()->BindsToConstant()) { 2376 } else if (compare->left()->BindsToConstant()) {
2431 constant = compare->left()->BoundConstant().raw(); 2377 constant = compare->left()->BoundConstant().raw();
2432 other = compare->right(); 2378 other = compare->right();
2433 } else { 2379 } else {
2434 return compare; 2380 return compare;
2435 } 2381 }
2436 2382
2437 const bool can_merge = is_branch || (other->Type()->ToCid() == kBoolCid); 2383 const bool can_merge = is_branch || (other->Type()->ToCid() == kBoolCid);
2438 Definition* other_defn = other->definition(); 2384 Definition* other_defn = other->definition();
2439 Token::Kind kind = compare->kind(); 2385 Token::Kind kind = compare->kind();
2440 // Handle e === true. 2386 // Handle e === true.
2441 if ((kind == Token::kEQ_STRICT) && 2387 if ((kind == Token::kEQ_STRICT) && (constant.raw() == Bool::True().raw()) &&
2442 (constant.raw() == Bool::True().raw()) &&
2443 can_merge) { 2388 can_merge) {
2444 return other_defn; 2389 return other_defn;
2445 } 2390 }
2446 // Handle e !== false. 2391 // Handle e !== false.
2447 if ((kind == Token::kNE_STRICT) && 2392 if ((kind == Token::kNE_STRICT) && (constant.raw() == Bool::False().raw()) &&
2448 (constant.raw() == Bool::False().raw()) &&
2449 can_merge) { 2393 can_merge) {
2450 return other_defn; 2394 return other_defn;
2451 } 2395 }
2452 // Handle e !== true. 2396 // Handle e !== true.
2453 if ((kind == Token::kNE_STRICT) && 2397 if ((kind == Token::kNE_STRICT) && (constant.raw() == Bool::True().raw()) &&
2454 (constant.raw() == Bool::True().raw()) && 2398 other_defn->IsComparison() && can_merge &&
2455 other_defn->IsComparison() &&
2456 can_merge &&
2457 other_defn->HasOnlyUse(other)) { 2399 other_defn->HasOnlyUse(other)) {
2458 *negated = true; 2400 *negated = true;
2459 return other_defn; 2401 return other_defn;
2460 } 2402 }
2461 // Handle e === false. 2403 // Handle e === false.
2462 if ((kind == Token::kEQ_STRICT) && 2404 if ((kind == Token::kEQ_STRICT) && (constant.raw() == Bool::False().raw()) &&
2463 (constant.raw() == Bool::False().raw()) && 2405 other_defn->IsComparison() && can_merge &&
2464 other_defn->IsComparison() &&
2465 can_merge &&
2466 other_defn->HasOnlyUse(other)) { 2406 other_defn->HasOnlyUse(other)) {
2467 *negated = true; 2407 *negated = true;
2468 return other_defn; 2408 return other_defn;
2469 } 2409 }
2470 return compare; 2410 return compare;
2471 } 2411 }
2472 2412
2473 2413
2474 static bool BindsToGivenConstant(Value* v, intptr_t expected) { 2414 static bool BindsToGivenConstant(Value* v, intptr_t expected) {
2475 return v->BindsToConstant() && 2415 return v->BindsToConstant() && v->BoundConstant().IsSmi() &&
2476 v->BoundConstant().IsSmi() && 2416 (Smi::Cast(v->BoundConstant()).Value() == expected);
2477 (Smi::Cast(v->BoundConstant()).Value() == expected);
2478 } 2417 }
2479 2418
2480 2419
2481 // Recognize patterns (a & b) == 0 and (a & 2^n) != 2^n. 2420 // Recognize patterns (a & b) == 0 and (a & 2^n) != 2^n.
2482 static bool RecognizeTestPattern(Value* left, Value* right, bool* negate) { 2421 static bool RecognizeTestPattern(Value* left, Value* right, bool* negate) {
2483 if (!right->BindsToConstant() || !right->BoundConstant().IsSmi()) { 2422 if (!right->BindsToConstant() || !right->BoundConstant().IsSmi()) {
2484 return false; 2423 return false;
2485 } 2424 }
2486 2425
2487 const intptr_t value = Smi::Cast(right->BoundConstant()).Value(); 2426 const intptr_t value = Smi::Cast(right->BoundConstant()).Value();
2488 if ((value != 0) && !Utils::IsPowerOfTwo(value)) { 2427 if ((value != 0) && !Utils::IsPowerOfTwo(value)) {
2489 return false; 2428 return false;
2490 } 2429 }
2491 2430
2492 2431
2493 BinarySmiOpInstr* mask_op = left->definition()->AsBinarySmiOp(); 2432 BinarySmiOpInstr* mask_op = left->definition()->AsBinarySmiOp();
2494 if ((mask_op == NULL) || 2433 if ((mask_op == NULL) || (mask_op->op_kind() != Token::kBIT_AND) ||
2495 (mask_op->op_kind() != Token::kBIT_AND) ||
2496 !mask_op->HasOnlyUse(left)) { 2434 !mask_op->HasOnlyUse(left)) {
2497 return false; 2435 return false;
2498 } 2436 }
2499 2437
2500 if (value == 0) { 2438 if (value == 0) {
2501 // Recognized (a & b) == 0 pattern. 2439 // Recognized (a & b) == 0 pattern.
2502 *negate = false; 2440 *negate = false;
2503 return true; 2441 return true;
2504 } 2442 }
2505 2443
2506 // Recognize 2444 // Recognize
2507 if (BindsToGivenConstant(mask_op->left(), value) || 2445 if (BindsToGivenConstant(mask_op->left(), value) ||
2508 BindsToGivenConstant(mask_op->right(), value)) { 2446 BindsToGivenConstant(mask_op->right(), value)) {
2509 // Recognized (a & 2^n) == 2^n pattern. It's equivalent to (a & 2^n) != 0 2447 // Recognized (a & 2^n) == 2^n pattern. It's equivalent to (a & 2^n) != 0
2510 // so we need to negate original comparison. 2448 // so we need to negate original comparison.
2511 *negate = true; 2449 *negate = true;
2512 return true; 2450 return true;
2513 } 2451 }
2514 2452
2515 return false; 2453 return false;
2516 } 2454 }
2517 2455
2518 2456
2519 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { 2457 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) {
2520 Zone* zone = flow_graph->zone(); 2458 Zone* zone = flow_graph->zone();
2521 // Only handle strict-compares. 2459 // Only handle strict-compares.
2522 if (comparison()->IsStrictCompare()) { 2460 if (comparison()->IsStrictCompare()) {
2523 bool negated = false; 2461 bool negated = false;
2524 Definition* replacement = 2462 Definition* replacement = CanonicalizeStrictCompare(
2525 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), 2463 comparison()->AsStrictCompare(), &negated, /* is_branch = */ true);
2526 &negated, /* is_branch = */ true);
2527 if (replacement == comparison()) { 2464 if (replacement == comparison()) {
2528 return this; 2465 return this;
2529 } 2466 }
2530 ComparisonInstr* comp = replacement->AsComparison(); 2467 ComparisonInstr* comp = replacement->AsComparison();
2531 if ((comp == NULL) || 2468 if ((comp == NULL) || comp->CanDeoptimize() ||
2532 comp->CanDeoptimize() ||
2533 comp->HasUnmatchedInputRepresentations()) { 2469 comp->HasUnmatchedInputRepresentations()) {
2534 return this; 2470 return this;
2535 } 2471 }
2536 2472
2537 // Replace the comparison if the replacement is used at this branch, 2473 // Replace the comparison if the replacement is used at this branch,
2538 // and has exactly one use. 2474 // and has exactly one use.
2539 Value* use = comp->input_use_list(); 2475 Value* use = comp->input_use_list();
2540 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { 2476 if ((use->instruction() == this) && comp->HasOnlyUse(use)) {
2541 if (negated) { 2477 if (negated) {
2542 comp->NegateComparison(); 2478 comp->NegateComparison();
(...skipping 12 matching lines...) Expand all
2555 // Clear the comparison's temp index and ssa temp index since the 2491 // Clear the comparison's temp index and ssa temp index since the
2556 // value of the comparison is not used outside the branch anymore. 2492 // value of the comparison is not used outside the branch anymore.
2557 ASSERT(comp->input_use_list() == NULL); 2493 ASSERT(comp->input_use_list() == NULL);
2558 comp->ClearSSATempIndex(); 2494 comp->ClearSSATempIndex();
2559 comp->ClearTempIndex(); 2495 comp->ClearTempIndex();
2560 } 2496 }
2561 } else if (comparison()->IsEqualityCompare() && 2497 } else if (comparison()->IsEqualityCompare() &&
2562 comparison()->operation_cid() == kSmiCid) { 2498 comparison()->operation_cid() == kSmiCid) {
2563 BinarySmiOpInstr* bit_and = NULL; 2499 BinarySmiOpInstr* bit_and = NULL;
2564 bool negate = false; 2500 bool negate = false;
2565 if (RecognizeTestPattern(comparison()->left(), 2501 if (RecognizeTestPattern(comparison()->left(), comparison()->right(),
2566 comparison()->right(),
2567 &negate)) { 2502 &negate)) {
2568 bit_and = comparison()->left()->definition()->AsBinarySmiOp(); 2503 bit_and = comparison()->left()->definition()->AsBinarySmiOp();
2569 } else if (RecognizeTestPattern(comparison()->right(), 2504 } else if (RecognizeTestPattern(comparison()->right(), comparison()->left(),
2570 comparison()->left(),
2571 &negate)) { 2505 &negate)) {
2572 bit_and = comparison()->right()->definition()->AsBinarySmiOp(); 2506 bit_and = comparison()->right()->definition()->AsBinarySmiOp();
2573 } 2507 }
2574 if (bit_and != NULL) { 2508 if (bit_and != NULL) {
2575 if (FLAG_trace_optimization) { 2509 if (FLAG_trace_optimization) {
2576 OS::Print("Merging test smi v%" Pd "\n", bit_and->ssa_temp_index()); 2510 OS::Print("Merging test smi v%" Pd "\n", bit_and->ssa_temp_index());
2577 } 2511 }
2578 TestSmiInstr* test = new TestSmiInstr( 2512 TestSmiInstr* test = new TestSmiInstr(
2579 comparison()->token_pos(), 2513 comparison()->token_pos(),
2580 negate ? Token::NegateComparison(comparison()->kind()) 2514 negate ? Token::NegateComparison(comparison()->kind())
2581 : comparison()->kind(), 2515 : comparison()->kind(),
2582 bit_and->left()->Copy(zone), 2516 bit_and->left()->Copy(zone), bit_and->right()->Copy(zone));
2583 bit_and->right()->Copy(zone));
2584 ASSERT(!CanDeoptimize()); 2517 ASSERT(!CanDeoptimize());
2585 RemoveEnvironment(); 2518 RemoveEnvironment();
2586 flow_graph->CopyDeoptTarget(this, bit_and); 2519 flow_graph->CopyDeoptTarget(this, bit_and);
2587 SetComparison(test); 2520 SetComparison(test);
2588 bit_and->RemoveFromGraph(); 2521 bit_and->RemoveFromGraph();
2589 } 2522 }
2590 } 2523 }
2591 return this; 2524 return this;
2592 } 2525 }
2593 2526
(...skipping 17 matching lines...) Expand all
2611 return this; 2544 return this;
2612 } 2545 }
2613 2546
2614 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this; 2547 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this;
2615 } 2548 }
2616 2549
2617 2550
2618 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) { 2551 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) {
2619 if (value()->BindsToConstant()) { 2552 if (value()->BindsToConstant()) {
2620 const Object& constant_value = value()->BoundConstant(); 2553 const Object& constant_value = value()->BoundConstant();
2621 if (constant_value.IsSmi() && 2554 if (constant_value.IsSmi() && Smi::Cast(constant_value).Value() == cid_) {
2622 Smi::Cast(constant_value).Value() == cid_) {
2623 return NULL; 2555 return NULL;
2624 } 2556 }
2625 } 2557 }
2626 return this; 2558 return this;
2627 } 2559 }
2628 2560
2629 2561
2630 Definition* TestCidsInstr::Canonicalize(FlowGraph* flow_graph) { 2562 Definition* TestCidsInstr::Canonicalize(FlowGraph* flow_graph) {
2631 CompileType* in_type = left()->Type(); 2563 CompileType* in_type = left()->Type();
2632 intptr_t cid = in_type->ToCid(); 2564 intptr_t cid = in_type->ToCid();
2633 if (cid == kDynamicCid) return this; 2565 if (cid == kDynamicCid) return this;
2634 2566
2635 const ZoneGrowableArray<intptr_t>& data = cid_results(); 2567 const ZoneGrowableArray<intptr_t>& data = cid_results();
2636 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; 2568 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
2637 for (intptr_t i = 0; i < data.length(); i += 2) { 2569 for (intptr_t i = 0; i < data.length(); i += 2) {
2638 if (data[i] == cid) { 2570 if (data[i] == cid) {
2639 return (data[i + 1] == true_result) 2571 return (data[i + 1] == true_result)
2640 ? flow_graph->GetConstant(Bool::True()) 2572 ? flow_graph->GetConstant(Bool::True())
2641 : flow_graph->GetConstant(Bool::False()); 2573 : flow_graph->GetConstant(Bool::False());
2642 } 2574 }
2643 } 2575 }
2644 2576
2645 // TODO(sra): Handle misses if the instruction is not deoptimizing. 2577 // TODO(sra): Handle misses if the instruction is not deoptimizing.
2646 // TODO(sra): Handle nullable input, possibly canonicalizing to a compare 2578 // TODO(sra): Handle nullable input, possibly canonicalizing to a compare
2647 // against `null`. 2579 // against `null`.
2648 return this; 2580 return this;
2649 } 2581 }
2650 2582
2651 2583
(...skipping 30 matching lines...) Expand all
2682 StaticCallInstr* call = value()->definition()->AsStaticCall(); 2614 StaticCallInstr* call = value()->definition()->AsStaticCall();
2683 if (call == NULL) { 2615 if (call == NULL) {
2684 return this; 2616 return this;
2685 } 2617 }
2686 2618
2687 ConstantInstr* length = NULL; 2619 ConstantInstr* length = NULL;
2688 if (call->is_known_list_constructor() && 2620 if (call->is_known_list_constructor() &&
2689 LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) { 2621 LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
2690 length = call->ArgumentAt(1)->AsConstant(); 2622 length = call->ArgumentAt(1)->AsConstant();
2691 } 2623 }
2692 if ((length != NULL) && 2624 if ((length != NULL) && length->value().IsSmi() &&
2693 length->value().IsSmi() &&
2694 Smi::Cast(length->value()).Value() == expected_length) { 2625 Smi::Cast(length->value()).Value() == expected_length) {
2695 return NULL; // Expected length matched. 2626 return NULL; // Expected length matched.
2696 } 2627 }
2697 2628
2698 return this; 2629 return this;
2699 } 2630 }
2700 2631
2701 2632
2702 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) { 2633 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) {
2703 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this; 2634 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this;
2704 } 2635 }
2705 2636
2706 2637
2707 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) { 2638 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) {
2708 if ((left()->Type()->ToCid() == kDoubleCid) || 2639 if ((left()->Type()->ToCid() == kDoubleCid) ||
2709 (right()->Type()->ToCid() == kDoubleCid)) { 2640 (right()->Type()->ToCid() == kDoubleCid)) {
2710 return NULL; // Remove from the graph. 2641 return NULL; // Remove from the graph.
2711 } 2642 }
2712 return this; 2643 return this;
2713 } 2644 }
(...skipping 21 matching lines...) Expand all
2735 return NULL; 2666 return NULL;
2736 } 2667 }
2737 } 2668 }
2738 2669
2739 2670
2740 UnboxInstr* UnboxInstr::Create(Representation to, 2671 UnboxInstr* UnboxInstr::Create(Representation to,
2741 Value* value, 2672 Value* value,
2742 intptr_t deopt_id) { 2673 intptr_t deopt_id) {
2743 switch (to) { 2674 switch (to) {
2744 case kUnboxedInt32: 2675 case kUnboxedInt32:
2745 return new UnboxInt32Instr( 2676 return new UnboxInt32Instr(UnboxInt32Instr::kNoTruncation, value,
2746 UnboxInt32Instr::kNoTruncation, value, deopt_id); 2677 deopt_id);
2747 2678
2748 case kUnboxedUint32: 2679 case kUnboxedUint32:
2749 return new UnboxUint32Instr(value, deopt_id); 2680 return new UnboxUint32Instr(value, deopt_id);
2750 2681
2751 case kUnboxedMint: 2682 case kUnboxedMint:
2752 return new UnboxInt64Instr(value, deopt_id); 2683 return new UnboxInt64Instr(value, deopt_id);
2753 2684
2754 case kUnboxedDouble: 2685 case kUnboxedDouble:
2755 case kUnboxedFloat32x4: 2686 case kUnboxedFloat32x4:
2756 case kUnboxedFloat64x2: 2687 case kUnboxedFloat64x2:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2799 LocationSummary* JoinEntryInstr::MakeLocationSummary(Zone* zone, 2730 LocationSummary* JoinEntryInstr::MakeLocationSummary(Zone* zone,
2800 bool optimizing) const { 2731 bool optimizing) const {
2801 UNREACHABLE(); 2732 UNREACHABLE();
2802 return NULL; 2733 return NULL;
2803 } 2734 }
2804 2735
2805 2736
2806 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2737 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2807 __ Bind(compiler->GetJumpLabel(this)); 2738 __ Bind(compiler->GetJumpLabel(this));
2808 if (!compiler->is_optimizing()) { 2739 if (!compiler->is_optimizing()) {
2809 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, 2740 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
2810 GetDeoptId(),
2811 TokenPosition::kNoSource); 2741 TokenPosition::kNoSource);
2812 } 2742 }
2813 if (HasParallelMove()) { 2743 if (HasParallelMove()) {
2814 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 2744 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
2815 } 2745 }
2816 } 2746 }
2817 2747
2818 2748
2819 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone, 2749 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone,
2820 bool optimizing) const { 2750 bool optimizing) const {
2821 UNREACHABLE(); 2751 UNREACHABLE();
2822 return NULL; 2752 return NULL;
2823 } 2753 }
2824 2754
2825 2755
2826 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2756 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2827 __ Bind(compiler->GetJumpLabel(this)); 2757 __ Bind(compiler->GetJumpLabel(this));
2828 if (!compiler->is_optimizing()) { 2758 if (!compiler->is_optimizing()) {
2829 #if !defined(TARGET_ARCH_DBC) 2759 #if !defined(TARGET_ARCH_DBC)
2830 // TODO(vegorov) re-enable edge counters on DBC if we consider them 2760 // TODO(vegorov) re-enable edge counters on DBC if we consider them
2831 // beneficial for the quality of the optimized bytecode. 2761 // beneficial for the quality of the optimized bytecode.
2832 if (compiler->NeedsEdgeCounter(this)) { 2762 if (compiler->NeedsEdgeCounter(this)) {
2833 compiler->EmitEdgeCounter(preorder_number()); 2763 compiler->EmitEdgeCounter(preorder_number());
2834 } 2764 }
2835 #endif 2765 #endif
2836 2766
2837 // The deoptimization descriptor points after the edge counter code for 2767 // The deoptimization descriptor points after the edge counter code for
2838 // uniformity with ARM and MIPS, where we can reuse pattern matching 2768 // uniformity with ARM and MIPS, where we can reuse pattern matching
2839 // code that matches backwards from the end of the pattern. 2769 // code that matches backwards from the end of the pattern.
2840 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, 2770 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
2841 GetDeoptId(),
2842 TokenPosition::kNoSource); 2771 TokenPosition::kNoSource);
2843 } 2772 }
2844 if (HasParallelMove()) { 2773 if (HasParallelMove()) {
2845 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 2774 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
2846 } 2775 }
2847 } 2776 }
2848 2777
2849 2778
2850 void IndirectGotoInstr::ComputeOffsetTable() { 2779 void IndirectGotoInstr::ComputeOffsetTable() {
2851 if (GetBlock()->offset() < 0) { 2780 if (GetBlock()->offset() < 0) {
(...skipping 23 matching lines...) Expand all
2875 offset = ientry->offset(); 2804 offset = ientry->offset();
2876 } 2805 }
2877 2806
2878 ASSERT(offset > 0); 2807 ASSERT(offset > 0);
2879 offsets_.SetInt32(i * element_size, offset); 2808 offsets_.SetInt32(i * element_size, offset);
2880 } 2809 }
2881 } 2810 }
2882 2811
2883 2812
2884 LocationSummary* IndirectEntryInstr::MakeLocationSummary( 2813 LocationSummary* IndirectEntryInstr::MakeLocationSummary(
2885 Zone* zone, bool optimizing) const { 2814 Zone* zone,
2815 bool optimizing) const {
2886 return JoinEntryInstr::MakeLocationSummary(zone, optimizing); 2816 return JoinEntryInstr::MakeLocationSummary(zone, optimizing);
2887 } 2817 }
2888 2818
2889 2819
2890 void IndirectEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2820 void IndirectEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2891 JoinEntryInstr::EmitNativeCode(compiler); 2821 JoinEntryInstr::EmitNativeCode(compiler);
2892 } 2822 }
2893 2823
2894 2824
2895 LocationSummary* PhiInstr::MakeLocationSummary(Zone* zone, 2825 LocationSummary* PhiInstr::MakeLocationSummary(Zone* zone,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2955 return NULL; 2885 return NULL;
2956 } 2886 }
2957 2887
2958 2888
2959 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2889 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2960 UNREACHABLE(); 2890 UNREACHABLE();
2961 } 2891 }
2962 2892
2963 2893
2964 LocationSummary* MaterializeObjectInstr::MakeLocationSummary( 2894 LocationSummary* MaterializeObjectInstr::MakeLocationSummary(
2965 Zone* zone, bool optimizing) const { 2895 Zone* zone,
2896 bool optimizing) const {
2966 UNREACHABLE(); 2897 UNREACHABLE();
2967 return NULL; 2898 return NULL;
2968 } 2899 }
2969 2900
2970 2901
2971 void MaterializeObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2902 void MaterializeObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2972 UNREACHABLE(); 2903 UNREACHABLE();
2973 } 2904 }
2974 2905
2975 2906
(...skipping 23 matching lines...) Expand all
2999 2930
3000 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2931 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3001 // Only appears in initial definitions, never in normal code. 2932 // Only appears in initial definitions, never in normal code.
3002 UNREACHABLE(); 2933 UNREACHABLE();
3003 } 2934 }
3004 2935
3005 2936
3006 LocationSummary* DropTempsInstr::MakeLocationSummary(Zone* zone, 2937 LocationSummary* DropTempsInstr::MakeLocationSummary(Zone* zone,
3007 bool optimizing) const { 2938 bool optimizing) const {
3008 return (InputCount() == 1) 2939 return (InputCount() == 1)
3009 ? LocationSummary::Make(zone, 2940 ? LocationSummary::Make(zone, 1, Location::SameAsFirstInput(),
3010 1, 2941 LocationSummary::kNoCall)
3011 Location::SameAsFirstInput(), 2942 : LocationSummary::Make(zone, 0, Location::NoLocation(),
3012 LocationSummary::kNoCall) 2943 LocationSummary::kNoCall);
3013 : LocationSummary::Make(zone,
3014 0,
3015 Location::NoLocation(),
3016 LocationSummary::kNoCall);
3017 } 2944 }
3018 2945
3019 2946
3020 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2947 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3021 #if defined(TARGET_ARCH_DBC) 2948 #if defined(TARGET_ARCH_DBC)
3022 // On DBC the action of poping the TOS value and then pushing it 2949 // On DBC the action of poping the TOS value and then pushing it
3023 // after all intermediates are poped is folded into a special 2950 // after all intermediates are poped is folded into a special
3024 // bytecode (DropR). On other architectures this is handled by 2951 // bytecode (DropR). On other architectures this is handled by
3025 // instruction prologue/epilogues. 2952 // instruction prologue/epilogues.
3026 ASSERT(!compiler->is_optimizing()); 2953 ASSERT(!compiler->is_optimizing());
3027 if ((InputCount() != 0) && HasTemp()) { 2954 if ((InputCount() != 0) && HasTemp()) {
3028 __ DropR(num_temps()); 2955 __ DropR(num_temps());
3029 } else { 2956 } else {
3030 __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0)); 2957 __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0));
3031 } 2958 }
3032 #else 2959 #else
3033 ASSERT(!compiler->is_optimizing()); 2960 ASSERT(!compiler->is_optimizing());
3034 // Assert that register assignment is correct. 2961 // Assert that register assignment is correct.
3035 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg())); 2962 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg()));
3036 __ Drop(num_temps()); 2963 __ Drop(num_temps());
3037 #endif // defined(TARGET_ARCH_DBC) 2964 #endif // defined(TARGET_ARCH_DBC)
3038 } 2965 }
3039 2966
3040 2967
3041 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos, 2968 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos,
3042 Token::Kind kind, 2969 Token::Kind kind,
3043 Value* left, 2970 Value* left,
3044 Value* right, 2971 Value* right,
3045 bool needs_number_check) 2972 bool needs_number_check)
3046 : TemplateComparison(token_pos, 2973 : TemplateComparison(token_pos, kind, Thread::Current()->GetNextDeoptId()),
3047 kind,
3048 Thread::Current()->GetNextDeoptId()),
3049 needs_number_check_(needs_number_check) { 2974 needs_number_check_(needs_number_check) {
3050 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); 2975 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
3051 SetInputAt(0, left); 2976 SetInputAt(0, left);
3052 SetInputAt(1, right); 2977 SetInputAt(1, right);
3053 } 2978 }
3054 2979
3055 2980
3056 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone, 2981 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone,
3057 bool optimizing) const { 2982 bool optimizing) const {
3058 return MakeCallSummary(zone); 2983 return MakeCallSummary(zone);
3059 } 2984 }
3060 2985
3061 2986
3062 // DBC does not use specialized inline cache stubs for smi operations. 2987 // DBC does not use specialized inline cache stubs for smi operations.
3063 #if !defined(TARGET_ARCH_DBC) 2988 #if !defined(TARGET_ARCH_DBC)
3064 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { 2989 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
3065 if (!FLAG_two_args_smi_icd) { 2990 if (!FLAG_two_args_smi_icd) {
3066 return 0; 2991 return 0;
3067 } 2992 }
3068 switch (kind) { 2993 switch (kind) {
3069 case Token::kADD: return StubCode::SmiAddInlineCache_entry(); 2994 case Token::kADD:
3070 case Token::kSUB: return StubCode::SmiSubInlineCache_entry(); 2995 return StubCode::SmiAddInlineCache_entry();
3071 case Token::kEQ: return StubCode::SmiEqualInlineCache_entry(); 2996 case Token::kSUB:
3072 default: return NULL; 2997 return StubCode::SmiSubInlineCache_entry();
2998 case Token::kEQ:
2999 return StubCode::SmiEqualInlineCache_entry();
3000 default:
3001 return NULL;
3073 } 3002 }
3074 } 3003 }
3075 #else 3004 #else
3076 static void TryFastPathSmiOp( 3005 static void TryFastPathSmiOp(FlowGraphCompiler* compiler,
3077 FlowGraphCompiler* compiler, ICData* call_ic_data, const String& name) { 3006 ICData* call_ic_data,
3007 const String& name) {
3078 if (!FLAG_two_args_smi_icd) { 3008 if (!FLAG_two_args_smi_icd) {
3079 return; 3009 return;
3080 } 3010 }
3081 if (name.raw() == Symbols::Plus().raw()) { 3011 if (name.raw() == Symbols::Plus().raw()) {
3082 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3012 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3083 __ AddTOS(); 3013 __ AddTOS();
3084 } 3014 }
3085 } else if (name.raw() == Symbols::Minus().raw()) { 3015 } else if (name.raw() == Symbols::Minus().raw()) {
3086 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3016 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3087 __ SubTOS(); 3017 __ SubTOS();
3088 } 3018 }
3089 } else if (name.raw() == Symbols::EqualOperator().raw()) { 3019 } else if (name.raw() == Symbols::EqualOperator().raw()) {
3090 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3020 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3091 __ EqualTOS(); 3021 __ EqualTOS();
3092 } 3022 }
3093 } else if (name.raw() == Symbols::LAngleBracket().raw()) { 3023 } else if (name.raw() == Symbols::LAngleBracket().raw()) {
3094 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3024 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3095 __ LessThanTOS(); 3025 __ LessThanTOS();
3096 } 3026 }
3097 } else if (name.raw() == Symbols::RAngleBracket().raw()) { 3027 } else if (name.raw() == Symbols::RAngleBracket().raw()) {
3098 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3028 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3099 __ GreaterThanTOS(); 3029 __ GreaterThanTOS();
3100 } 3030 }
3101 } else if (name.raw() == Symbols::BitAnd().raw()) { 3031 } else if (name.raw() == Symbols::BitAnd().raw()) {
3102 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3032 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3103 __ BitAndTOS(); 3033 __ BitAndTOS();
3104 } 3034 }
3105 } else if (name.raw() == Symbols::BitOr().raw()) { 3035 } else if (name.raw() == Symbols::BitOr().raw()) {
3106 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3036 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3107 __ BitOrTOS(); 3037 __ BitOrTOS();
3108 } 3038 }
3109 } else if (name.raw() == Symbols::Star().raw()) { 3039 } else if (name.raw() == Symbols::Star().raw()) {
3110 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3040 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3111 __ MulTOS(); 3041 __ MulTOS();
3112 } 3042 }
3113 } 3043 }
3114 } 3044 }
3115 #endif 3045 #endif
3116 3046
3117 3047
3118 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3048 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3119 Zone* zone = compiler->zone(); 3049 Zone* zone = compiler->zone();
3120 const ICData* call_ic_data = NULL; 3050 const ICData* call_ic_data = NULL;
3121 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || 3051 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
3122 (ic_data() == NULL)) { 3052 (ic_data() == NULL)) {
3123 const Array& arguments_descriptor = 3053 const Array& arguments_descriptor = Array::Handle(
3124 Array::Handle(zone, ArgumentsDescriptor::New(ArgumentCount(), 3054 zone, ArgumentsDescriptor::New(ArgumentCount(), argument_names()));
3125 argument_names()));
3126 call_ic_data = compiler->GetOrAddInstanceCallICData( 3055 call_ic_data = compiler->GetOrAddInstanceCallICData(
3127 deopt_id(), function_name(), arguments_descriptor, 3056 deopt_id(), function_name(), arguments_descriptor,
3128 checked_argument_count()); 3057 checked_argument_count());
3129 } else { 3058 } else {
3130 call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw()); 3059 call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw());
3131 } 3060 }
3132 3061
3133 #if !defined(TARGET_ARCH_DBC) 3062 #if !defined(TARGET_ARCH_DBC)
3134 if (compiler->is_optimizing() && HasICData()) { 3063 if (compiler->is_optimizing() && HasICData()) {
3135 ASSERT(HasICData()); 3064 ASSERT(HasICData());
3136 if (ic_data()->NumberOfUsedChecks() > 0) { 3065 if (ic_data()->NumberOfUsedChecks() > 0) {
3137 const ICData& unary_ic_data = 3066 const ICData& unary_ic_data =
3138 ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks()); 3067 ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks());
3139 compiler->GenerateInstanceCall(deopt_id(), 3068 compiler->GenerateInstanceCall(deopt_id(), token_pos(), ArgumentCount(),
3140 token_pos(), 3069 locs(), unary_ic_data);
3141 ArgumentCount(),
3142 locs(),
3143 unary_ic_data);
3144 } else { 3070 } else {
3145 // Call was not visited yet, use original ICData in order to populate it. 3071 // Call was not visited yet, use original ICData in order to populate it.
3146 compiler->GenerateInstanceCall(deopt_id(), 3072 compiler->GenerateInstanceCall(deopt_id(), token_pos(), ArgumentCount(),
3147 token_pos(), 3073 locs(), *call_ic_data);
3148 ArgumentCount(),
3149 locs(),
3150 *call_ic_data);
3151 } 3074 }
3152 } else { 3075 } else {
3153 // Unoptimized code. 3076 // Unoptimized code.
3154 ASSERT(!HasICData()); 3077 ASSERT(!HasICData());
3155 bool is_smi_two_args_op = false; 3078 bool is_smi_two_args_op = false;
3156 const StubEntry* stub_entry = TwoArgsSmiOpInlineCacheEntry(token_kind()); 3079 const StubEntry* stub_entry = TwoArgsSmiOpInlineCacheEntry(token_kind());
3157 if (stub_entry != NULL) { 3080 if (stub_entry != NULL) {
3158 // We have a dedicated inline cache stub for this operation, add an 3081 // We have a dedicated inline cache stub for this operation, add an
3159 // an initial Smi/Smi check with count 0. 3082 // an initial Smi/Smi check with count 0.
3160 is_smi_two_args_op = call_ic_data->AddSmiSmiCheckForFastSmiStubs(); 3083 is_smi_two_args_op = call_ic_data->AddSmiSmiCheckForFastSmiStubs();
3161 } 3084 }
3162 if (is_smi_two_args_op) { 3085 if (is_smi_two_args_op) {
3163 ASSERT(ArgumentCount() == 2); 3086 ASSERT(ArgumentCount() == 2);
3164 compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(), 3087 compiler->EmitInstanceCall(*stub_entry, *call_ic_data, ArgumentCount(),
3165 deopt_id(), token_pos(), locs()); 3088 deopt_id(), token_pos(), locs());
3166 } else { 3089 } else {
3167 compiler->GenerateInstanceCall(deopt_id(), 3090 compiler->GenerateInstanceCall(deopt_id(), token_pos(), ArgumentCount(),
3168 token_pos(), 3091 locs(), *call_ic_data);
3169 ArgumentCount(),
3170 locs(),
3171 *call_ic_data);
3172 } 3092 }
3173 } 3093 }
3174 #else 3094 #else
3175 ICData* original_ic_data = &ICData::ZoneHandle(call_ic_data->Original()); 3095 ICData* original_ic_data = &ICData::ZoneHandle(call_ic_data->Original());
3176 3096
3177 // Emit smi fast path instruction. If fast-path succeeds it skips the next 3097 // Emit smi fast path instruction. If fast-path succeeds it skips the next
3178 // instruction otherwise it falls through. Only attempt in unoptimized code 3098 // instruction otherwise it falls through. Only attempt in unoptimized code
3179 // because TryFastPathSmiOp will update original_ic_data. 3099 // because TryFastPathSmiOp will update original_ic_data.
3180 if (!compiler->is_optimizing()) { 3100 if (!compiler->is_optimizing()) {
3181 TryFastPathSmiOp(compiler, original_ic_data, function_name()); 3101 TryFastPathSmiOp(compiler, original_ic_data, function_name());
(...skipping 12 matching lines...) Expand all
3194 if (compiler->is_optimizing()) { 3114 if (compiler->is_optimizing()) {
3195 __ InstanceCall2Opt(ArgumentCount(), call_ic_data_kidx); 3115 __ InstanceCall2Opt(ArgumentCount(), call_ic_data_kidx);
3196 } else { 3116 } else {
3197 __ InstanceCall2(ArgumentCount(), call_ic_data_kidx); 3117 __ InstanceCall2(ArgumentCount(), call_ic_data_kidx);
3198 } 3118 }
3199 break; 3119 break;
3200 default: 3120 default:
3201 UNIMPLEMENTED(); 3121 UNIMPLEMENTED();
3202 break; 3122 break;
3203 } 3123 }
3204 compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, 3124 compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, deopt_id(),
3205 deopt_id(),
3206 token_pos()); 3125 token_pos());
3207 compiler->RecordAfterCall(this); 3126 compiler->RecordAfterCall(this);
3208 3127
3209 if (compiler->is_optimizing()) { 3128 if (compiler->is_optimizing()) {
3210 __ PopLocal(locs()->out(0).reg()); 3129 __ PopLocal(locs()->out(0).reg());
3211 } 3130 }
3212 #endif // !defined(TARGET_ARCH_DBC) 3131 #endif // !defined(TARGET_ARCH_DBC)
3213 } 3132 }
3214 3133
3215 3134
3216 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const { 3135 bool PolymorphicInstanceCallInstr::HasSingleRecognizedTarget() const {
3217 if (FLAG_precompiled_mode && with_checks()) return false; 3136 if (FLAG_precompiled_mode && with_checks()) return false;
3218 3137
3219 return ic_data().HasOneTarget() && 3138 return ic_data().HasOneTarget() &&
3220 (MethodRecognizer::RecognizeKind( 3139 (MethodRecognizer::RecognizeKind(Function::Handle(
3221 Function::Handle(ic_data().GetTargetAt(0))) != 3140 ic_data().GetTargetAt(0))) != MethodRecognizer::kUnknown);
3222 MethodRecognizer::kUnknown);
3223 } 3141 }
3224 3142
3225 3143
3226 // DBC does not support optimizing compiler and thus doesn't emit 3144 // DBC does not support optimizing compiler and thus doesn't emit
3227 // PolymorphicInstanceCallInstr. 3145 // PolymorphicInstanceCallInstr.
3228 #if !defined(TARGET_ARCH_DBC) 3146 #if !defined(TARGET_ARCH_DBC)
3229 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3147 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3230 ASSERT(ic_data().NumArgsTested() == 1); 3148 ASSERT(ic_data().NumArgsTested() == 1);
3231 if (!with_checks()) { 3149 if (!with_checks()) {
3232 ASSERT(ic_data().HasOneTarget()); 3150 ASSERT(ic_data().HasOneTarget());
3233 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); 3151 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
3234 compiler->GenerateStaticCall(deopt_id(), 3152 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(),
3235 instance_call()->token_pos(), 3153 target, instance_call()->ArgumentCount(),
3236 target, 3154 instance_call()->argument_names(), locs(),
3237 instance_call()->ArgumentCount(),
3238 instance_call()->argument_names(),
3239 locs(),
3240 ICData::Handle()); 3155 ICData::Handle());
3241 return; 3156 return;
3242 } 3157 }
3243 3158
3244 compiler->EmitPolymorphicInstanceCall(ic_data(), 3159 compiler->EmitPolymorphicInstanceCall(
3245 instance_call()->ArgumentCount(), 3160 ic_data(), instance_call()->ArgumentCount(),
3246 instance_call()->argument_names(), 3161 instance_call()->argument_names(), deopt_id(),
3247 deopt_id(), 3162 instance_call()->token_pos(), locs(), complete());
3248 instance_call()->token_pos(),
3249 locs(),
3250 complete());
3251 } 3163 }
3252 #endif 3164 #endif
3253 3165
3254 3166
3255 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType( 3167 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType(
3256 const ICData& ic_data) { 3168 const ICData& ic_data) {
3257 bool is_string = true; 3169 bool is_string = true;
3258 bool is_integer = true; 3170 bool is_integer = true;
3259 bool is_double = true; 3171 bool is_double = true;
3260 3172
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3316 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone, 3228 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone,
3317 bool optimizing) const { 3229 bool optimizing) const {
3318 return MakeCallSummary(zone); 3230 return MakeCallSummary(zone);
3319 } 3231 }
3320 3232
3321 3233
3322 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3234 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3323 const ICData* call_ic_data = NULL; 3235 const ICData* call_ic_data = NULL;
3324 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || 3236 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
3325 (ic_data() == NULL)) { 3237 (ic_data() == NULL)) {
3326 const Array& arguments_descriptor = 3238 const Array& arguments_descriptor = Array::Handle(
3327 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), 3239 ArgumentsDescriptor::New(ArgumentCount(), argument_names()));
3328 argument_names()));
3329 MethodRecognizer::Kind recognized_kind = 3240 MethodRecognizer::Kind recognized_kind =
3330 MethodRecognizer::RecognizeKind(function()); 3241 MethodRecognizer::RecognizeKind(function());
3331 int num_args_checked = 0; 3242 int num_args_checked = 0;
3332 switch (recognized_kind) { 3243 switch (recognized_kind) {
3333 case MethodRecognizer::kDoubleFromInteger: 3244 case MethodRecognizer::kDoubleFromInteger:
3334 case MethodRecognizer::kMathMin: 3245 case MethodRecognizer::kMathMin:
3335 case MethodRecognizer::kMathMax: 3246 case MethodRecognizer::kMathMax:
3336 num_args_checked = 2; 3247 num_args_checked = 2;
3337 break; 3248 break;
3338 default: 3249 default:
3339 break; 3250 break;
3340 } 3251 }
3341 call_ic_data = compiler->GetOrAddStaticCallICData(deopt_id(), 3252 call_ic_data = compiler->GetOrAddStaticCallICData(
3342 function(), 3253 deopt_id(), function(), arguments_descriptor, num_args_checked);
3343 arguments_descriptor,
3344 num_args_checked);
3345 } else { 3254 } else {
3346 call_ic_data = &ICData::ZoneHandle(ic_data()->raw()); 3255 call_ic_data = &ICData::ZoneHandle(ic_data()->raw());
3347 } 3256 }
3348 3257
3349 #if !defined(TARGET_ARCH_DBC) 3258 #if !defined(TARGET_ARCH_DBC)
3350 compiler->GenerateStaticCall(deopt_id(), 3259 compiler->GenerateStaticCall(deopt_id(), token_pos(), function(),
3351 token_pos(), 3260 ArgumentCount(), argument_names(), locs(),
3352 function(),
3353 ArgumentCount(),
3354 argument_names(),
3355 locs(),
3356 *call_ic_data); 3261 *call_ic_data);
3357 #else 3262 #else
3358 const Array& arguments_descriptor = 3263 const Array& arguments_descriptor =
3359 (ic_data() == NULL) ? 3264 (ic_data() == NULL) ? Array::Handle(ArgumentsDescriptor::New(
3360 Array::Handle(ArgumentsDescriptor::New(ArgumentCount(), 3265 ArgumentCount(), argument_names()))
3361 argument_names())) : 3266 : Array::Handle(ic_data()->arguments_descriptor());
3362 Array::Handle(ic_data()->arguments_descriptor());
3363 const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor); 3267 const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
3364 3268
3365 if (compiler->is_optimizing()) { 3269 if (compiler->is_optimizing()) {
3366 __ PushConstant(function()); 3270 __ PushConstant(function());
3367 __ StaticCall(ArgumentCount(), argdesc_kidx); 3271 __ StaticCall(ArgumentCount(), argdesc_kidx);
3368 compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, 3272 compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
3369 deopt_id(), token_pos()); 3273 token_pos());
3370 compiler->RecordAfterCall(this); 3274 compiler->RecordAfterCall(this);
3371 __ PopLocal(locs()->out(0).reg()); 3275 __ PopLocal(locs()->out(0).reg());
3372 } else { 3276 } else {
3373 const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data); 3277 const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data);
3374 __ PushConstant(ic_data_kidx); 3278 __ PushConstant(ic_data_kidx);
3375 __ IndirectStaticCall(ArgumentCount(), argdesc_kidx); 3279 __ IndirectStaticCall(ArgumentCount(), argdesc_kidx);
3376 compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall, 3280 compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall,
3377 deopt_id(), token_pos()); 3281 deopt_id(), token_pos());
3378 compiler->RecordAfterCall(this); 3282 compiler->RecordAfterCall(this);
3379 } 3283 }
3380 #endif // !defined(TARGET_ARCH_DBC) 3284 #endif // !defined(TARGET_ARCH_DBC)
3381 } 3285 }
3382 3286
3383 3287
3384 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3288 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3385 compiler->GenerateAssertAssignable(token_pos(), 3289 compiler->GenerateAssertAssignable(token_pos(), deopt_id(), dst_type(),
3386 deopt_id(), 3290 dst_name(), locs());
3387 dst_type(),
3388 dst_name(),
3389 locs());
3390 3291
3391 // DBC does not use LocationSummaries in the same way as other architectures. 3292 // DBC does not use LocationSummaries in the same way as other architectures.
3392 #if !defined(TARGET_ARCH_DBC) 3293 #if !defined(TARGET_ARCH_DBC)
3393 ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); 3294 ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
3394 #endif // !defined(TARGET_ARCH_DBC) 3295 #endif // !defined(TARGET_ARCH_DBC)
3395 } 3296 }
3396 3297
3397 3298
3398 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, 3299 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,
3399 bool opt) const { 3300 bool opt) const {
3400 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); 3301 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
3401 } 3302 }
3402 3303
3403 3304
3404 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3305 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3405 #if !defined(TARGET_ARCH_DBC) 3306 #if !defined(TARGET_ARCH_DBC)
3406 __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_)); 3307 __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_));
3407 #else 3308 #else
3408 compiler->EmitDeopt(deopt_id(), deopt_reason_); 3309 compiler->EmitDeopt(deopt_id(), deopt_reason_);
3409 #endif 3310 #endif
3410 } 3311 }
3411 3312
3412 3313
3413 Environment* Environment::From(Zone* zone, 3314 Environment* Environment::From(Zone* zone,
3414 const GrowableArray<Definition*>& definitions, 3315 const GrowableArray<Definition*>& definitions,
3415 intptr_t fixed_parameter_count, 3316 intptr_t fixed_parameter_count,
3416 const ParsedFunction& parsed_function) { 3317 const ParsedFunction& parsed_function) {
3417 Environment* env = 3318 Environment* env =
3418 new(zone) Environment(definitions.length(), 3319 new (zone) Environment(definitions.length(), fixed_parameter_count,
3419 fixed_parameter_count, 3320 Thread::kNoDeoptId, parsed_function, NULL);
3420 Thread::kNoDeoptId,
3421 parsed_function,
3422 NULL);
3423 for (intptr_t i = 0; i < definitions.length(); ++i) { 3321 for (intptr_t i = 0; i < definitions.length(); ++i) {
3424 env->values_.Add(new(zone) Value(definitions[i])); 3322 env->values_.Add(new (zone) Value(definitions[i]));
3425 } 3323 }
3426 return env; 3324 return env;
3427 } 3325 }
3428 3326
3429 3327
3430 Environment* Environment::DeepCopy(Zone* zone, intptr_t length) const { 3328 Environment* Environment::DeepCopy(Zone* zone, intptr_t length) const {
3431 ASSERT(length <= values_.length()); 3329 ASSERT(length <= values_.length());
3432 Environment* copy = new(zone) Environment( 3330 Environment* copy = new (zone)
3433 length, 3331 Environment(length, fixed_parameter_count_, deopt_id_, parsed_function_,
3434 fixed_parameter_count_, 3332 (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
3435 deopt_id_,
3436 parsed_function_,
3437 (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
3438 if (locations_ != NULL) { 3333 if (locations_ != NULL) {
3439 Location* new_locations = zone->Alloc<Location>(length); 3334 Location* new_locations = zone->Alloc<Location>(length);
3440 copy->set_locations(new_locations); 3335 copy->set_locations(new_locations);
3441 } 3336 }
3442 for (intptr_t i = 0; i < length; ++i) { 3337 for (intptr_t i = 0; i < length; ++i) {
3443 copy->values_.Add(values_[i]->Copy(zone)); 3338 copy->values_.Add(values_[i]->Copy(zone));
3444 if (locations_ != NULL) { 3339 if (locations_ != NULL) {
3445 copy->locations_[i] = locations_[i].Copy(); 3340 copy->locations_[i] = locations_[i].Copy();
3446 } 3341 }
3447 } 3342 }
(...skipping 20 matching lines...) Expand all
3468 Instruction* instr, 3363 Instruction* instr,
3469 intptr_t argc, 3364 intptr_t argc,
3470 Definition* dead, 3365 Definition* dead,
3471 Definition* result) const { 3366 Definition* result) const {
3472 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 3367 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
3473 it.CurrentValue()->RemoveFromUseList(); 3368 it.CurrentValue()->RemoveFromUseList();
3474 } 3369 }
3475 3370
3476 Environment* copy = DeepCopy(zone, values_.length() - argc); 3371 Environment* copy = DeepCopy(zone, values_.length() - argc);
3477 for (intptr_t i = 0; i < argc; i++) { 3372 for (intptr_t i = 0; i < argc; i++) {
3478 copy->values_.Add(new(zone) Value(dead)); 3373 copy->values_.Add(new (zone) Value(dead));
3479 } 3374 }
3480 copy->values_.Add(new(zone) Value(result)); 3375 copy->values_.Add(new (zone) Value(result));
3481 3376
3482 instr->SetEnvironment(copy); 3377 instr->SetEnvironment(copy);
3483 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 3378 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
3484 Value* value = it.CurrentValue(); 3379 Value* value = it.CurrentValue();
3485 value->definition()->AddEnvUse(value); 3380 value->definition()->AddEnvUse(value);
3486 } 3381 }
3487 } 3382 }
3488 3383
3489 3384
3490 // Copies the environment as outer on an inlined instruction and updates the 3385 // Copies the environment as outer on an inlined instruction and updates the
(...skipping 17 matching lines...) Expand all
3508 3403
3509 ComparisonInstr* DoubleTestOpInstr::CopyWithNewOperands(Value* new_left, 3404 ComparisonInstr* DoubleTestOpInstr::CopyWithNewOperands(Value* new_left,
3510 Value* new_right) { 3405 Value* new_right) {
3511 UNREACHABLE(); 3406 UNREACHABLE();
3512 return NULL; 3407 return NULL;
3513 } 3408 }
3514 3409
3515 3410
3516 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left, 3411 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left,
3517 Value* new_right) { 3412 Value* new_right) {
3518 return new EqualityCompareInstr(token_pos(), 3413 return new EqualityCompareInstr(token_pos(), kind(), new_left, new_right,
3519 kind(), 3414 operation_cid(), deopt_id());
3520 new_left,
3521 new_right,
3522 operation_cid(),
3523 deopt_id());
3524 } 3415 }
3525 3416
3526 3417
3527 ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left, 3418 ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left,
3528 Value* new_right) { 3419 Value* new_right) {
3529 return new RelationalOpInstr(token_pos(), 3420 return new RelationalOpInstr(token_pos(), kind(), new_left, new_right,
3530 kind(), 3421 operation_cid(), deopt_id());
3531 new_left,
3532 new_right,
3533 operation_cid(),
3534 deopt_id());
3535 } 3422 }
3536 3423
3537 3424
3538 ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left, 3425 ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left,
3539 Value* new_right) { 3426 Value* new_right) {
3540 return new StrictCompareInstr(token_pos(), 3427 return new StrictCompareInstr(token_pos(), kind(), new_left, new_right,
3541 kind(),
3542 new_left,
3543 new_right,
3544 needs_number_check()); 3428 needs_number_check());
3545 } 3429 }
3546 3430
3547 3431
3548
3549 ComparisonInstr* TestSmiInstr::CopyWithNewOperands(Value* new_left, 3432 ComparisonInstr* TestSmiInstr::CopyWithNewOperands(Value* new_left,
3550 Value* new_right) { 3433 Value* new_right) {
3551 return new TestSmiInstr(token_pos(), kind(), new_left, new_right); 3434 return new TestSmiInstr(token_pos(), kind(), new_left, new_right);
3552 } 3435 }
3553 3436
3554 3437
3555
3556 ComparisonInstr* TestCidsInstr::CopyWithNewOperands(Value* new_left, 3438 ComparisonInstr* TestCidsInstr::CopyWithNewOperands(Value* new_left,
3557 Value* new_right) { 3439 Value* new_right) {
3558 return new TestCidsInstr(token_pos(), 3440 return new TestCidsInstr(token_pos(), kind(), new_left, cid_results(),
3559 kind(),
3560 new_left,
3561 cid_results(),
3562 deopt_id()); 3441 deopt_id());
3563 } 3442 }
3564 3443
3565 3444
3566 bool TestCidsInstr::AttributesEqual(Instruction* other) const { 3445 bool TestCidsInstr::AttributesEqual(Instruction* other) const {
3567 TestCidsInstr* other_instr = other->AsTestCids(); 3446 TestCidsInstr* other_instr = other->AsTestCids();
3568 if (!ComparisonInstr::AttributesEqual(other)) { 3447 if (!ComparisonInstr::AttributesEqual(other)) {
3569 return false; 3448 return false;
3570 } 3449 }
3571 if (cid_results().length() != other_instr->cid_results().length()) { 3450 if (cid_results().length() != other_instr->cid_results().length()) {
(...skipping 16 matching lines...) Expand all
3588 3467
3589 3468
3590 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, 3469 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
3591 Value* v1, 3470 Value* v1,
3592 Value* v2) { 3471 Value* v2) {
3593 #if !defined(TARGET_ARCH_DBC) 3472 #if !defined(TARGET_ARCH_DBC)
3594 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2); 3473 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2);
3595 if (comparison->IsStrictCompare()) { 3474 if (comparison->IsStrictCompare()) {
3596 // Strict comparison with number checks calls a stub and is not supported 3475 // Strict comparison with number checks calls a stub and is not supported
3597 // by if-conversion. 3476 // by if-conversion.
3598 return is_smi_result 3477 return is_smi_result &&
3599 && !comparison->AsStrictCompare()->needs_number_check(); 3478 !comparison->AsStrictCompare()->needs_number_check();
3600 } 3479 }
3601 if (comparison->operation_cid() != kSmiCid) { 3480 if (comparison->operation_cid() != kSmiCid) {
3602 // Non-smi comparisons are not supported by if-conversion. 3481 // Non-smi comparisons are not supported by if-conversion.
3603 return false; 3482 return false;
3604 } 3483 }
3605 return is_smi_result; 3484 return is_smi_result;
3606 #else 3485 #else
3607 return false; 3486 return false;
3608 #endif // !defined(TARGET_ARCH_DBC) 3487 #endif // !defined(TARGET_ARCH_DBC)
3609 } 3488 }
3610 3489
3611 3490
3612 bool PhiInstr::IsRedundant() const { 3491 bool PhiInstr::IsRedundant() const {
3613 ASSERT(InputCount() > 1); 3492 ASSERT(InputCount() > 1);
3614 Definition* first = InputAt(0)->definition(); 3493 Definition* first = InputAt(0)->definition();
3615 for (intptr_t i = 1; i < InputCount(); ++i) { 3494 for (intptr_t i = 1; i < InputCount(); ++i) {
3616 Definition* def = InputAt(i)->definition(); 3495 Definition* def = InputAt(i)->definition();
3617 if (def != first) return false; 3496 if (def != first) return false;
3618 } 3497 }
3619 return true; 3498 return true;
3620 } 3499 }
3621 3500
3622 3501
3623 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) { 3502 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) {
3624 return LoadFieldInstr::IsFixedLengthArrayCid(cid); 3503 return LoadFieldInstr::IsFixedLengthArrayCid(cid);
3625 } 3504 }
3626 3505
3627 3506
3628 Instruction* CheckArrayBoundInstr::Canonicalize(FlowGraph* flow_graph) { 3507 Instruction* CheckArrayBoundInstr::Canonicalize(FlowGraph* flow_graph) {
3629 return IsRedundant(RangeBoundary::FromDefinition(length()->definition())) ? 3508 return IsRedundant(RangeBoundary::FromDefinition(length()->definition()))
3630 NULL : this; 3509 ? NULL
3510 : this;
3631 } 3511 }
3632 3512
3633 3513
3634 intptr_t CheckArrayBoundInstr::LengthOffsetFor(intptr_t class_id) { 3514 intptr_t CheckArrayBoundInstr::LengthOffsetFor(intptr_t class_id) {
3635 if (RawObject::IsExternalTypedDataClassId(class_id)) { 3515 if (RawObject::IsExternalTypedDataClassId(class_id)) {
3636 return ExternalTypedData::length_offset(); 3516 return ExternalTypedData::length_offset();
3637 } 3517 }
3638 if (RawObject::IsTypedDataClassId(class_id)) { 3518 if (RawObject::IsTypedDataClassId(class_id)) {
3639 return TypedData::length_offset(); 3519 return TypedData::length_offset();
3640 } 3520 }
(...skipping 13 matching lines...) Expand all
3654 } 3534 }
3655 3535
3656 3536
3657 const Function& StringInterpolateInstr::CallFunction() const { 3537 const Function& StringInterpolateInstr::CallFunction() const {
3658 if (function_.IsNull()) { 3538 if (function_.IsNull()) {
3659 const int kNumberOfArguments = 1; 3539 const int kNumberOfArguments = 1;
3660 const Array& kNoArgumentNames = Object::null_array(); 3540 const Array& kNoArgumentNames = Object::null_array();
3661 const Class& cls = 3541 const Class& cls =
3662 Class::Handle(Library::LookupCoreClass(Symbols::StringBase())); 3542 Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
3663 ASSERT(!cls.IsNull()); 3543 ASSERT(!cls.IsNull());
3664 function_ = 3544 function_ = Resolver::ResolveStatic(
3665 Resolver::ResolveStatic( 3545 cls, Library::PrivateCoreLibName(Symbols::Interpolate()),
3666 cls, 3546 kNumberOfArguments, kNoArgumentNames);
3667 Library::PrivateCoreLibName(Symbols::Interpolate()),
3668 kNumberOfArguments,
3669 kNoArgumentNames);
3670 } 3547 }
3671 ASSERT(!function_.IsNull()); 3548 ASSERT(!function_.IsNull());
3672 return function_; 3549 return function_;
3673 } 3550 }
3674 3551
3675 3552
3676 // Replace StringInterpolateInstr with a constant string if all inputs are 3553 // Replace StringInterpolateInstr with a constant string if all inputs are
3677 // constant of [string, number, boolean, null]. 3554 // constant of [string, number, boolean, null].
3678 // Leave the CreateArrayInstr and StoreIndexedInstr in the stream in case 3555 // Leave the CreateArrayInstr and StoreIndexedInstr in the stream in case
3679 // deoptimization occurs. 3556 // deoptimization occurs.
(...skipping 18 matching lines...) Expand all
3698 return this; 3575 return this;
3699 } 3576 }
3700 const intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); 3577 const intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
3701 Thread* thread = Thread::Current(); 3578 Thread* thread = Thread::Current();
3702 Zone* zone = thread->zone(); 3579 Zone* zone = thread->zone();
3703 GrowableHandlePtrArray<const String> pieces(zone, length); 3580 GrowableHandlePtrArray<const String> pieces(zone, length);
3704 for (intptr_t i = 0; i < length; i++) { 3581 for (intptr_t i = 0; i < length; i++) {
3705 pieces.Add(Object::null_string()); 3582 pieces.Add(Object::null_string());
3706 } 3583 }
3707 3584
3708 for (Value::Iterator it(create_array->input_use_list()); 3585 for (Value::Iterator it(create_array->input_use_list()); !it.Done();
3709 !it.Done();
3710 it.Advance()) { 3586 it.Advance()) {
3711 Instruction* curr = it.Current()->instruction(); 3587 Instruction* curr = it.Current()->instruction();
3712 if (curr == this) continue; 3588 if (curr == this) continue;
3713 3589
3714 StoreIndexedInstr* store = curr->AsStoreIndexed(); 3590 StoreIndexedInstr* store = curr->AsStoreIndexed();
3715 if (!store->index()->BindsToConstant() || 3591 if (!store->index()->BindsToConstant() ||
3716 !store->index()->BoundConstant().IsSmi()) { 3592 !store->index()->BoundConstant().IsSmi()) {
3717 return this; 3593 return this;
3718 } 3594 }
3719 intptr_t store_index = Smi::Cast(store->index()->BoundConstant()).Value(); 3595 intptr_t store_index = Smi::Cast(store->index()->BoundConstant()).Value();
3720 ASSERT(store_index < length); 3596 ASSERT(store_index < length);
3721 ASSERT(store != NULL); 3597 ASSERT(store != NULL);
3722 if (store->value()->definition()->IsConstant()) { 3598 if (store->value()->definition()->IsConstant()) {
3723 ASSERT(store->index()->BindsToConstant()); 3599 ASSERT(store->index()->BindsToConstant());
3724 const Object& obj = store->value()->definition()->AsConstant()->value(); 3600 const Object& obj = store->value()->definition()->AsConstant()->value();
3725 // TODO(srdjan): Verify if any other types should be converted as well. 3601 // TODO(srdjan): Verify if any other types should be converted as well.
3726 if (obj.IsString()) { 3602 if (obj.IsString()) {
3727 pieces.SetAt(store_index, String::Cast(obj)); 3603 pieces.SetAt(store_index, String::Cast(obj));
3728 } else if (obj.IsSmi()) { 3604 } else if (obj.IsSmi()) {
3729 const char* cstr = obj.ToCString(); 3605 const char* cstr = obj.ToCString();
3730 pieces.SetAt(store_index, 3606 pieces.SetAt(store_index,
3731 String::Handle(zone, String::New(cstr, Heap::kOld))); 3607 String::Handle(zone, String::New(cstr, Heap::kOld)));
3732 } else if (obj.IsBool()) { 3608 } else if (obj.IsBool()) {
3733 pieces.SetAt(store_index, 3609 pieces.SetAt(store_index, Bool::Cast(obj).value() ? Symbols::True()
3734 Bool::Cast(obj).value() ? Symbols::True() : Symbols::False()); 3610 : Symbols::False());
3735 } else if (obj.IsNull()) { 3611 } else if (obj.IsNull()) {
3736 pieces.SetAt(store_index, Symbols::Null()); 3612 pieces.SetAt(store_index, Symbols::Null());
3737 } else { 3613 } else {
3738 return this; 3614 return this;
3739 } 3615 }
3740 } else { 3616 } else {
3741 return this; 3617 return this;
3742 } 3618 }
3743 } 3619 }
3744 3620
3745 const String& concatenated = String::ZoneHandle(zone, 3621 const String& concatenated =
3746 Symbols::FromConcatAll(thread, pieces)); 3622 String::ZoneHandle(zone, Symbols::FromConcatAll(thread, pieces));
3747 return flow_graph->GetConstant(concatenated); 3623 return flow_graph->GetConstant(concatenated);
3748 } 3624 }
3749 3625
3750 3626
3751 static AlignmentType StrengthenAlignment(intptr_t cid, 3627 static AlignmentType StrengthenAlignment(intptr_t cid,
3752 AlignmentType alignment) { 3628 AlignmentType alignment) {
3753 switch (cid) { 3629 switch (cid) {
3754 case kTypedDataInt8ArrayCid: 3630 case kTypedDataInt8ArrayCid:
3755 case kTypedDataUint8ArrayCid: 3631 case kTypedDataUint8ArrayCid:
3756 case kTypedDataUint8ClampedArrayCid: 3632 case kTypedDataUint8ClampedArrayCid:
(...skipping 27 matching lines...) Expand all
3784 : TemplateDefinition(deopt_id), 3660 : TemplateDefinition(deopt_id),
3785 index_scale_(index_scale), 3661 index_scale_(index_scale),
3786 class_id_(class_id), 3662 class_id_(class_id),
3787 alignment_(StrengthenAlignment(class_id, alignment)), 3663 alignment_(StrengthenAlignment(class_id, alignment)),
3788 token_pos_(token_pos) { 3664 token_pos_(token_pos) {
3789 SetInputAt(0, array); 3665 SetInputAt(0, array);
3790 SetInputAt(1, index); 3666 SetInputAt(1, index);
3791 } 3667 }
3792 3668
3793 3669
3794
3795 StoreIndexedInstr::StoreIndexedInstr(Value* array, 3670 StoreIndexedInstr::StoreIndexedInstr(Value* array,
3796 Value* index, 3671 Value* index,
3797 Value* value, 3672 Value* value,
3798 StoreBarrierType emit_store_barrier, 3673 StoreBarrierType emit_store_barrier,
3799 intptr_t index_scale, 3674 intptr_t index_scale,
3800 intptr_t class_id, 3675 intptr_t class_id,
3801 AlignmentType alignment, 3676 AlignmentType alignment,
3802 intptr_t deopt_id, 3677 intptr_t deopt_id,
3803 TokenPosition token_pos) 3678 TokenPosition token_pos)
3804 : TemplateDefinition(deopt_id), 3679 : TemplateDefinition(deopt_id),
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3852 case MethodRecognizer::kMathDoublePow: 3727 case MethodRecognizer::kMathDoublePow:
3853 case MethodRecognizer::kMathAtan2: 3728 case MethodRecognizer::kMathAtan2:
3854 return 2; 3729 return 2;
3855 default: 3730 default:
3856 UNREACHABLE(); 3731 UNREACHABLE();
3857 } 3732 }
3858 return 0; 3733 return 0;
3859 } 3734 }
3860 3735
3861 // Use expected function signatures to help MSVC compiler resolve overloading. 3736 // Use expected function signatures to help MSVC compiler resolve overloading.
3862 typedef double (*UnaryMathCFunction) (double x); 3737 typedef double (*UnaryMathCFunction)(double x);
3863 typedef double (*BinaryMathCFunction) (double x, double y); 3738 typedef double (*BinaryMathCFunction)(double x, double y);
3864 3739
3865 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcPow, 2, true /* is_float */, 3740 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3866 reinterpret_cast<RuntimeFunction>( 3741 LibcPow,
3867 static_cast<BinaryMathCFunction>(&pow))); 3742 2,
3743 true /* is_float */,
3744 reinterpret_cast<RuntimeFunction>(static_cast<BinaryMathCFunction>(&pow)));
3868 3745
3869 DEFINE_RAW_LEAF_RUNTIME_ENTRY(DartModulo, 2, true /* is_float */, 3746 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3747 DartModulo,
3748 2,
3749 true /* is_float */,
3870 reinterpret_cast<RuntimeFunction>( 3750 reinterpret_cast<RuntimeFunction>(
3871 static_cast<BinaryMathCFunction>(&DartModulo))); 3751 static_cast<BinaryMathCFunction>(&DartModulo)));
3872 3752
3873 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcAtan2, 2, true /* is_float */, 3753 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3754 LibcAtan2,
3755 2,
3756 true /* is_float */,
3874 reinterpret_cast<RuntimeFunction>( 3757 reinterpret_cast<RuntimeFunction>(
3875 static_cast<BinaryMathCFunction>(&atan2_ieee))); 3758 static_cast<BinaryMathCFunction>(&atan2_ieee)));
3876 3759
3877 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcFloor, 1, true /* is_float */, 3760 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3878 reinterpret_cast<RuntimeFunction>( 3761 LibcFloor,
3879 static_cast<UnaryMathCFunction>(&floor))); 3762 1,
3763 true /* is_float */,
3764 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&floor)));
3880 3765
3881 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcCeil, 1, true /* is_float */, 3766 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3882 reinterpret_cast<RuntimeFunction>( 3767 LibcCeil,
3883 static_cast<UnaryMathCFunction>(&ceil))); 3768 1,
3769 true /* is_float */,
3770 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&ceil)));
3884 3771
3885 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcTrunc, 1, true /* is_float */, 3772 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3886 reinterpret_cast<RuntimeFunction>( 3773 LibcTrunc,
3887 static_cast<UnaryMathCFunction>(&trunc))); 3774 1,
3775 true /* is_float */,
3776 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&trunc)));
3888 3777
3889 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcRound, 1, true /* is_float */, 3778 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3890 reinterpret_cast<RuntimeFunction>( 3779 LibcRound,
3891 static_cast<UnaryMathCFunction>(&round))); 3780 1,
3781 true /* is_float */,
3782 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&round)));
3892 3783
3893 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcCos, 1, true /* is_float */, 3784 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3894 reinterpret_cast<RuntimeFunction>( 3785 LibcCos,
3895 static_cast<UnaryMathCFunction>(&cos))); 3786 1,
3787 true /* is_float */,
3788 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&cos)));
3896 3789
3897 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcSin, 1, true /* is_float */, 3790 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3898 reinterpret_cast<RuntimeFunction>( 3791 LibcSin,
3899 static_cast<UnaryMathCFunction>(&sin))); 3792 1,
3793 true /* is_float */,
3794 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&sin)));
3900 3795
3901 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcAsin, 1, true /* is_float */, 3796 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3902 reinterpret_cast<RuntimeFunction>( 3797 LibcAsin,
3903 static_cast<UnaryMathCFunction>(&asin))); 3798 1,
3799 true /* is_float */,
3800 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&asin)));
3904 3801
3905 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcAcos, 1, true /* is_float */, 3802 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3906 reinterpret_cast<RuntimeFunction>( 3803 LibcAcos,
3907 static_cast<UnaryMathCFunction>(&acos))); 3804 1,
3805 true /* is_float */,
3806 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&acos)));
3908 3807
3909 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcTan, 1, true /* is_float */, 3808 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3910 reinterpret_cast<RuntimeFunction>( 3809 LibcTan,
3911 static_cast<UnaryMathCFunction>(&tan))); 3810 1,
3811 true /* is_float */,
3812 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&tan)));
3912 3813
3913 DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcAtan, 1, true /* is_float */, 3814 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
3914 reinterpret_cast<RuntimeFunction>( 3815 LibcAtan,
3915 static_cast<UnaryMathCFunction>(&atan))); 3816 1,
3817 true /* is_float */,
3818 reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&atan)));
3916 3819
3917 3820
3918 const RuntimeEntry& InvokeMathCFunctionInstr::TargetFunction() const { 3821 const RuntimeEntry& InvokeMathCFunctionInstr::TargetFunction() const {
3919 switch (recognized_kind_) { 3822 switch (recognized_kind_) {
3920 case MethodRecognizer::kDoubleTruncate: 3823 case MethodRecognizer::kDoubleTruncate:
3921 return kLibcTruncRuntimeEntry; 3824 return kLibcTruncRuntimeEntry;
3922 case MethodRecognizer::kDoubleRound: 3825 case MethodRecognizer::kDoubleRound:
3923 return kLibcRoundRuntimeEntry; 3826 return kLibcRoundRuntimeEntry;
3924 case MethodRecognizer::kDoubleFloor: 3827 case MethodRecognizer::kDoubleFloor:
3925 return kLibcFloorRuntimeEntry; 3828 return kLibcFloorRuntimeEntry;
(...skipping 19 matching lines...) Expand all
3945 return kLibcAtan2RuntimeEntry; 3848 return kLibcAtan2RuntimeEntry;
3946 default: 3849 default:
3947 UNREACHABLE(); 3850 UNREACHABLE();
3948 } 3851 }
3949 return kLibcPowRuntimeEntry; 3852 return kLibcPowRuntimeEntry;
3950 } 3853 }
3951 3854
3952 3855
3953 const char* MathUnaryInstr::KindToCString(MathUnaryKind kind) { 3856 const char* MathUnaryInstr::KindToCString(MathUnaryKind kind) {
3954 switch (kind) { 3857 switch (kind) {
3955 case kIllegal: return "illegal"; 3858 case kIllegal:
3956 case kSqrt: return "sqrt"; 3859 return "illegal";
3957 case kDoubleSquare: return "double-square"; 3860 case kSqrt:
3861 return "sqrt";
3862 case kDoubleSquare:
3863 return "double-square";
3958 } 3864 }
3959 UNREACHABLE(); 3865 UNREACHABLE();
3960 return ""; 3866 return "";
3961 } 3867 }
3962 3868
3963 3869
3964 const RuntimeEntry& CaseInsensitiveCompareUC16Instr::TargetFunction() const { 3870 const RuntimeEntry& CaseInsensitiveCompareUC16Instr::TargetFunction() const {
3965 return kCaseInsensitiveCompareUC16RuntimeEntry; 3871 return kCaseInsensitiveCompareUC16RuntimeEntry;
3966 } 3872 }
3967 3873
3968 3874
3969 MergedMathInstr::MergedMathInstr(ZoneGrowableArray<Value*>* inputs, 3875 MergedMathInstr::MergedMathInstr(ZoneGrowableArray<Value*>* inputs,
3970 intptr_t deopt_id, 3876 intptr_t deopt_id,
3971 MergedMathInstr::Kind kind) 3877 MergedMathInstr::Kind kind)
3972 : PureDefinition(deopt_id), 3878 : PureDefinition(deopt_id), inputs_(inputs), kind_(kind) {
3973 inputs_(inputs),
3974 kind_(kind) {
3975 ASSERT(inputs_->length() == InputCountFor(kind_)); 3879 ASSERT(inputs_->length() == InputCountFor(kind_));
3976 for (intptr_t i = 0; i < inputs_->length(); ++i) { 3880 for (intptr_t i = 0; i < inputs_->length(); ++i) {
3977 ASSERT((*inputs)[i] != NULL); 3881 ASSERT((*inputs)[i] != NULL);
3978 (*inputs)[i]->set_instruction(this); 3882 (*inputs)[i]->set_instruction(this);
3979 (*inputs)[i]->set_use_index(i); 3883 (*inputs)[i]->set_use_index(i);
3980 } 3884 }
3981 } 3885 }
3982 3886
3983 3887
3984 intptr_t MergedMathInstr::OutputIndexOf(MethodRecognizer::Kind kind) { 3888 intptr_t MergedMathInstr::OutputIndexOf(MethodRecognizer::Kind kind) {
3985 switch (kind) { 3889 switch (kind) {
3986 case MethodRecognizer::kMathSin: return 1; 3890 case MethodRecognizer::kMathSin:
3987 case MethodRecognizer::kMathCos: return 0; 3891 return 1;
3988 default: UNIMPLEMENTED(); return -1; 3892 case MethodRecognizer::kMathCos:
3893 return 0;
3894 default:
3895 UNIMPLEMENTED();
3896 return -1;
3989 } 3897 }
3990 } 3898 }
3991 3899
3992 3900
3993 intptr_t MergedMathInstr::OutputIndexOf(Token::Kind token) { 3901 intptr_t MergedMathInstr::OutputIndexOf(Token::Kind token) {
3994 switch (token) { 3902 switch (token) {
3995 case Token::kTRUNCDIV: return 0; 3903 case Token::kTRUNCDIV:
3996 case Token::kMOD: return 1; 3904 return 0;
3997 default: UNIMPLEMENTED(); return -1; 3905 case Token::kMOD:
3906 return 1;
3907 default:
3908 UNIMPLEMENTED();
3909 return -1;
3998 } 3910 }
3999 } 3911 }
4000 3912
4001 3913
4002 void NativeCallInstr::SetupNative() { 3914 void NativeCallInstr::SetupNative() {
4003 Zone* zone = Thread::Current()->zone(); 3915 Zone* zone = Thread::Current()->zone();
4004 const Class& cls = Class::Handle(zone, function().Owner()); 3916 const Class& cls = Class::Handle(zone, function().Owner());
4005 const Library& library = Library::Handle(zone, cls.library()); 3917 const Library& library = Library::Handle(zone, cls.library());
4006 const int num_params = 3918 const int num_params =
4007 NativeArguments::ParameterCountForResolution(function()); 3919 NativeArguments::ParameterCountForResolution(function());
4008 bool auto_setup_scope = true; 3920 bool auto_setup_scope = true;
4009 NativeFunction native_function = NativeEntry::ResolveNative( 3921 NativeFunction native_function = NativeEntry::ResolveNative(
4010 library, native_name(), num_params, &auto_setup_scope); 3922 library, native_name(), num_params, &auto_setup_scope);
4011 if (native_function == NULL) { 3923 if (native_function == NULL) {
4012 Report::MessageF(Report::kError, 3924 Report::MessageF(Report::kError, Script::Handle(function().script()),
4013 Script::Handle(function().script()), 3925 function().token_pos(), Report::AtLocation,
4014 function().token_pos(),
4015 Report::AtLocation,
4016 "native function '%s' (%" Pd " arguments) cannot be found", 3926 "native function '%s' (%" Pd " arguments) cannot be found",
4017 native_name().ToCString(), 3927 native_name().ToCString(), function().NumParameters());
4018 function().NumParameters());
4019 } 3928 }
4020 set_native_c_function(native_function); 3929 set_native_c_function(native_function);
4021 function().SetIsNativeAutoSetupScope(auto_setup_scope); 3930 function().SetIsNativeAutoSetupScope(auto_setup_scope);
4022 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); 3931 Dart_NativeEntryResolver resolver = library.native_entry_resolver();
4023 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); 3932 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver);
4024 set_is_bootstrap_native(is_bootstrap_native); 3933 set_is_bootstrap_native(is_bootstrap_native);
4025 } 3934 }
4026 3935
4027 #undef __ 3936 #undef __
4028 3937
4029 } // namespace dart 3938 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698