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

Unified Diff: runtime/vm/opt_code_generator_ia32.cc

Issue 8413047: Special code for equality comparison for Smi, allowing null on left or right without calling deop... (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/opt_code_generator_ia32.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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());
« no previous file with comments | « runtime/vm/opt_code_generator_ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698