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

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

Issue 10823278: Use type propagation for removing Smi checks in binary operations and comparisons. Regis will adapt… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 __ jmp(&done); 431 __ jmp(&done);
432 __ Bind(&non_null_compare); // Receiver is not null. 432 __ Bind(&non_null_compare); // Receiver is not null.
433 __ pushl(left); 433 __ pushl(left);
434 __ pushl(right); 434 __ pushl(right);
435 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, 435 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
436 deopt_id, token_pos, try_index); 436 deopt_id, token_pos, try_index);
437 __ Bind(&done); 437 __ Bind(&done);
438 } 438 }
439 439
440 440
441 static intptr_t GetCid(const Value& v) {
442 const AbstractType& type = AbstractType::Handle(v.CompileType());
443 return Class::Handle(type.type_class()).id();
444 }
445
446
441 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 447 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
442 const LocationSummary& locs, 448 const LocationSummary& locs,
443 Token::Kind kind, 449 Token::Kind kind,
444 BranchInstr* branch, 450 BranchInstr* branch,
445 intptr_t deopt_id, 451 intptr_t deopt_id,
446 intptr_t token_pos, 452 intptr_t token_pos,
447 intptr_t try_index) { 453 intptr_t try_index) {
448 Register left = locs.in(0).reg(); 454 Register left = locs.in(0).reg();
449 Register right = locs.in(1).reg(); 455 Register right = locs.in(1).reg();
450 Register temp = locs.temp(0).reg(); 456 const bool left_is_smi = (branch == NULL) ?
451 Label* deopt = compiler->AddDeoptStub(deopt_id, 457 false : (GetCid(*branch->left()) == kSmiCid);
452 try_index, 458 const bool right_is_smi = (branch == NULL) ?
453 kDeoptSmiCompareSmi, 459 false : (GetCid(*branch->left()) == kSmiCid);
454 left, 460 if (!left_is_smi || !right_is_smi) {
455 right); 461 Register temp = locs.temp(0).reg();
456 __ movl(temp, left); 462 Label* deopt = compiler->AddDeoptStub(deopt_id,
457 __ orl(temp, right); 463 try_index,
458 __ testl(temp, Immediate(kSmiTagMask)); 464 kDeoptSmiCompareSmi,
459 __ j(NOT_ZERO, deopt); 465 left,
466 right);
467 __ movl(temp, left);
468 __ orl(temp, right);
469 __ testl(temp, Immediate(kSmiTagMask));
470 __ j(NOT_ZERO, deopt);
471 }
460 472
461 Condition true_condition = TokenKindToSmiCondition(kind); 473 Condition true_condition = TokenKindToSmiCondition(kind);
462 __ cmpl(left, right); 474 __ cmpl(left, right);
463 475
464 if (branch != NULL) { 476 if (branch != NULL) {
465 branch->EmitBranchOnCondition(compiler, true_condition); 477 branch->EmitBranchOnCondition(compiler, true_condition);
466 } else { 478 } else {
467 Register result = locs.out().reg(); 479 Register result = locs.out().reg();
468 Label done, is_true; 480 Label done, is_true;
469 __ j(true_condition, &is_true); 481 __ j(true_condition, &is_true);
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 } 1434 }
1423 } 1435 }
1424 1436
1425 1437
1426 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { 1438 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
1427 Register left = comp->locs()->in(0).reg(); 1439 Register left = comp->locs()->in(0).reg();
1428 Register right = comp->locs()->in(1).reg(); 1440 Register right = comp->locs()->in(1).reg();
1429 Register result = comp->locs()->out().reg(); 1441 Register result = comp->locs()->out().reg();
1430 Register temp = comp->locs()->temp(0).reg(); 1442 Register temp = comp->locs()->temp(0).reg();
1431 ASSERT(left == result); 1443 ASSERT(left == result);
1432 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), 1444 const bool left_is_smi = (GetCid(*comp->left()) == kSmiCid);
1433 comp->instance_call()->try_index(), 1445 const bool right_is_smi = (GetCid(*comp->left()) == kSmiCid);
1434 kDeoptSmiBinaryOp, 1446 bool can_deopt;
1435 temp, 1447 switch (comp->op_kind()) {
1436 right); 1448 case Token::kBIT_AND:
1437 // TODO(vegorov): for many binary operations this pattern can be rearranged 1449 case Token::kBIT_OR:
1438 // to save one move. 1450 case Token::kBIT_XOR:
1439 __ movl(temp, left); 1451 can_deopt = !(right_is_smi && left_is_smi);
1440 __ orl(left, right); 1452 break;
1441 __ testl(left, Immediate(kSmiTagMask)); 1453 default:
1442 __ j(NOT_ZERO, deopt); 1454 can_deopt = true;
1443 __ movl(left, temp); 1455 }
1456 Label* deopt = NULL;
1457 if (can_deopt) {
1458 deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(),
1459 comp->instance_call()->try_index(),
1460 kDeoptSmiBinaryOp,
1461 temp,
1462 right);
1463 }
1464 if (left_is_smi && right_is_smi) {
1465 if (can_deopt) {
1466 // Preserve left for deopt.
1467 __ movl(temp, left);
1468 }
1469 } else {
1470 // TODO(vegorov): for many binary operations this pattern can be rearranged
1471 // to save one move.
1472 __ movl(temp, left);
1473 __ orl(left, right);
1474 __ testl(left, Immediate(kSmiTagMask));
1475 __ j(NOT_ZERO, deopt);
1476 __ movl(left, temp);
1477 }
1444 switch (comp->op_kind()) { 1478 switch (comp->op_kind()) {
1445 case Token::kADD: { 1479 case Token::kADD: {
1446 __ addl(left, right); 1480 __ addl(left, right);
1447 __ j(OVERFLOW, deopt); 1481 __ j(OVERFLOW, deopt);
1448 break; 1482 break;
1449 } 1483 }
1450 case Token::kSUB: { 1484 case Token::kSUB: {
1451 __ subl(left, right); 1485 __ subl(left, right);
1452 __ j(OVERFLOW, deopt); 1486 __ j(OVERFLOW, deopt);
1453 break; 1487 break;
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
2062 kNumArgsChecked); 2096 kNumArgsChecked);
2063 __ CompareObject(EAX, compiler->bool_true()); 2097 __ CompareObject(EAX, compiler->bool_true());
2064 EmitBranchOnCondition(compiler, branch_condition); 2098 EmitBranchOnCondition(compiler, branch_condition);
2065 } 2099 }
2066 2100
2067 } // namespace dart 2101 } // namespace dart
2068 2102
2069 #undef __ 2103 #undef __
2070 2104
2071 #endif // defined TARGET_ARCH_X64 2105 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698