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

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

Issue 79653002: Merge TRUNCDIV and MOD into one instruction. Icorporated feedback from CL https://codereview.chromi… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | tests/language/arithmetic_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 4024 matching lines...) Expand 10 before | Expand all | Expand 10 after
4035 __ jmp(&skip_call, Assembler::kNearJump); 4035 __ jmp(&skip_call, Assembler::kNearJump);
4036 } 4036 }
4037 __ Bind(&do_call); 4037 __ Bind(&do_call);
4038 __ CallRuntime(TargetFunction(), InputCount()); 4038 __ CallRuntime(TargetFunction(), InputCount());
4039 __ movaps(locs()->out().fpu_reg(), XMM0); 4039 __ movaps(locs()->out().fpu_reg(), XMM0);
4040 __ Bind(&skip_call); 4040 __ Bind(&skip_call);
4041 __ leave(); 4041 __ leave();
4042 } 4042 }
4043 4043
4044 4044
4045 LocationSummary* MergedMathInstr::MakeLocationSummary() const {
4046 if (kind() == MergedMathInstr::kTruncDivMod) {
4047 const intptr_t kNumInputs = 2;
4048 const intptr_t kNumTemps = 1;
4049 LocationSummary* summary =
4050 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
4051 // Both inputs must be writable because they will be untagged.
4052 summary->set_in(0, Location::RegisterLocation(RAX));
4053 summary->set_in(1, Location::WritableRegister());
4054 summary->set_out(Location::RequiresRegister());
4055 // Will be used for sign extension and division.
4056 summary->set_temp(0, Location::RegisterLocation(RDX));
4057 return summary;
4058 }
4059 UNIMPLEMENTED();
4060 return NULL;
4061 }
4062
4063
4064 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4065 Label* deopt = NULL;
4066 if (CanDeoptimize()) {
4067 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
4068 }
4069 if (kind() == MergedMathInstr::kTruncDivMod) {
4070 Register left = locs()->in(0).reg();
4071 Register right = locs()->in(1).reg();
4072 Register result = locs()->out().reg();
4073 Label not_32bit, done;
4074 Register temp = locs()->temp(0).reg();
4075 ASSERT(left == RAX);
4076 ASSERT((right != RDX) && (right != RAX));
4077 ASSERT(temp == RDX);
4078 ASSERT((result != RDX) && (result != RAX));
4079 // Handle divide by zero in runtime.
4080 __ testq(right, right);
4081 __ j(ZERO, deopt);
4082 // Check if both operands fit into 32bits as idiv with 64bit operands
4083 // requires twice as many cycles and has much higher latency.
4084 // We are checking this before untagging them to avoid corner case
4085 // dividing INT_MAX by -1 that raises exception because quotient is
4086 // too large for 32bit register.
4087 __ movsxd(temp, left);
4088 __ cmpq(temp, left);
4089 __ j(NOT_EQUAL, &not_32bit);
4090 __ movsxd(temp, right);
4091 __ cmpq(temp, right);
4092 __ j(NOT_EQUAL, &not_32bit);
4093
4094 // Both operands are 31bit smis. Divide using 32bit idiv.
4095 __ SmiUntag(left);
4096 __ SmiUntag(right);
4097 __ cdq();
4098 __ idivl(right);
4099 __ movsxd(RAX, RAX);
4100 __ movsxd(RDX, RDX);
4101 __ jmp(&done);
4102
4103 // Divide using 64bit idiv.
4104 __ Bind(&not_32bit);
4105 __ SmiUntag(left);
4106 __ SmiUntag(right);
4107 __ cqo(); // Sign extend RAX -> RDX:RAX.
4108 __ idivq(right); // RAX: quotient, RDX: remainder.
4109 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
4110 // case we cannot tag the result.
4111 __ CompareImmediate(RAX, Immediate(0x4000000000000000), PP);
4112 __ j(EQUAL, deopt);
4113 __ Bind(&done);
4114
4115 // Modulo correction (RDX).
4116 // res = left % right;
4117 // if (res < 0) {
4118 // if (right < 0) {
4119 // res = res - right;
4120 // } else {
4121 // res = res + right;
4122 // }
4123 // }
4124 Label subtract, all_done;
4125 __ cmpq(RDX, Immediate(0));
4126 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
4127 // Result is negative, adjust it.
4128 __ cmpq(right, Immediate(0));
4129 __ j(LESS, &subtract, Assembler::kNearJump);
4130 __ addq(RDX, right);
4131 __ jmp(&all_done, Assembler::kNearJump);
4132 __ Bind(&subtract);
4133 __ subq(RDX, right);
4134 __ Bind(&all_done);
4135 __ SmiTag(result);
4136
4137 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP);
4138 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid);
4139 Address trunc_div_address(
4140 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid,
4141 index_scale,
4142 result,
4143 0));
4144 Address mod_address(
4145 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid,
4146 index_scale,
4147 result,
4148 1));
4149 __ SmiTag(RAX);
4150 __ SmiTag(RDX);
4151 __ StoreIntoObjectNoBarrier(result, trunc_div_address, RAX);
4152 __ StoreIntoObjectNoBarrier(result, mod_address, RDX);
4153 // FLAG_throw_on_javascript_int_overflow: not needed.
4154 // Note that the result of an integer division/modulo of two
4155 // in-range arguments, cannot create out-of-range result.
4156 return;
4157 }
4158 UNIMPLEMENTED();
4159 }
4160
4161
4045 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { 4162 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
4046 return MakeCallSummary(); 4163 return MakeCallSummary();
4047 } 4164 }
4048 4165
4049 4166
4050 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4167 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4051 Label* deopt = compiler->AddDeoptStub(deopt_id(), 4168 Label* deopt = compiler->AddDeoptStub(deopt_id(),
4052 kDeoptPolymorphicInstanceCallTestFail); 4169 kDeoptPolymorphicInstanceCallTestFail);
4053 if (ic_data().NumberOfChecks() == 0) { 4170 if (ic_data().NumberOfChecks() == 0) {
4054 __ jmp(deopt); 4171 __ jmp(deopt);
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
4572 PcDescriptors::kOther, 4689 PcDescriptors::kOther,
4573 locs()); 4690 locs());
4574 __ Drop(2); // Discard type arguments and receiver. 4691 __ Drop(2); // Discard type arguments and receiver.
4575 } 4692 }
4576 4693
4577 } // namespace dart 4694 } // namespace dart
4578 4695
4579 #undef __ 4696 #undef __
4580 4697
4581 #endif // defined TARGET_ARCH_X64 4698 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_mips.cc ('k') | tests/language/arithmetic_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698