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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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.h ('k') | runtime/vm/intermediate_language_x64.cc » ('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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 // We should never return here. 185 // We should never return here.
186 __ int3(); 186 __ int3();
187 187
188 __ Bind(&done); 188 __ Bind(&done);
189 ASSERT(obj == result); 189 ASSERT(obj == result);
190 } 190 }
191 191
192 192
193 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { 193 LocationSummary* EqualityCompareComp::MakeLocationSummary() const {
194 const intptr_t kNumInputs = 2; 194 const intptr_t kNumInputs = 2;
195 if (HasICData() && 195 if (receiver_class_id() != kObject) {
196 (ic_data()->NumberOfChecks() == 1) && 196 ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble));
197 (ic_data()->GetReceiverClassIdAt(0) == kSmi)) {
198 const intptr_t kNumTemps = 1; 197 const intptr_t kNumTemps = 1;
199 LocationSummary* locs = new LocationSummary(kNumInputs, 198 LocationSummary* locs = new LocationSummary(kNumInputs,
200 kNumTemps, 199 kNumTemps,
201 LocationSummary::kNoCall); 200 LocationSummary::kNoCall);
202 locs->set_in(0, Location::RequiresRegister()); 201 locs->set_in(0, Location::RequiresRegister());
203 locs->set_in(1, Location::RequiresRegister()); 202 locs->set_in(1, Location::RequiresRegister());
204 locs->set_temp(0, Location::RequiresRegister()); 203 locs->set_temp(0, Location::RequiresRegister());
205 if (!is_fused_with_branch()) { 204 if (!is_fused_with_branch()) {
206 locs->set_out(Location::RequiresRegister()); 205 locs->set_out(Location::RequiresRegister());
207 } 206 }
(...skipping 18 matching lines...) Expand all
226 LocationSummary::kCall); 225 LocationSummary::kCall);
227 locs->set_in(0, Location::RequiresRegister()); 226 locs->set_in(0, Location::RequiresRegister());
228 locs->set_in(1, Location::RequiresRegister()); 227 locs->set_in(1, Location::RequiresRegister());
229 if (!is_fused_with_branch()) { 228 if (!is_fused_with_branch()) {
230 locs->set_out(Location::RegisterLocation(EAX)); 229 locs->set_out(Location::RegisterLocation(EAX));
231 } 230 }
232 return locs; 231 return locs;
233 } 232 }
234 233
235 234
235 // Optional integer arguments can often be null. Null is not collected
236 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well?
236 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, 237 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler,
237 EqualityCompareComp* comp) { 238 EqualityCompareComp* comp) {
238 Register left = comp->locs()->in(0).reg(); 239 Register left = comp->locs()->in(0).reg();
239 Register right = comp->locs()->in(1).reg(); 240 Register right = comp->locs()->in(1).reg();
240 Register temp = comp->locs()->temp(0).reg(); 241 Register temp = comp->locs()->temp(0).reg();
241 Label* deopt = compiler->AddDeoptStub(comp->cid(), 242 Label* deopt = compiler->AddDeoptStub(comp->cid(),
242 comp->token_pos(), 243 comp->token_pos(),
243 comp->try_index(), 244 comp->try_index(),
244 kDeoptSmiCompareSmis, 245 kDeoptSmiCompareSmi,
245 left, 246 left,
246 right); 247 right);
247 // TODO(srdjan): Should we always include NULL test (common case)?
248 __ movl(temp, left); 248 __ movl(temp, left);
249 __ orl(temp, right); 249 __ orl(temp, right);
250 __ testl(temp, Immediate(kSmiTagMask)); 250 __ testl(temp, Immediate(kSmiTagMask));
251 __ j(NOT_ZERO, deopt); 251 __ j(NOT_ZERO, deopt);
252 __ cmpl(left, right); 252 __ cmpl(left, right);
253 if (comp->is_fused_with_branch()) { 253 if (comp->is_fused_with_branch()) {
254 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); 254 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
255 } else { 255 } else {
256 Register result = comp->locs()->out().reg(); 256 Register result = comp->locs()->out().reg();
257 Label load_true, done; 257 Label load_true, done;
258 __ j(EQUAL, &load_true, Assembler::kNearJump); 258 __ j(EQUAL, &load_true, Assembler::kNearJump);
259 __ LoadObject(result, compiler->bool_false()); 259 __ LoadObject(result, compiler->bool_false());
260 __ jmp(&done, Assembler::kNearJump); 260 __ jmp(&done, Assembler::kNearJump);
261 __ Bind(&load_true); 261 __ Bind(&load_true);
262 __ LoadObject(result, compiler->bool_true()); 262 __ LoadObject(result, compiler->bool_true());
263 __ Bind(&done); 263 __ Bind(&done);
264 } 264 }
265 } 265 }
266 266
267 267
268 // TODO(srdjan): Add support for mixed Smi/Double equality
269 // (see LoadDoubleOrSmiToXmm).
270 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler,
271 EqualityCompareComp* comp) {
272 Register left = comp->locs()->in(0).reg();
273 Register right = comp->locs()->in(1).reg();
274 Register temp = comp->locs()->temp(0).reg();
275 Label* deopt = compiler->AddDeoptStub(comp->cid(),
276 comp->token_pos(),
277 comp->try_index(),
278 kDeoptDoubleCompareDouble,
279 left,
280 right);
281 Label done, is_false, is_true;
282 __ CompareClassId(left, kDouble, temp);
283 __ j(NOT_EQUAL, deopt);
284 __ CompareClassId(right, kDouble, temp);
285 __ j(NOT_EQUAL, deopt);
286 __ movsd(XMM0, FieldAddress(left, Double::value_offset()));
287 __ movsd(XMM1, FieldAddress(right, Double::value_offset()));
288 if (comp->is_fused_with_branch()) {
289 compiler->EmitDoubleCompareBranch(
290 EQUAL, XMM0, XMM1, comp->fused_with_branch());
291 } else {
292 compiler->EmitDoubleCompareBool(
293 EQUAL, XMM0, XMM1, comp->locs()->out().reg());
294 }
295 }
296
297
268 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 298 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
269 EqualityCompareComp* comp) { 299 EqualityCompareComp* comp) {
270 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 300 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
271 comp->cid(), 301 comp->cid(),
272 comp->token_pos(), 302 comp->token_pos(),
273 comp->try_index()); 303 comp->try_index());
274 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); 304 const String& operator_name = String::ZoneHandle(String::NewSymbol("=="));
275 const int kNumberOfArguments = 2; 305 const int kNumberOfArguments = 2;
276 const Array& kNoArgumentNames = Array::Handle(); 306 const Array& kNoArgumentNames = Array::Handle();
277 const int kNumArgumentsChecked = 2; 307 const int kNumArgumentsChecked = 2;
(...skipping 12 matching lines...) Expand all
290 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); 320 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL);
291 } 321 }
292 } 322 }
293 323
294 324
295 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 325 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
296 EqualityCompareComp* comp, 326 EqualityCompareComp* comp,
297 Register left, 327 Register left,
298 Register right) { 328 Register right) {
299 ASSERT(comp->HasICData()); 329 ASSERT(comp->HasICData());
300 const ICData& ic_data = *comp->ic_data(); 330 const ICData& ic_data = ICData::Handle(comp->ic_data()->AsUnaryClassChecks());
301 ASSERT(ic_data.NumberOfChecks() > 0); 331 ASSERT(ic_data.NumberOfChecks() > 0);
302 ASSERT(ic_data.num_args_tested() == 1); 332 ASSERT(ic_data.num_args_tested() == 1);
303 Label* deopt = compiler->AddDeoptStub(comp->cid(), 333 Label* deopt = compiler->AddDeoptStub(comp->cid(),
304 comp->token_pos(), 334 comp->token_pos(),
305 comp->try_index(), 335 comp->try_index(),
306 kDeoptEquality); 336 kDeoptEquality);
307 __ testl(left, Immediate(kSmiTagMask)); 337 __ testl(left, Immediate(kSmiTagMask));
308 Register temp = comp->locs()->temp(0).reg(); 338 Register temp = comp->locs()->temp(0).reg();
309 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { 339 if (ic_data.GetReceiverClassIdAt(0) == kSmi) {
310 Label done, load_class_id; 340 Label done, load_class_id;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) { 430 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() > 0)) {
401 EmitEqualityAsPolymorphicCall(compiler, comp, left, right); 431 EmitEqualityAsPolymorphicCall(compiler, comp, left, right);
402 } else { 432 } else {
403 EmitEqualityAsInstanceCall(compiler, comp); 433 EmitEqualityAsInstanceCall(compiler, comp);
404 } 434 }
405 __ Bind(&done); 435 __ Bind(&done);
406 } 436 }
407 437
408 438
409 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 439 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
410 if (HasICData() && 440 if (receiver_class_id() == kSmi) {
411 (ic_data()->NumberOfChecks() == 1) &&
412 (ic_data()->GetReceiverClassIdAt(0) == kSmi)) {
413 EmitSmiEqualityCompare(compiler, this); 441 EmitSmiEqualityCompare(compiler, this);
414 return; 442 return;
415 } 443 }
444 if (receiver_class_id() == kDouble) {
445 EmitDoubleEqualityCompare(compiler, this);
446 return;
447 }
416 EmitGenericEqualityCompare(compiler, this); 448 EmitGenericEqualityCompare(compiler, this);
417 } 449 }
418 450
419 451
420 LocationSummary* RelationalOpComp::MakeLocationSummary() const { 452 LocationSummary* RelationalOpComp::MakeLocationSummary() const {
421 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) { 453 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) {
422 const intptr_t kNumInputs = 2; 454 const intptr_t kNumInputs = 2;
423 const intptr_t kNumTemps = 1; 455 const intptr_t kNumTemps = 1;
424 LocationSummary* summary = new LocationSummary(kNumInputs, 456 LocationSummary* summary = new LocationSummary(kNumInputs,
425 kNumTemps, 457 kNumTemps,
(...skipping 28 matching lines...) Expand all
454 486
455 487
456 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, 488 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler,
457 RelationalOpComp* comp) { 489 RelationalOpComp* comp) {
458 Register left = comp->locs()->in(0).reg(); 490 Register left = comp->locs()->in(0).reg();
459 Register right = comp->locs()->in(1).reg(); 491 Register right = comp->locs()->in(1).reg();
460 Register temp = comp->locs()->temp(0).reg(); 492 Register temp = comp->locs()->temp(0).reg();
461 Label* deopt = compiler->AddDeoptStub(comp->cid(), 493 Label* deopt = compiler->AddDeoptStub(comp->cid(),
462 comp->token_pos(), 494 comp->token_pos(),
463 comp->try_index(), 495 comp->try_index(),
464 kDeoptSmiCompareSmis, 496 kDeoptSmiCompareSmi,
465 left, 497 left,
466 right); 498 right);
467 __ movl(temp, left); 499 __ movl(temp, left);
468 __ orl(temp, right); 500 __ orl(temp, right);
469 __ testl(temp, Immediate(kSmiTagMask)); 501 __ testl(temp, Immediate(kSmiTagMask));
470 __ j(NOT_ZERO, deopt); 502 __ j(NOT_ZERO, deopt);
471 503
472 Condition true_condition = TokenKindToSmiCondition(comp->kind()); 504 Condition true_condition = TokenKindToSmiCondition(comp->kind());
473 __ cmpl(left, right); 505 __ cmpl(left, right);
474 506
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 Label* deopt = compiler->AddDeoptStub(comp->cid(), 542 Label* deopt = compiler->AddDeoptStub(comp->cid(),
511 comp->token_pos(), 543 comp->token_pos(),
512 comp->try_index(), 544 comp->try_index(),
513 kDeoptDoubleComparison, 545 kDeoptDoubleComparison,
514 left, 546 left,
515 right); 547 right);
516 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 548 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
517 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 549 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
518 550
519 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); 551 Condition true_condition = TokenKindToDoubleCondition(comp->kind());
520 __ comisd(XMM0, XMM1);
521
522 if (comp->is_fused_with_branch()) { 552 if (comp->is_fused_with_branch()) {
523 BranchInstr* branch = comp->fused_with_branch(); 553 compiler->EmitDoubleCompareBranch(
524 BlockEntryInstr* nan_result = branch->is_negated() ? 554 true_condition, XMM0, XMM1, comp->fused_with_branch());
525 branch->true_successor() : branch->false_successor();
526 __ j(PARITY_EVEN, compiler->GetBlockLabel(nan_result));
527 branch->EmitBranchOnCondition(compiler, true_condition);
528 } else { 555 } else {
529 Register result = comp->locs()->out().reg(); 556 compiler->EmitDoubleCompareBool(
530 Label is_false, is_true, done; 557 true_condition, XMM0, XMM1, comp->locs()->out().reg());
531 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
532 __ j(true_condition, &is_true, Assembler::kNearJump);
533 __ Bind(&is_false);
534 __ LoadObject(result, compiler->bool_false());
535 __ jmp(&done);
536 __ Bind(&is_true);
537 __ LoadObject(result, compiler->bool_true());
538 __ Bind(&done);
539 } 558 }
540 } 559 }
541 560
542 561
543 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 562 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
544 if (operands_class_id() == kSmi) { 563 if (operands_class_id() == kSmi) {
545 EmitSmiRelationalOp(compiler, this); 564 EmitSmiRelationalOp(compiler, this);
546 return; 565 return;
547 } 566 }
548 if (operands_class_id() == kDouble) { 567 if (operands_class_id() == kDouble) {
(...skipping 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after
1954 instance_call()->argument_names()); 1973 instance_call()->argument_names());
1955 } 1974 }
1956 __ Bind(&done); 1975 __ Bind(&done);
1957 } 1976 }
1958 1977
1959 } // namespace dart 1978 } // namespace dart
1960 1979
1961 #undef __ 1980 #undef __
1962 1981
1963 #endif // defined TARGET_ARCH_X64 1982 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698