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

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

Issue 10702195: Equality compare should record two arguments in IC data. INline double equality comparison. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/object.h » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 // We should never return here. 193 // We should never return here.
194 __ int3(); 194 __ int3();
195 195
196 __ Bind(&done); 196 __ Bind(&done);
197 ASSERT(obj == result); 197 ASSERT(obj == result);
198 } 198 }
199 199
200 200
201 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { 201 LocationSummary* EqualityCompareComp::MakeLocationSummary() const {
202 const intptr_t kNumInputs = 2; 202 const intptr_t kNumInputs = 2;
203 if (HasICData() && 203 if (receiver_class_id() != kObject) {
204 (ic_data()->NumberOfChecks() == 1) && 204 ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble));
205 (ic_data()->GetReceiverClassIdAt(0) == kSmi)) { 205 // No temporary register needed for double comparison.
206 const intptr_t kNumTemps = 1; 206 const intptr_t kNumTemps = (receiver_class_id() == kSmi) ? 1 : 0;
207 LocationSummary* locs = new LocationSummary(kNumInputs, 207 LocationSummary* locs = new LocationSummary(kNumInputs,
208 kNumTemps, 208 kNumTemps,
209 LocationSummary::kNoCall); 209 LocationSummary::kNoCall);
210 locs->set_in(0, Location::RequiresRegister()); 210 locs->set_in(0, Location::RequiresRegister());
211 locs->set_in(1, Location::RequiresRegister()); 211 locs->set_in(1, Location::RequiresRegister());
212 locs->set_temp(0, Location::RequiresRegister()); 212 if (receiver_class_id() == kSmi) {
213 locs->set_temp(0, Location::RequiresRegister());
214 }
213 if (!is_fused_with_branch()) { 215 if (!is_fused_with_branch()) {
214 locs->set_out(Location::RequiresRegister()); 216 locs->set_out(Location::RequiresRegister());
215 } 217 }
216 return locs; 218 return locs;
217 } 219 }
218 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 220 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
219 const intptr_t kNumTemps = 1; 221 const intptr_t kNumTemps = 1;
220 LocationSummary* locs = new LocationSummary(kNumInputs, 222 LocationSummary* locs = new LocationSummary(kNumInputs,
221 kNumTemps, 223 kNumTemps,
222 LocationSummary::kCall); 224 LocationSummary::kCall);
(...skipping 11 matching lines...) Expand all
234 LocationSummary::kCall); 236 LocationSummary::kCall);
235 locs->set_in(0, Location::RequiresRegister()); 237 locs->set_in(0, Location::RequiresRegister());
236 locs->set_in(1, Location::RequiresRegister()); 238 locs->set_in(1, Location::RequiresRegister());
237 if (!is_fused_with_branch()) { 239 if (!is_fused_with_branch()) {
238 locs->set_out(Location::RegisterLocation(RAX)); 240 locs->set_out(Location::RegisterLocation(RAX));
239 } 241 }
240 return locs; 242 return locs;
241 } 243 }
242 244
243 245
246 // Optional integer arguments can often be null. Null is not collected
247 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well?
244 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, 248 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler,
245 EqualityCompareComp* comp) { 249 EqualityCompareComp* comp) {
246 Register left = comp->locs()->in(0).reg(); 250 Register left = comp->locs()->in(0).reg();
247 Register right = comp->locs()->in(1).reg(); 251 Register right = comp->locs()->in(1).reg();
248 Register temp = comp->locs()->temp(0).reg(); 252 Register temp = comp->locs()->temp(0).reg();
249 Label* deopt = compiler->AddDeoptStub(comp->cid(), 253 Label* deopt = compiler->AddDeoptStub(comp->cid(),
250 comp->token_pos(), 254 comp->token_pos(),
251 comp->try_index(), 255 comp->try_index(),
252 kDeoptSmiCompareSmis, 256 kDeoptSmiCompareSmi,
253 left, 257 left,
254 right); 258 right);
255 // TODO(srdjan): Should we always include NULL test (common case)?
256 __ movq(temp, left); 259 __ movq(temp, left);
257 __ orq(temp, right); 260 __ orq(temp, right);
258 __ testq(temp, Immediate(kSmiTagMask)); 261 __ testq(temp, Immediate(kSmiTagMask));
259 __ j(NOT_ZERO, deopt); 262 __ j(NOT_ZERO, deopt);
260 __ cmpq(left, right); 263 __ cmpq(left, right);
261 if (comp->is_fused_with_branch()) { 264 if (comp->is_fused_with_branch()) {
262 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); 265 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
263 } else { 266 } else {
264 Register result = comp->locs()->out().reg(); 267 Register result = comp->locs()->out().reg();
265 Label load_true, done; 268 Label load_true, done;
266 __ j(EQUAL, &load_true, Assembler::kNearJump); 269 __ j(EQUAL, &load_true, Assembler::kNearJump);
267 __ LoadObject(result, compiler->bool_false()); 270 __ LoadObject(result, compiler->bool_false());
268 __ jmp(&done, Assembler::kNearJump); 271 __ jmp(&done, Assembler::kNearJump);
269 __ Bind(&load_true); 272 __ Bind(&load_true);
270 __ LoadObject(result, compiler->bool_true()); 273 __ LoadObject(result, compiler->bool_true());
271 __ Bind(&done); 274 __ Bind(&done);
272 } 275 }
273 } 276 }
274 277
275 278
279 // TODO(srdjan): Add support for mixed Smi/Double equality
280 // (see LoadDoubleOrSmiToXmm).
281 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler,
282 EqualityCompareComp* comp) {
283 Register left = comp->locs()->in(0).reg();
284 Register right = comp->locs()->in(1).reg();
285 Label* deopt = compiler->AddDeoptStub(comp->cid(),
286 comp->token_pos(),
287 comp->try_index(),
288 kDeoptDoubleCompareDouble,
289 left,
290 right);
291 __ CompareClassId(left, kDouble);
292 __ j(NOT_EQUAL, deopt);
293 __ CompareClassId(right, kDouble);
294 __ j(NOT_EQUAL, deopt);
295 __ movsd(XMM0, FieldAddress(left, Double::value_offset()));
296 __ movsd(XMM1, FieldAddress(right, Double::value_offset()));
297 if (comp->is_fused_with_branch()) {
298 compiler->EmitDoubleCompareBranch(
299 EQUAL, XMM0, XMM1, comp->fused_with_branch());
300 } else {
301 compiler->EmitDoubleCompareBool(
302 EQUAL, XMM0, XMM1, comp->locs()->out().reg());
303 }
304 }
305
306
276 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 307 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
277 EqualityCompareComp* comp) { 308 EqualityCompareComp* comp) {
278 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 309 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
279 comp->cid(), 310 comp->cid(),
280 comp->token_pos(), 311 comp->token_pos(),
281 comp->try_index()); 312 comp->try_index());
282 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); 313 const String& operator_name = String::ZoneHandle(String::NewSymbol("=="));
283 const int kNumberOfArguments = 2; 314 const int kNumberOfArguments = 2;
284 const Array& kNoArgumentNames = Array::Handle(); 315 const Array& kNoArgumentNames = Array::Handle();
285 const int kNumArgumentsChecked = 2; 316 const int kNumArgumentsChecked = 2;
(...skipping 12 matching lines...) Expand all
298 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); 329 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
299 } 330 }
300 } 331 }
301 332
302 333
303 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 334 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
304 EqualityCompareComp* comp, 335 EqualityCompareComp* comp,
305 Register left, 336 Register left,
306 Register right) { 337 Register right) {
307 ASSERT(comp->HasICData()); 338 ASSERT(comp->HasICData());
308 const ICData& ic_data = *comp->ic_data(); 339 const ICData& ic_data = ICData::Handle(comp->ic_data()->AsUnaryClassChecks());
309 ASSERT(ic_data.NumberOfChecks() > 0); 340 ASSERT(ic_data.NumberOfChecks() > 0);
310 ASSERT(ic_data.num_args_tested() == 1); 341 ASSERT(ic_data.num_args_tested() == 1);
311 Label* deopt = compiler->AddDeoptStub(comp->cid(), 342 Label* deopt = compiler->AddDeoptStub(comp->cid(),
312 comp->token_pos(), 343 comp->token_pos(),
313 comp->try_index(), 344 comp->try_index(),
314 kDeoptEquality); 345 kDeoptEquality);
315 __ testq(left, Immediate(kSmiTagMask)); 346 __ testq(left, Immediate(kSmiTagMask));
316 Register temp = comp->locs()->temp(0).reg(); 347 Register temp = comp->locs()->temp(0).reg();
317 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { 348 if (ic_data.GetReceiverClassIdAt(0) == kSmi) {
318 Label done, load_class_id; 349 Label done, load_class_id;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) { 439 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) {
409 EmitEqualityAsPolymorphicCall(compiler, comp, left, right); 440 EmitEqualityAsPolymorphicCall(compiler, comp, left, right);
410 } else { 441 } else {
411 EmitEqualityAsInstanceCall(compiler, comp); 442 EmitEqualityAsInstanceCall(compiler, comp);
412 } 443 }
413 __ Bind(&done); 444 __ Bind(&done);
414 } 445 }
415 446
416 447
417 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 448 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
418 if (HasICData() && 449 if (receiver_class_id() == kSmi) {
419 (ic_data()->NumberOfChecks() == 1) &&
420 (ic_data()->GetReceiverClassIdAt(0) == kSmi)) {
421 EmitSmiEqualityCompare(compiler, this); 450 EmitSmiEqualityCompare(compiler, this);
422 return; 451 return;
423 } 452 }
453 if (receiver_class_id() == kDouble) {
454 EmitDoubleEqualityCompare(compiler, this);
455 return;
456 }
424 EmitGenericEqualityCompare(compiler, this); 457 EmitGenericEqualityCompare(compiler, this);
425 } 458 }
426 459
427 460
428 LocationSummary* RelationalOpComp::MakeLocationSummary() const { 461 LocationSummary* RelationalOpComp::MakeLocationSummary() const {
429 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { 462 if (operands_class_id() == kSmi || operands_class_id() == kDouble) {
430 const intptr_t kNumInputs = 2; 463 const intptr_t kNumInputs = 2;
431 const intptr_t kNumTemps = 1; 464 const intptr_t kNumTemps = 1;
432 LocationSummary* summary = new LocationSummary(kNumInputs, 465 LocationSummary* summary = new LocationSummary(kNumInputs,
433 kNumTemps, 466 kNumTemps,
(...skipping 28 matching lines...) Expand all
462 495
463 496
464 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, 497 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler,
465 RelationalOpComp* comp) { 498 RelationalOpComp* comp) {
466 Register left = comp->locs()->in(0).reg(); 499 Register left = comp->locs()->in(0).reg();
467 Register right = comp->locs()->in(1).reg(); 500 Register right = comp->locs()->in(1).reg();
468 Register temp = comp->locs()->temp(0).reg(); 501 Register temp = comp->locs()->temp(0).reg();
469 Label* deopt = compiler->AddDeoptStub(comp->cid(), 502 Label* deopt = compiler->AddDeoptStub(comp->cid(),
470 comp->token_pos(), 503 comp->token_pos(),
471 comp->try_index(), 504 comp->try_index(),
472 kDeoptSmiCompareSmis, 505 kDeoptSmiCompareSmi,
473 left, 506 left,
474 right); 507 right);
475 __ movq(temp, left); 508 __ movq(temp, left);
476 __ orq(temp, right); 509 __ orq(temp, right);
477 __ testq(temp, Immediate(kSmiTagMask)); 510 __ testq(temp, Immediate(kSmiTagMask));
478 __ j(NOT_ZERO, deopt); 511 __ j(NOT_ZERO, deopt);
479 512
480 Condition true_condition = TokenKindToSmiCondition(comp->kind()); 513 Condition true_condition = TokenKindToSmiCondition(comp->kind());
481 __ cmpq(left, right); 514 __ cmpq(left, right);
482 515
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 Label* deopt = compiler->AddDeoptStub(comp->cid(), 551 Label* deopt = compiler->AddDeoptStub(comp->cid(),
519 comp->token_pos(), 552 comp->token_pos(),
520 comp->try_index(), 553 comp->try_index(),
521 kDeoptDoubleComparison, 554 kDeoptDoubleComparison,
522 left, 555 left,
523 right); 556 right);
524 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 557 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
525 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 558 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
526 559
527 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); 560 Condition true_condition = TokenKindToDoubleCondition(comp->kind());
528 __ comisd(XMM0, XMM1);
529
530 if (comp->is_fused_with_branch()) { 561 if (comp->is_fused_with_branch()) {
531 BranchInstr* branch = comp->fused_with_branch(); 562 compiler->EmitDoubleCompareBranch(
532 BlockEntryInstr* nan_result = branch->is_negated() ? 563 true_condition, XMM0, XMM1, comp->fused_with_branch());
533 branch->true_successor() : branch->false_successor();
534 __ j(PARITY_EVEN, compiler->GetBlockLabel(nan_result));
535 branch->EmitBranchOnCondition(compiler, true_condition);
536 } else { 564 } else {
537 Register result = comp->locs()->out().reg(); 565 compiler->EmitDoubleCompareBool(
538 Label is_false, is_true, done; 566 true_condition, XMM0, XMM1, comp->locs()->out().reg());
539 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
540 __ j(true_condition, &is_true, Assembler::kNearJump);
541 __ Bind(&is_false);
542 __ LoadObject(result, compiler->bool_false());
543 __ jmp(&done);
544 __ Bind(&is_true);
545 __ LoadObject(result, compiler->bool_true());
546 __ Bind(&done);
547 } 567 }
548 } 568 }
549 569
550 570
551 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 571 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
552 if (operands_class_id() == kSmi) { 572 if (operands_class_id() == kSmi) {
553 EmitSmiRelationalOp(compiler, this); 573 EmitSmiRelationalOp(compiler, this);
554 return; 574 return;
555 } 575 }
556 if (operands_class_id() == kDouble) { 576 if (operands_class_id() == kDouble) {
(...skipping 1402 matching lines...) Expand 10 before | Expand all | Expand 10 after
1959 } 1979 }
1960 __ Bind(&done); 1980 __ Bind(&done);
1961 } 1981 }
1962 1982
1963 1983
1964 } // namespace dart 1984 } // namespace dart
1965 1985
1966 #undef __ 1986 #undef __
1967 1987
1968 #endif // defined TARGET_ARCH_X64 1988 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698