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

Unified Diff: runtime/vm/opt_code_generator_ia32.cc

Issue 9007027: Add (debug) printing when IC is used in optimized code (must eliminate it). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years 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/compiler.cc ('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 2670)
+++ runtime/vm/opt_code_generator_ia32.cc (working copy)
@@ -655,6 +655,29 @@
}
+// IC data may have only one check, and it has to contain the two classes in
+// specified order.
+static bool AtIdNodeHasTwoClasses(AstNode* node,
+ intptr_t id,
+ const Class& cls0,
+ const Class& cls1) {
+ ASSERT(node != NULL);
+ ASSERT(!cls0.IsNull() && !cls1.IsNull());
hausner 2011/12/20 21:50:08 You could move this assertion after line 670 to ma
srdjan 2011/12/20 21:55:05 Yes, but I want to catch mistakes at call site ear
+ const ICData& ic_data = node->ICDataAtId(id);
+ ASSERT(ic_data.NumberOfArgumentsChecked() == 2);
+ if (ic_data.NumberOfChecks() != 1) {
+ return false;
+ }
+ Function& target = Function::Handle();
+ GrowableArray<const Class*> classes;
+ ic_data.GetCheckAt(0, &classes, &target);
+ if ((cls0.raw() == classes[0]->raw()) && (cls1.raw() == classes[1]->raw())) {
+ return true;
+ }
+ return false;
+}
+
+
static bool AtIdNodeHasOnlyClass(AstNode* node, intptr_t id, const Class& cls) {
ASSERT(node != NULL);
ASSERT(!cls.IsNull());
@@ -858,9 +881,7 @@
}
-// TODO(srdjan): Expand inline caches to detect Smi/double operations, so that
-// we do not have to call the instance method, and therefore could guarantee
-// that the result is a Smi at the end.
+// Handles only Smi & Smi.
void OptimizingCodeGenerator::GenerateSmiBinaryOp(BinaryOpNode* node) {
const char* kOptMessage = "Inlines BinaryOp for Smi";
Label done;
@@ -880,81 +901,50 @@
Function& target = Function::Handle();
GrowableArray<const Class*> classes;
ic_data.GetCheckAt(0, &classes, &target);
- const bool both_args_expected_smi =
- (ic_data.NumberOfChecks() == 1) &&
- (classes[0]->raw() == smi_class_.raw()) &&
- (classes[1]->raw() == smi_class_.raw());
-
+ ASSERT(ic_data.NumberOfChecks() == 1);
+ ASSERT((classes[0]->raw() == smi_class_.raw()) &&
+ (classes[1]->raw() == smi_class_.raw()));
CodeGenInfo left_info(node->left());
CodeGenInfo right_info(node->right());
VisitLoadTwo(node->left(), node->right(), EAX, EDX);
- Label* overflow_label = NULL;
Label two_smis, call_operator;
- if (both_args_expected_smi) {
- DeoptimizationBlob* deopt_blob =
- AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp);
- overflow_label = deopt_blob->label();
- __ movl(ECX, EAX); // Save if overflow (needs original value).
+ DeoptimizationBlob* deopt_blob =
+ AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp);
+ __ movl(ECX, EAX); // Save if overflow (needs original value).
- if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) {
- if (!left_info.IsClass(smi_class_) || !right_info.IsClass(smi_class_)) {
- // One of the type is not known (statically) to be Smi. Check it.
- Register test_reg = left_info.IsClass(smi_class_) ? EDX : EAX;
- __ testl(test_reg, Immediate(kSmiTagMask));
- __ j(NOT_ZERO, deopt_blob->label());
- }
- } else {
- // Type feedback says both types are Smi, but static type analysis
- // does not know if any of them is Smi, therefore check.
- __ orl(EAX, EDX);
- __ testl(EAX, Immediate(kSmiTagMask));
+ if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) {
+ if (!left_info.IsClass(smi_class_) || !right_info.IsClass(smi_class_)) {
+ // One of the type is not known (statically) to be Smi. Check it.
+ Register test_reg = left_info.IsClass(smi_class_) ? EDX : EAX;
+ __ testl(test_reg, Immediate(kSmiTagMask));
__ j(NOT_ZERO, deopt_blob->label());
- __ movl(EAX, ECX);
}
- if (node->info() != NULL) {
- node->info()->set_is_class(&smi_class_);
- }
} else {
- overflow_label = &call_operator;
- __ movl(ECX, EAX);
+ // Type feedback says both types are Smi, but static type analysis
+ // does not know if any of them is Smi, therefore check.
__ orl(EAX, EDX);
__ testl(EAX, Immediate(kSmiTagMask));
- __ j(ZERO, &two_smis, Assembler::kNearJump);
-
- // Operator is called either if one of the arguments is not Smi or
- // if we hit an overflow in an arithmetic operation.
- __ Bind(&call_operator);
- // Restore arguments on stack, and dispatch to operator, thus preventing
- // deoptimization in case of smi/non-smi operations. At exit we do not
- // know the result is Smi or not.
- // TODO(srdjan): Handle type feedback for both arguments instead of for
- // receiver only, deoptimize if the type changes.
- __ pushl(ECX);
- __ pushl(EDX);
- GenerateBinaryOperatorCall(node->id(),
- node->token_index(),
- node->Name());
- __ jmp(&done);
- __ Bind(&two_smis);
- // Restore left operand. EAX will be 'destroyed', ECX holds the left
- // argument, which may be needed for deoptimization.
+ __ j(NOT_ZERO, deopt_blob->label());
__ movl(EAX, ECX);
}
+ if (node->info() != NULL) {
+ node->info()->set_is_class(&smi_class_);
+ }
switch (kind) {
case Token::kADD: {
__ addl(EAX, EDX);
- __ j(OVERFLOW, overflow_label);
+ __ j(OVERFLOW, deopt_blob->label());
break;
}
case Token::kSUB: {
__ subl(EAX, EDX);
- __ j(OVERFLOW, overflow_label);
+ __ j(OVERFLOW, deopt_blob->label());
break;
}
case Token::kMUL: {
__ SmiUntag(EAX);
__ imull(EAX, EDX);
- __ j(OVERFLOW, overflow_label);
+ __ j(OVERFLOW, deopt_blob->label());
break;
}
case Token::kBIT_AND: {
@@ -975,7 +965,7 @@
case Token::kTRUNCDIV: {
// Handle divide by zero in runtime.
__ cmpl(EDX, Immediate(0));
- __ j(EQUAL, overflow_label);
+ __ j(EQUAL, deopt_blob->label());
// Preserve left & right in case of 'overflow'.
__ pushl(EDX);
__ pushl(ECX);
@@ -991,7 +981,7 @@
// Check the corner case of dividing the 'MIN_SMI' with -1, in which
// case we cannot tag the result.
__ cmpl(EAX, Immediate(0x40000000));
- __ j(EQUAL, overflow_label);
+ __ j(EQUAL, deopt_blob->label());
__ SmiTag(EAX);
break;
}
@@ -1310,7 +1300,7 @@
return;
}
- if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) {
+ if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, smi_class_)) {
GenerateSmiBinaryOp(node);
return;
}
« no previous file with comments | « runtime/vm/compiler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698