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

Unified Diff: runtime/vm/opt_code_generator_ia32.cc

Issue 8995019: More optimizations (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/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 2702)
+++ runtime/vm/opt_code_generator_ia32.cc (working copy)
@@ -630,7 +630,8 @@
}
-// Look only at the first class in all check groups.
+// Look only at the first class in all check groups. Returns true if all
+// receiver classes are 'cls'.
static bool AtIdNodeHasReceiverClass(AstNode* node,
intptr_t id,
const Class& cls) {
@@ -678,22 +679,6 @@
}
-static bool AtIdNodeHasOnlyClass(AstNode* node, intptr_t id, const Class& cls) {
- ASSERT(node != NULL);
- ASSERT(!cls.IsNull());
- const ICData& ic_data = node->ICDataAtId(id);
- if ((ic_data.NumberOfArgumentsChecked() != 1) ||
- (ic_data.NumberOfChecks() != 1)) {
- return false;
- }
- Class& target_cls = Class::Handle();
- Function& target = Function::Handle();
- ic_data.GetOneClassCheckAt(0, &target_cls, &target);
- return target_cls.raw() == cls.raw();
-}
-
-
-
// SHL: Implement with slow case so that it works both with Smi and Mint types.
// Result is in EAX. Mangles ECX, EBX, EDX.
void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) {
@@ -722,10 +707,9 @@
return;
}
ASSERT(node->kind() == Token::kSHL);
- Label done;
- bool shift_generated = false;
if (node->right()->IsLiteralNode() &&
node->right()->AsLiteralNode()->literal().IsSmi()) {
+ Label done;
// Shift count is a Smi literal.
Smi& smi = Smi::Handle();
smi ^= node->right()->AsLiteralNode()->literal().raw();
@@ -746,52 +730,55 @@
__ Bind(&slow_case);
__ pushl(EAX);
__ pushl(Immediate(reinterpret_cast<int32_t>(smi.raw())));
- CodeGenerator::GenerateBinaryOperatorCall(node->id(),
- node->token_index(),
- node->Name());
- shift_generated = true;
+ const int number_of_arguments = 2;
+ const Array& no_optional_argument_names = Array::Handle();
+ GenerateCheckedInstanceCalls(node,
+ node->left(),
+ node->id(),
+ node->token_index(),
+ number_of_arguments,
+ no_optional_argument_names);
+ __ Bind(&done);
+ return;
}
}
- if (!shift_generated) {
- Label slow_case;
- VisitLoadTwo(node->left(), node->right(), EAX, EDX);
- // TODO(srdjan): Better code for count being a Smi literal.
- // EAX: value, EDX: shift amount. Preserve them for slow case.
- // Fast case only if both ar Smi.
- __ movl(EBX, EAX);
- __ orl(EBX, EDX);
- __ testl(EBX, Immediate(kSmiTagMask));
- __ j(NOT_ZERO, &slow_case, Assembler::kNearJump);
- // Check if count too large for handling it inlined.
- __ cmpl(EDX, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
- __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump);
- // Shift amount must be in ECX.
- __ movl(ECX, EDX);
- __ movl(EBX, EAX);
- __ SmiUntag(ECX);
- // Overflow test.
- __ shll(EBX, ECX);
- __ sarl(EBX, ECX);
- __ cmpl(EAX, EBX);
- __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow.
+ Label slow_case, done;
+ VisitLoadTwo(node->left(), node->right(), EAX, EDX);
+ // TODO(srdjan): Better code for count being a Smi literal.
+ // EAX: value, EDX: shift amount. Preserve them for slow case.
+ // Fast case only if both ar Smi.
+ __ movl(EBX, EAX);
+ __ orl(EBX, EDX);
+ __ testl(EBX, Immediate(kSmiTagMask));
+ __ j(NOT_ZERO, &slow_case, Assembler::kNearJump);
+ // Check if count too large for handling it inlined.
+ __ cmpl(EDX, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
+ __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump);
+ // Shift amount must be in ECX.
+ __ movl(ECX, EDX);
+ __ movl(EBX, EAX);
+ __ SmiUntag(ECX);
+ // Overflow test.
+ __ shll(EBX, ECX);
+ __ sarl(EBX, ECX);
+ __ cmpl(EAX, EBX);
+ __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow.
- __ shll(EAX, ECX); // Shift for result now we know there is no overflow.
- // EAX is the correctly tagged Smi.
- __ jmp(&done);
- __ Bind(&slow_case);
- __ pushl(EAX);
- __ pushl(EDX);
- const int number_of_arguments = 2;
- const Array& no_optional_argument_names = Array::Handle();
- GenerateCheckedInstanceCalls(node,
- node->left(),
- node->id(),
- node->token_index(),
- number_of_arguments,
- no_optional_argument_names);
- shift_generated = true;
- }
+ __ shll(EAX, ECX); // Shift for result now we know there is no overflow.
+ // EAX is the correctly tagged Smi.
+ __ jmp(&done);
+ __ Bind(&slow_case);
+ __ pushl(EAX);
+ __ pushl(EDX);
+ const int number_of_arguments = 2;
+ const Array& no_optional_argument_names = Array::Handle();
+ GenerateCheckedInstanceCalls(node,
+ node->left(),
+ node->id(),
+ node->token_index(),
+ number_of_arguments,
+ no_optional_argument_names);
__ Bind(&done);
}
@@ -882,6 +869,8 @@
// Handles only Smi & Smi.
+// TODO(srdjan): Certain operations always overflow, and thus cause
+// deoptimization. We need to mark those places and handle them.
void OptimizingCodeGenerator::GenerateSmiBinaryOp(BinaryOpNode* node) {
const char* kOptMessage = "Inlines BinaryOp for Smi";
Label done;
@@ -1046,7 +1035,14 @@
__ Bind(&slow_case);
__ pushl(EAX);
__ pushl(EDX);
- GenerateBinaryOperatorCall(node->id(), node->token_index(), node->Name());
+ const int number_of_arguments = 2;
+ const Array& no_optional_argument_names = Array::Handle();
+ GenerateCheckedInstanceCalls(node,
+ node->left(),
+ node->id(),
+ node->token_index(),
+ number_of_arguments,
+ no_optional_argument_names);
__ Bind(&done);
if (CodeGenerator::IsResultNeeded(node)) {
__ pushl(EAX);
@@ -1090,14 +1086,16 @@
}
-// TODO(srdjan): Detect double/Smi operation and remove extra code to
-// always check for Smi on the right hand side.
// Result of the computation is a newly allocated double object or
// a temporary object if the parent node specifies a CodeGenInfo for this node
// and therefore knows how to handle a temporary. A temporary object cannot
// be used for long living values (e.g., the ones stored on stack or into other
// objects).
-void OptimizingCodeGenerator::GenerateDoubleBinaryOp(BinaryOpNode* node) {
+// Implement for combinations: Double/Double, Double/Smi, Smi/Double, as
+// the result is always double.
+// TODO(srdjan): Implement Smi/Smi for kDIV (result also double).
+void OptimizingCodeGenerator::GenerateDoubleBinaryOp(BinaryOpNode* node,
+ bool receiver_can_be_smi) {
const char* kOptMessage = "Inlines BinaryOp for Doubles";
const Token::Kind kind = node->kind();
if ((kind == Token::kADD) ||
@@ -1139,9 +1137,10 @@
Double::ZoneHandle(Double::New(0.0, Heap::kOld));
__ LoadObject(result_register, double_object);
}
- Label is_smi, extract_left;
+
DeoptimizationBlob* deopt_blob = NULL;
Label* deopt_lbl = NULL;
+ // Deoptimization can only occur if one of arguments is not double.
if (!left_info.IsClass(double_class_) ||
!right_info.IsClass(double_class_)) {
deopt_blob = AddDeoptimizationBlob(node,
@@ -1151,25 +1150,43 @@
deopt_lbl = deopt_blob->label();
}
+ if (receiver_can_be_smi) {
+ // Only deoptimize if both argument are Smi.
+ __ movl(kTempRegister, kLeftRegister);
+ __ orl(kTempRegister, kRightRegister);
+ __ testl(kTempRegister, Immediate(kSmiTagMask));
+ __ j(ZERO, deopt_lbl);
+ }
+
bool nodes_of_same_type = AreNodesOfSameType(node->left(), node->right());
if (!left_info.IsClass(double_class_)) {
- CheckIfDoubleOrSmi(kLeftRegister, kTempRegister, deopt_lbl, deopt_lbl);
- // Fall through for double. Jump to 'deopt' if not double.
+ Label is_smi, done;
+ CheckIfDoubleOrSmi(kLeftRegister, kTempRegister, &is_smi, deopt_lbl);
+ // Fall through for double. Jump to 'is_smi' if double, jump to
+ // 'deopt' if neither smi nor double.
+ __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset()));
+ __ jmp(&done);
+ __ Bind(&is_smi);
+ __ SmiUntag(kLeftRegister);
+ __ cvtsi2sd(XMM0, kLeftRegister);
+ __ Bind(&done);
+ } else {
+ __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset()));
}
if (!right_info.IsClass(double_class_) && !nodes_of_same_type) {
+ Label is_smi, done;
CheckIfDoubleOrSmi(kRightRegister, kTempRegister, &is_smi, deopt_lbl);
// Fall through for double. Jump to 'is_smi' if double, jump to
// 'deopt' if neither smi nor double.
__ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset()));
- __ jmp(&extract_left);
+ __ jmp(&done);
__ Bind(&is_smi);
__ SmiUntag(kRightRegister);
__ cvtsi2sd(XMM1, kRightRegister);
- __ Bind(&extract_left);
+ __ Bind(&done);
} else {
__ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset()));
}
- __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset()));
switch (kind) {
case Token::kADD: __ addsd(XMM0, XMM1); break;
@@ -1306,10 +1323,17 @@
}
if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) {
- GenerateDoubleBinaryOp(node);
+ const bool receiver_can_be_smi = false;
+ GenerateDoubleBinaryOp(node, receiver_can_be_smi);
return;
}
+ if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, double_class_)) {
+ const bool receiver_can_be_smi = true;
+ GenerateDoubleBinaryOp(node, receiver_can_be_smi);
+ return;
+ }
+
const Class& mint_class =
Class::Handle(Isolate::Current()->object_store()->mint_class());
if (AtIdNodeHasReceiverClass(node, node->id(), mint_class)) {
@@ -2324,13 +2348,14 @@
Class::ZoneHandle(object_store->array_class());
const Class& immutable_object_array_class =
Class::ZoneHandle(object_store->immutable_array_class());
- if (AtIdNodeHasOnlyClass(node, node->id(), object_array_class) ||
- AtIdNodeHasOnlyClass(node, node->id(), immutable_object_array_class)) {
+ if (AtIdNodeHasReceiverClass(node, node->id(), object_array_class) ||
+ AtIdNodeHasReceiverClass(node, node->id(),
+ immutable_object_array_class)) {
VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX);
DeoptimizationBlob* deopt_blob =
AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray);
const Class& test_class =
- AtIdNodeHasOnlyClass(node, node->id(), object_array_class) ?
+ AtIdNodeHasReceiverClass(node, node->id(), object_array_class) ?
object_array_class : immutable_object_array_class;
// Type checks of array.
__ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi.
@@ -2360,7 +2385,7 @@
const Class& growable_array_class = Class::ZoneHandle(
Library::Handle(Library::CoreImplLibrary()).
LookupClass(growable_object_array_class_name));
- if (AtIdNodeHasOnlyClass(node, node->id(), growable_array_class)) {
+ if (AtIdNodeHasReceiverClass(node, node->id(), growable_array_class)) {
const String& growable_array_length_field_name =
String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName));
const String& growable_array_array_field_name =
@@ -2418,7 +2443,7 @@
__ jmp(deopt_blob->label());
return;
}
- if (AtIdNodeHasOnlyClass(node, node->id(), object_array_class)) {
+ if (AtIdNodeHasReceiverClass(node, node->id(), object_array_class)) {
VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
DeoptimizationBlob* deopt_blob =
AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed);
@@ -2811,7 +2836,7 @@
Recognizer::KindToCString(recognized));
}
if ((recognized == Recognizer::kIntegerToDouble) &&
- AtIdNodeHasOnlyClass(node, node->id(), smi_class_)) {
+ AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) {
// TODO(srdjan): Check if we could use temporary double instead of
// allocating a new object every time.
const Code& stub =
@@ -2831,7 +2856,7 @@
}
if ((recognized == Recognizer::kDoubleToDouble) &&
- AtIdNodeHasOnlyClass(node, node->id(), double_class_)) {
+ AtIdNodeHasReceiverClass(node, node->id(), double_class_)) {
DeoptimizationBlob* deopt_blob =
AddDeoptimizationBlob(node, EAX, kDeoptDoubleToDouble);
__ popl(EAX);
@@ -2985,7 +3010,7 @@
}
if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) {
- if (AtIdNodeHasOnlyClass(node, node->id(), smi_class_)) {
+ if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) {
const ICData& ic_data = node->ICDataAtId(node->id());
ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
GenerateSmiUnaryOp(node);
« 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