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

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

Issue 11048032: Support for mixed null/smi equality: do not deoptimize, emit same optimized code as if that was smi… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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
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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 302 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
303 const intptr_t kNumTemps = 1; 303 const intptr_t kNumTemps = 1;
304 LocationSummary* locs = 304 LocationSummary* locs =
305 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 305 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
306 locs->set_in(0, Location::RegisterLocation(RCX)); 306 locs->set_in(0, Location::RegisterLocation(RCX));
307 locs->set_in(1, Location::RegisterLocation(RDX)); 307 locs->set_in(1, Location::RegisterLocation(RDX));
308 locs->set_temp(0, Location::RegisterLocation(RBX)); 308 locs->set_temp(0, Location::RegisterLocation(RBX));
309 locs->set_out(Location::RegisterLocation(RAX)); 309 locs->set_out(Location::RegisterLocation(RAX));
310 return locs; 310 return locs;
311 } 311 }
312 const intptr_t kNumTemps = 0; 312 const intptr_t kNumTemps = 1;
313 LocationSummary* locs = 313 LocationSummary* locs =
314 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 314 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
315 locs->set_in(0, Location::RegisterLocation(RCX)); 315 locs->set_in(0, Location::RegisterLocation(RCX));
316 locs->set_in(1, Location::RegisterLocation(RDX)); 316 locs->set_in(1, Location::RegisterLocation(RDX));
317 locs->set_temp(0, Location::RegisterLocation(RBX));
317 locs->set_out(Location::RegisterLocation(RAX)); 318 locs->set_out(Location::RegisterLocation(RAX));
318 return locs; 319 return locs;
319 } 320 }
320 321
321 322
322 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 323 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
323 intptr_t deopt_id, 324 intptr_t deopt_id,
324 intptr_t token_pos, 325 intptr_t token_pos,
325 Token::Kind kind, 326 Token::Kind kind,
326 LocationSummary* locs) { 327 LocationSummary* locs) {
327 if (!compiler->is_optimizing()) { 328 if (!compiler->is_optimizing()) {
328 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, 329 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
329 deopt_id, 330 deopt_id,
330 token_pos); 331 token_pos);
331 } 332 }
332 const String& operator_name = String::ZoneHandle(Symbols::New("==")); 333 const String& operator_name = String::ZoneHandle(Symbols::New("=="));
333 const int kNumberOfArguments = 2; 334 const int kNumberOfArguments = 2;
334 const Array& kNoArgumentNames = Array::Handle(); 335 const Array& kNoArgumentNames = Array::Handle();
335 const int kNumArgumentsChecked = 2; 336 const int kNumArgumentsChecked = 2;
336 337
337 Label done, false_label, true_label;
338 Register left = locs->in(0).reg();
339 Register right = locs->in(1).reg();
340 __ popq(right);
341 __ popq(left);
342 const Immediate raw_null = 338 const Immediate raw_null =
343 Immediate(reinterpret_cast<intptr_t>(Object::null())); 339 Immediate(reinterpret_cast<intptr_t>(Object::null()));
344 Label check_identity, instance_call; 340 Label check_identity;
345 __ cmpq(right, raw_null); 341 __ cmpq(Address(RSP, 0 * kWordSize), raw_null);
346 __ j(EQUAL, &check_identity, Assembler::kNearJump); 342 __ j(EQUAL, &check_identity, Assembler::kNearJump);
347 __ cmpq(left, raw_null); 343 __ cmpq(Address(RSP, 1 * kWordSize), raw_null);
348 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); 344 __ j(EQUAL, &check_identity, Assembler::kNearJump);
345 const ICData& ic_data = compiler->GenerateInstanceCall(deopt_id,
346 token_pos,
347 operator_name,
348 kNumberOfArguments,
349 kNoArgumentNames,
350 kNumArgumentsChecked,
351 locs);
352 Label check_ne;
353 __ jmp(&check_ne);
349 354
350 __ Bind(&check_identity); 355 __ Bind(&check_identity);
351 __ cmpq(left, right); 356 // Call stub, load IC data in register. The stub will update ICData if
352 __ j(EQUAL, &true_label); 357 // necessary.
353 if (kind == Token::kEQ) { 358 Register ic_data_reg = locs->temp(0).reg();
354 __ LoadObject(RAX, compiler->bool_false()); 359 ASSERT(ic_data_reg == RBX); // Stub depends on it.
355 __ jmp(&done); 360 __ LoadObject(ic_data_reg, ic_data);
356 __ Bind(&true_label); 361 compiler->GenerateCall(token_pos,
357 __ LoadObject(RAX, compiler->bool_true()); 362 &StubCode::EqualityWithNullArgLabel(),
358 __ jmp(&done); 363 PcDescriptors::kOther,
359 } else { 364 locs);
360 ASSERT(kind == Token::kNE); 365 __ Drop(2);
361 __ jmp(&false_label); 366 __ Bind(&check_ne);
362 }
363
364 __ Bind(&instance_call);
365 __ pushq(left);
366 __ pushq(right);
367 compiler->GenerateInstanceCall(deopt_id,
368 token_pos,
369 operator_name,
370 kNumberOfArguments,
371 kNoArgumentNames,
372 kNumArgumentsChecked,
373 locs);
374 if (kind == Token::kNE) { 367 if (kind == Token::kNE) {
368 Label false_label, true_label, done;
375 // Negate the condition: true label returns false and vice versa. 369 // Negate the condition: true label returns false and vice versa.
376 __ CompareObject(RAX, compiler->bool_true()); 370 __ CompareObject(RAX, compiler->bool_true());
377 __ j(EQUAL, &true_label, Assembler::kNearJump); 371 __ j(EQUAL, &true_label, Assembler::kNearJump);
378 __ Bind(&false_label); 372 __ Bind(&false_label);
379 __ LoadObject(RAX, compiler->bool_true()); 373 __ LoadObject(RAX, compiler->bool_true());
380 __ jmp(&done, Assembler::kNearJump); 374 __ jmp(&done, Assembler::kNearJump);
381 __ Bind(&true_label); 375 __ Bind(&true_label);
382 __ LoadObject(RAX, compiler->bool_false()); 376 __ LoadObject(RAX, compiler->bool_false());
377 __ Bind(&done);
383 } 378 }
384 __ Bind(&done);
385 } 379 }
386 380
387 381
388 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 382 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
389 const ICData& orig_ic_data, 383 const ICData& orig_ic_data,
390 LocationSummary* locs, 384 LocationSummary* locs,
391 BranchInstr* branch, 385 BranchInstr* branch,
392 Token::Kind kind, 386 Token::Kind kind,
393 intptr_t deopt_id, 387 intptr_t deopt_id,
394 intptr_t token_pos) { 388 intptr_t token_pos) {
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 570 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
577 const LocationSummary& locs, 571 const LocationSummary& locs,
578 Token::Kind kind, 572 Token::Kind kind,
579 BranchInstr* branch) { 573 BranchInstr* branch) {
580 Location left = locs.in(0); 574 Location left = locs.in(0);
581 Location right = locs.in(1); 575 Location right = locs.in(1);
582 576
583 Condition true_condition = TokenKindToSmiCondition(kind); 577 Condition true_condition = TokenKindToSmiCondition(kind);
584 578
585 if (left.IsConstant() && right.IsConstant()) { 579 if (left.IsConstant() && right.IsConstant()) {
580 bool result = false;
581 // One of them could be NULL (for equality only).
582 if (left.constant().IsNull() || right.constant().IsNull()) {
583 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
584 result = left.constant().IsNull() && right.constant().IsNull();
585 if (kind == Token::kNE) {
586 result = !result;
587 }
588 } else {
586 // TODO(vegorov): should be eliminated earlier by constant propagation. 589 // TODO(vegorov): should be eliminated earlier by constant propagation.
Florian Schneider 2012/10/05 09:17:35 Indentation is off.
srdjan 2012/10/09 18:06:03 Done.
587 const bool result = FlowGraphCompiler::EvaluateCondition( 590 result = FlowGraphCompiler::EvaluateCondition(
588 true_condition, 591 true_condition,
589 Smi::Cast(left.constant()).Value(), 592 Smi::Cast(left.constant()).Value(),
590 Smi::Cast(right.constant()).Value()); 593 Smi::Cast(right.constant()).Value());
594 }
591 595
592 if (branch != NULL) { 596 if (branch != NULL) {
593 branch->EmitBranchOnValue(compiler, result); 597 branch->EmitBranchOnValue(compiler, result);
594 } else { 598 } else {
595 __ LoadObject(locs.out().reg(), result ? compiler->bool_true() 599 __ LoadObject(locs.out().reg(), result ? compiler->bool_true()
596 : compiler->bool_false()); 600 : compiler->bool_false());
597 } 601 }
598 602
599 return; 603 return;
600 } 604 }
(...skipping 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 summary->set_temp(0, Location::RequiresRegister()); 2044 summary->set_temp(0, Location::RequiresRegister());
2041 return summary; 2045 return summary;
2042 } 2046 }
2043 2047
2044 2048
2045 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2049 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2046 Register value = locs()->in(0).reg(); 2050 Register value = locs()->in(0).reg();
2047 Register temp = locs()->temp(0).reg(); 2051 Register temp = locs()->temp(0).reg();
2048 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2052 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2049 kDeoptCheckClass); 2053 kDeoptCheckClass);
2050 ASSERT(unary_checks().GetReceiverClassIdAt(0) != kSmiCid);
2051 __ testq(value, Immediate(kSmiTagMask));
2052 __ j(ZERO, deopt);
2053 __ LoadClassId(temp, value);
2054 Label is_ok; 2054 Label is_ok;
2055 intptr_t cix = 0;
2056 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
2057 __ testq(value, Immediate(kSmiTagMask));
2058 __ j(ZERO, &is_ok);
2059 cix++; // Skip first check.
2060 } else {
2061 __ testq(value, Immediate(kSmiTagMask));
2062 __ j(ZERO, deopt);
2063 }
2055 const intptr_t num_checks = unary_checks().NumberOfChecks(); 2064 const intptr_t num_checks = unary_checks().NumberOfChecks();
2056 const bool use_near_jump = num_checks < 5; 2065 const bool use_near_jump = num_checks < 5;
2057 for (intptr_t i = 0; i < num_checks; i++) { 2066 for (intptr_t i = cix; i < num_checks; i++) {
2067 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
2058 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i))); 2068 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i)));
2059 if (i == (num_checks - 1)) { 2069 if (i == (num_checks - 1)) {
2060 __ j(NOT_EQUAL, deopt); 2070 __ j(NOT_EQUAL, deopt);
2061 } else { 2071 } else {
2062 if (use_near_jump) { 2072 if (use_near_jump) {
2063 __ j(EQUAL, &is_ok, Assembler::kNearJump); 2073 __ j(EQUAL, &is_ok, Assembler::kNearJump);
2064 } else { 2074 } else {
2065 __ j(EQUAL, &is_ok); 2075 __ j(EQUAL, &is_ok);
2066 } 2076 }
2067 } 2077 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2185 void UnboxedMintUnaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2195 void UnboxedMintUnaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2186 UNIMPLEMENTED(); 2196 UNIMPLEMENTED();
2187 } 2197 }
2188 2198
2189 2199
2190 } // namespace dart 2200 } // namespace dart
2191 2201
2192 #undef __ 2202 #undef __
2193 2203
2194 #endif // defined TARGET_ARCH_X64 2204 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698