| Index: runtime/vm/opt_code_generator_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/opt_code_generator_ia32.cc (revision 897)
|
| +++ runtime/vm/opt_code_generator_ia32.cc (working copy)
|
| @@ -1424,8 +1424,103 @@
|
| }
|
|
|
|
|
| -// Return false if the code cannot be generated.
|
| +// Generate code under assumption that it is common that a Smi
|
| +// is compared with null.
|
| +// Left argument can be Smi or null, otherwise deoptimize and collect more
|
| +// type information.
|
| +// Right operand can be Smi or null, otherwise call operator on Smi (e.g,
|
| +// when compared with double).
|
| +// This code will be more optimized once we collect types for two arguments.
|
| +void OptimizingCodeGenerator::GenerateSmiEquality(ComparisonNode* node) {
|
| + ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE));
|
| + CodeGenInfo left_info(node->left());
|
| + CodeGenInfo right_info(node->right());
|
| + VisitLoadTwo(node->left(), node->right(), EAX, EDX);
|
| + if (!CodeGenerator::IsResultNeeded(node)) {
|
| + return;
|
| + }
|
| + const Immediate raw_null =
|
| + Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| + Label evaluate_comparison;
|
| + if (!left_info.IsClass(smi_class_)) {
|
| + DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node, EAX, EDX);
|
| + Label left_not_null;
|
| + __ cmpl(EAX, raw_null);
|
| + __ j(NOT_EQUAL, &left_not_null, Assembler::kNearJump);
|
| +
|
| + // Left is null, strict compare.
|
| + __ cmpl(EAX, EDX);
|
| + __ jmp(&evaluate_comparison, Assembler::kNearJump);
|
| +
|
| + // Deoptimize if left is not Smi.
|
| + __ Bind(&left_not_null);
|
| + __ testl(EAX, Immediate(kSmiTagMask));
|
| + __ j(NOT_ZERO, deopt_blob->label());
|
| + }
|
| + Label done;
|
| + if (right_info.IsClass(smi_class_)) {
|
| + __ cmpl(EAX, EDX);
|
| + // Fall through to evaluate comparison.
|
| + } else {
|
| + Label call_operator, inlined_compare;
|
| + // Test right for being Smi.
|
| + __ testl(EDX, Immediate(kSmiTagMask));
|
| + __ j(ZERO, &inlined_compare, Assembler::kNearJump);
|
| + // Right is not Smi, test it for being null; if so result is false which
|
| + // is generated by comparing it to left. If right is not null call operator
|
| + // (could be double).
|
| + __ cmpl(EDX, raw_null);
|
| + __ j(NOT_EQUAL, &call_operator, Assembler::kNearJump);
|
| +
|
| + __ Bind(&inlined_compare);
|
| + // Left is Smi, right is Smi or Null.
|
| + __ cmpl(EAX, EDX);
|
| + __ jmp(&evaluate_comparison);
|
| +
|
| + __ Bind(&call_operator);
|
| + // Left is Smi.
|
| + const int kNumberOfArguments = 2;
|
| + const Array& kNoArgumentNames = Array::Handle();
|
| + __ pushl(EAX);
|
| + __ pushl(EDX);
|
| + GenerateCheckedInstanceCalls(node,
|
| + node->left(),
|
| + node->id(),
|
| + node->token_index(),
|
| + kNumberOfArguments,
|
| + kNoArgumentNames);
|
| + __ pushl(EAX);
|
| + __ jmp(&done, Assembler::kNearJump);
|
| + }
|
| + __ Bind(&evaluate_comparison);
|
| + // Condition is set by a previous comparison operation.
|
| + Condition condition = OVERFLOW; // Initialize to something.
|
| + bool ok = SupportedTokenKindToSmiCondition(node->kind(), &condition);
|
| + ASSERT(ok);
|
| + if (NodeInfoHasLabels(node)) {
|
| + GenerateConditionalJumps(*(node->info()), condition);
|
| + node->info()->set_labels_used(true);
|
| + } else {
|
| + const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
| + const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
| + Label true_label;
|
| + __ j(condition, &true_label, Assembler::kNearJump);
|
| + __ PushObject(bool_false);
|
| + __ jmp(&done, Assembler::kNearJump);
|
| + __ Bind(&true_label);
|
| + __ PushObject(bool_true);
|
| + }
|
| + __ Bind(&done);
|
| +}
|
| +
|
| +
|
| +// Return false if the code cannot be generated. It is expected that
|
| +// node->left() is Smi (or null for equality comparison).
|
| bool OptimizingCodeGenerator::GenerateSmiComparison(ComparisonNode* node) {
|
| + if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) {
|
| + GenerateSmiEquality(node);
|
| + return true;
|
| + }
|
| Condition condition;
|
| if (!SupportedTokenKindToSmiCondition(node->kind(), &condition)) {
|
| return false;
|
| @@ -1438,7 +1533,6 @@
|
| if (!CodeGenerator::IsResultNeeded(node)) {
|
| return true;
|
| }
|
| - Label two_smis;
|
| if (left_info.IsClass(smi_class_) && right_info.IsClass(smi_class_)) {
|
| __ cmpl(EAX, EDX);
|
| } else if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) {
|
| @@ -1499,7 +1593,7 @@
|
| // Checks if an inlined equality/non-equality operation can be emitted:
|
| // - type feedback must exist.
|
| // - no class in type feedback list overrides '=='.
|
| -// - no Smi class in type feedback class list.
|
| +// - no Smi class in type feedback class list (Smi overrides equality operator).
|
| bool OptimizingCodeGenerator::GenerateEqualityComparison(ComparisonNode* node) {
|
| ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE));
|
| const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
|
|