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

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

Issue 10808035: Apply Kevin's suggestions, make branch-compare generation more robust (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') | no next file » | 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 try_index(), 193 try_index(),
194 kConditionTypeErrorRuntimeEntry); 194 kConditionTypeErrorRuntimeEntry);
195 // We should never return here. 195 // We should never return here.
196 __ int3(); 196 __ int3();
197 197
198 __ Bind(&done); 198 __ Bind(&done);
199 ASSERT(obj == result); 199 ASSERT(obj == result);
200 } 200 }
201 201
202 202
203 static Condition TokenKindToSmiCondition(Token::Kind kind) {
204 switch (kind) {
205 case Token::kEQ: return EQUAL;
206 case Token::kNE: return NOT_EQUAL;
207 case Token::kLT: return LESS;
208 case Token::kGT: return GREATER;
209 case Token::kLTE: return LESS_EQUAL;
210 case Token::kGTE: return GREATER_EQUAL;
211 default:
212 UNREACHABLE();
213 return OVERFLOW;
214 }
215 }
216
217
203 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { 218 LocationSummary* EqualityCompareComp::MakeLocationSummary() const {
204 const intptr_t kNumInputs = 2; 219 const intptr_t kNumInputs = 2;
205 if (receiver_class_id() != kObject) { 220 if (receiver_class_id() != kObject) {
206 ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble)); 221 ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble));
207 // No temporary register needed for double comparison. 222 // No temporary register needed for double comparison.
208 const intptr_t kNumTemps = (receiver_class_id() == kSmi) ? 1 : 0; 223 const intptr_t kNumTemps = (receiver_class_id() == kSmi) ? 1 : 0;
209 LocationSummary* locs = new LocationSummary(kNumInputs, 224 LocationSummary* locs = new LocationSummary(kNumInputs,
210 kNumTemps, 225 kNumTemps,
211 LocationSummary::kNoCall); 226 LocationSummary::kNoCall);
212 locs->set_in(0, Location::RequiresRegister()); 227 locs->set_in(0, Location::RequiresRegister());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 kDeoptSmiCompareSmi, 267 kDeoptSmiCompareSmi,
253 left, 268 left,
254 right); 269 right);
255 __ movq(temp, left); 270 __ movq(temp, left);
256 __ orq(temp, right); 271 __ orq(temp, right);
257 __ testq(temp, Immediate(kSmiTagMask)); 272 __ testq(temp, Immediate(kSmiTagMask));
258 __ j(NOT_ZERO, deopt); 273 __ j(NOT_ZERO, deopt);
259 __ cmpq(left, right); 274 __ cmpq(left, right);
260 Register result = comp->locs()->out().reg(); 275 Register result = comp->locs()->out().reg();
261 Label load_true, done; 276 Label load_true, done;
262 __ j(EQUAL, &load_true, Assembler::kNearJump); 277 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump);
263 __ LoadObject(result, compiler->bool_false()); 278 __ LoadObject(result, compiler->bool_false());
264 __ jmp(&done, Assembler::kNearJump); 279 __ jmp(&done, Assembler::kNearJump);
265 __ Bind(&load_true); 280 __ Bind(&load_true);
266 __ LoadObject(result, compiler->bool_true()); 281 __ LoadObject(result, compiler->bool_true());
267 __ Bind(&done); 282 __ Bind(&done);
268 } 283 }
269 284
270 285
271 // TODO(srdjan): Add support for mixed Smi/Double equality 286 // TODO(srdjan): Add support for mixed Smi/Double equality
272 // (see LoadDoubleOrSmiToXmm). 287 // (see LoadDoubleOrSmiToXmm).
273 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, 288 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler,
274 EqualityCompareComp* comp) { 289 EqualityCompareComp* comp) {
275 Register left = comp->locs()->in(0).reg(); 290 Register left = comp->locs()->in(0).reg();
276 Register right = comp->locs()->in(1).reg(); 291 Register right = comp->locs()->in(1).reg();
277 Label* deopt = compiler->AddDeoptStub(comp->cid(), 292 Label* deopt = compiler->AddDeoptStub(comp->cid(),
278 comp->token_pos(), 293 comp->token_pos(),
279 comp->try_index(), 294 comp->try_index(),
280 kDeoptDoubleCompareDouble, 295 kDeoptDoubleCompareDouble,
281 left, 296 left,
282 right); 297 right);
283 __ CompareClassId(left, kDouble); 298 __ CompareClassId(left, kDouble);
284 __ j(NOT_EQUAL, deopt); 299 __ j(NOT_EQUAL, deopt);
285 __ CompareClassId(right, kDouble); 300 __ CompareClassId(right, kDouble);
286 __ j(NOT_EQUAL, deopt); 301 __ j(NOT_EQUAL, deopt);
287 __ movsd(XMM0, FieldAddress(left, Double::value_offset())); 302 __ movsd(XMM0, FieldAddress(left, Double::value_offset()));
288 __ movsd(XMM1, FieldAddress(right, Double::value_offset())); 303 __ movsd(XMM1, FieldAddress(right, Double::value_offset()));
289 compiler->EmitDoubleCompareBool( 304 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()),
290 EQUAL, XMM0, XMM1, comp->locs()->out().reg()); 305 XMM0, XMM1,
306 comp->locs()->out().reg());
291 } 307 }
292 308
293 309
294 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 310 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
295 EqualityCompareComp* comp) { 311 EqualityCompareComp* comp) {
296 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 312 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
297 comp->cid(), 313 comp->cid(),
298 comp->token_pos(), 314 comp->token_pos(),
299 comp->try_index()); 315 comp->try_index());
300 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); 316 const String& operator_name = String::ZoneHandle(String::NewSymbol("=="));
301 const int kNumberOfArguments = 2; 317 const int kNumberOfArguments = 2;
302 const Array& kNoArgumentNames = Array::Handle(); 318 const Array& kNoArgumentNames = Array::Handle();
303 const int kNumArgumentsChecked = 2; 319 const int kNumArgumentsChecked = 2;
304 320
305 compiler->GenerateInstanceCall(comp->cid(), 321 compiler->GenerateInstanceCall(comp->cid(),
306 comp->token_pos(), 322 comp->token_pos(),
307 comp->try_index(), 323 comp->try_index(),
308 operator_name, 324 operator_name,
309 kNumberOfArguments, 325 kNumberOfArguments,
310 kNoArgumentNames, 326 kNoArgumentNames,
311 kNumArgumentsChecked); 327 kNumArgumentsChecked);
312 ASSERT(comp->locs()->out().reg() == RAX); 328 ASSERT(comp->locs()->out().reg() == RAX);
329 if (comp->kind() == Token::kNE) {
330 Label done, false_label;
331 __ CompareObject(RAX, compiler->bool_true());
332 __ j(EQUAL, &false_label, Assembler::kNearJump);
333 __ LoadObject(RAX, compiler->bool_true());
334 __ jmp(&done, Assembler::kNearJump);
335 __ Bind(&false_label);
336 __ LoadObject(RAX, compiler->bool_false());
337 __ Bind(&done);
338 }
313 } 339 }
314 340
315 341
316 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 342 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
317 const ICData& orig_ic_data, 343 const ICData& orig_ic_data,
318 const LocationSummary& locs, 344 const LocationSummary& locs,
319 BranchInstr* branch, 345 BranchInstr* branch,
320 Token::Kind kind, 346 Token::Kind kind,
321 intptr_t cid, 347 intptr_t cid,
322 intptr_t token_pos, 348 intptr_t token_pos,
323 intptr_t try_index) { 349 intptr_t try_index) {
350 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
324 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); 351 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
325 ASSERT(ic_data.NumberOfChecks() > 0); 352 ASSERT(ic_data.NumberOfChecks() > 0);
326 ASSERT(ic_data.num_args_tested() == 1); 353 ASSERT(ic_data.num_args_tested() == 1);
327 Label* deopt = compiler->AddDeoptStub(cid, 354 Label* deopt = compiler->AddDeoptStub(cid,
328 token_pos, 355 token_pos,
329 try_index, 356 try_index,
330 kDeoptEquality); 357 kDeoptEquality);
331 Register left = locs.in(0).reg(); 358 Register left = locs.in(0).reg();
332 Register right = locs.in(1).reg(); 359 Register right = locs.in(1).reg();
333 __ testq(left, Immediate(kSmiTagMask)); 360 __ testq(left, Immediate(kSmiTagMask));
334 Register temp = locs.temp(0).reg(); 361 Register temp = locs.temp(0).reg();
335 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { 362 if (ic_data.GetReceiverClassIdAt(0) == kSmi) {
336 Label done, load_class_id; 363 Label done, load_class_id;
337 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); 364 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
338 __ movq(temp, Immediate(kSmi)); 365 __ movq(temp, Immediate(kSmi));
339 __ jmp(&done, Assembler::kNearJump); 366 __ jmp(&done, Assembler::kNearJump);
340 __ Bind(&load_class_id); 367 __ Bind(&load_class_id);
341 __ LoadClassId(temp, left); 368 __ LoadClassId(temp, left);
342 __ Bind(&done); 369 __ Bind(&done);
343 } else { 370 } else {
344 __ j(ZERO, deopt); // Smi deopts. 371 __ j(ZERO, deopt); // Smi deopts.
345 __ LoadClassId(temp, left); 372 __ LoadClassId(temp, left);
346 } 373 }
347 Condition cond = (kind == Token::kEQ) ? EQUAL : NOT_EQUAL; 374 Condition cond = TokenKindToSmiCondition(kind);
348 Label done; 375 Label done;
349 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 376 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
350 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmi) || (i == 0)); 377 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmi) || (i == 0));
351 Label next_test; 378 Label next_test;
352 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); 379 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i)));
353 __ j(NOT_EQUAL, &next_test, Assembler::kNearJump); 380 __ j(NOT_EQUAL, &next_test, Assembler::kNearJump);
354 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); 381 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
355 ObjectStore* object_store = Isolate::Current()->object_store(); 382 ObjectStore* object_store = Isolate::Current()->object_store();
356 if (target.owner() == object_store->object_class()) { 383 if (target.owner() == object_store->object_class()) {
357 // Object.== is same as ===. 384 // Object.== is same as ===.
(...skipping 13 matching lines...) Expand all
371 } 398 }
372 } else { 399 } else {
373 const int kNumberOfArguments = 2; 400 const int kNumberOfArguments = 2;
374 const Array& kNoArgumentNames = Array::Handle(); 401 const Array& kNoArgumentNames = Array::Handle();
375 compiler->GenerateStaticCall(cid, 402 compiler->GenerateStaticCall(cid,
376 token_pos, 403 token_pos,
377 try_index, 404 try_index,
378 target, 405 target,
379 kNumberOfArguments, 406 kNumberOfArguments,
380 kNoArgumentNames); 407 kNoArgumentNames);
381 if (branch != NULL) { 408 if (branch == NULL) {
409 if (kind == Token::kNE) {
410 Label false_label;
411 __ CompareObject(RAX, compiler->bool_true());
412 __ j(EQUAL, &false_label, Assembler::kNearJump);
413 __ LoadObject(RAX, compiler->bool_true());
414 __ jmp(&done, Assembler::kNearJump);
415 __ Bind(&false_label);
416 __ LoadObject(RAX, compiler->bool_false());
417 __ jmp(&done);
418 }
419 } else {
382 __ CompareObject(RAX, compiler->bool_true()); 420 __ CompareObject(RAX, compiler->bool_true());
383 branch->EmitBranchOnCondition(compiler, cond); 421 branch->EmitBranchOnCondition(compiler, cond);
384 } 422 }
385 } 423 }
386 __ jmp(&done); 424 __ jmp(&done);
387 __ Bind(&next_test); 425 __ Bind(&next_test);
388 } 426 }
389 // Fall through leads to deoptimization 427 // Fall through leads to deoptimization
390 __ jmp(deopt); 428 __ jmp(deopt);
391 __ Bind(&done); 429 __ Bind(&done);
392 } 430 }
393 431
394 432
395 // First test if receiver is NULL, in which case === is applied. 433 // First test if receiver is NULL, in which case === is applied.
396 // If type feedback was provided (lists of <class-id, target>), do a 434 // If type feedback was provided (lists of <class-id, target>), do a
397 // type by type check (either === or static call to the operator. 435 // type by type check (either === or static call to the operator.
398 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 436 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
399 const LocationSummary& locs, 437 const LocationSummary& locs,
400 Token::Kind kind, 438 Token::Kind kind,
401 BranchInstr* branch, 439 BranchInstr* branch,
402 const ICData& ic_data, 440 const ICData& ic_data,
403 intptr_t cid, 441 intptr_t cid,
404 intptr_t token_pos, 442 intptr_t token_pos,
405 intptr_t try_index) { 443 intptr_t try_index) {
444 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
406 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); 445 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
407 Register left = locs.in(0).reg(); 446 Register left = locs.in(0).reg();
408 Register right = locs.in(1).reg(); 447 Register right = locs.in(1).reg();
409 const Immediate raw_null = 448 const Immediate raw_null =
410 Immediate(reinterpret_cast<intptr_t>(Object::null())); 449 Immediate(reinterpret_cast<intptr_t>(Object::null()));
411 Label done, non_null_compare; 450 Label done, non_null_compare;
412 __ cmpq(left, raw_null); 451 __ cmpq(left, raw_null);
413 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); 452 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump);
414 // Comparison with NULL is "===". 453 // Comparison with NULL is "===".
415 __ cmpq(left, right); 454 __ cmpq(left, right);
416 Condition cond = (kind == Token::kEQ) ? EQUAL : NOT_EQUAL; 455 Condition cond = TokenKindToSmiCondition(kind);
417 if (branch != NULL) { 456 if (branch != NULL) {
418 branch->EmitBranchOnCondition(compiler, cond); 457 branch->EmitBranchOnCondition(compiler, cond);
419 } else { 458 } else {
420 Register result = locs.out().reg(); 459 Register result = locs.out().reg();
421 Label load_true; 460 Label load_true;
422 __ j(cond, &load_true, Assembler::kNearJump); 461 __ j(cond, &load_true, Assembler::kNearJump);
423 __ LoadObject(result, compiler->bool_false()); 462 __ LoadObject(result, compiler->bool_false());
424 __ jmp(&done); 463 __ jmp(&done);
425 __ Bind(&load_true); 464 __ Bind(&load_true);
426 __ LoadObject(result, compiler->bool_true()); 465 __ LoadObject(result, compiler->bool_true());
(...skipping 11 matching lines...) Expand all
438 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 477 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
439 if (receiver_class_id() == kSmi) { 478 if (receiver_class_id() == kSmi) {
440 EmitSmiEqualityCompare(compiler, this); 479 EmitSmiEqualityCompare(compiler, this);
441 return; 480 return;
442 } 481 }
443 if (receiver_class_id() == kDouble) { 482 if (receiver_class_id() == kDouble) {
444 EmitDoubleEqualityCompare(compiler, this); 483 EmitDoubleEqualityCompare(compiler, this);
445 return; 484 return;
446 } 485 }
447 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 486 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
448 EmitGenericEqualityCompare(compiler, *locs(), Token::kEQ, NULL, 487 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL,
449 *ic_data(), cid(), token_pos(), try_index()); 488 *ic_data(), cid(), token_pos(), try_index());
450 } else { 489 } else {
451 Register left = locs()->in(0).reg(); 490 Register left = locs()->in(0).reg();
452 Register right = locs()->in(1).reg(); 491 Register right = locs()->in(1).reg();
453 __ pushq(left); 492 __ pushq(left);
454 __ pushq(right); 493 __ pushq(right);
455 EmitEqualityAsInstanceCall(compiler, this); 494 EmitEqualityAsInstanceCall(compiler, this);
456 } 495 }
457 } 496 }
458 497
459 498
460 LocationSummary* RelationalOpComp::MakeLocationSummary() const { 499 LocationSummary* RelationalOpComp::MakeLocationSummary() const {
461 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { 500 if (operands_class_id() == kSmi || operands_class_id() == kDouble) {
462 const intptr_t kNumInputs = 2; 501 const intptr_t kNumInputs = 2;
463 const intptr_t kNumTemps = 1; 502 const intptr_t kNumTemps = 1;
464 LocationSummary* summary = new LocationSummary(kNumInputs, 503 LocationSummary* summary = new LocationSummary(kNumInputs,
465 kNumTemps, 504 kNumTemps,
466 LocationSummary::kCall); 505 LocationSummary::kCall);
467 summary->set_in(0, Location::RequiresRegister()); 506 summary->set_in(0, Location::RequiresRegister());
468 summary->set_in(1, Location::RequiresRegister()); 507 summary->set_in(1, Location::RequiresRegister());
469 summary->set_out(Location::RequiresRegister()); 508 summary->set_out(Location::RequiresRegister());
470 summary->set_temp(0, Location::RequiresRegister()); 509 summary->set_temp(0, Location::RequiresRegister());
471 return summary; 510 return summary;
472 } 511 }
473 ASSERT(operands_class_id() == kObject); 512 ASSERT(operands_class_id() == kObject);
474 return MakeCallSummary(); 513 return MakeCallSummary();
475 } 514 }
476 515
477 516
478 static Condition TokenKindToSmiCondition(Token::Kind kind) {
479 switch (kind) {
480 case Token::kEQ: return EQUAL;
481 case Token::kNE: return NOT_EQUAL;
482 case Token::kLT: return LESS;
483 case Token::kGT: return GREATER;
484 case Token::kLTE: return LESS_EQUAL;
485 case Token::kGTE: return GREATER_EQUAL;
486 default:
487 UNREACHABLE();
488 return OVERFLOW;
489 }
490 }
491
492
493 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 517 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
494 const LocationSummary& locs, 518 const LocationSummary& locs,
495 Token::Kind kind, 519 Token::Kind kind,
496 BranchInstr* branch, 520 BranchInstr* branch,
497 intptr_t cid, 521 intptr_t cid,
498 intptr_t token_pos, 522 intptr_t token_pos,
499 intptr_t try_index) { 523 intptr_t try_index) {
500 Register left = locs.in(0).reg(); 524 Register left = locs.in(0).reg();
501 Register right = locs.in(1).reg(); 525 Register right = locs.in(1).reg();
502 Register temp = locs.temp(0).reg(); 526 Register temp = locs.temp(0).reg();
(...skipping 1643 matching lines...) Expand 10 before | Expand all | Expand 10 after
2146 ASSERT(locs()->out().reg() == RAX); 2170 ASSERT(locs()->out().reg() == RAX);
2147 __ CompareObject(locs()->out().reg(), compiler->bool_true()); 2171 __ CompareObject(locs()->out().reg(), compiler->bool_true());
2148 EmitBranchOnCondition(compiler, branch_condition); 2172 EmitBranchOnCondition(compiler, branch_condition);
2149 } 2173 }
2150 2174
2151 } // namespace dart 2175 } // namespace dart
2152 2176
2153 #undef __ 2177 #undef __
2154 2178
2155 #endif // defined TARGET_ARCH_X64 2179 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698