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

Side by Side Diff: runtime/vm/intermediate_language_ia32.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_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 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 304 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
305 const intptr_t kNumTemps = 1; 305 const intptr_t kNumTemps = 1;
306 LocationSummary* locs = 306 LocationSummary* locs =
307 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 307 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
308 locs->set_in(0, Location::RegisterLocation(ECX)); 308 locs->set_in(0, Location::RegisterLocation(ECX));
309 locs->set_in(1, Location::RegisterLocation(EDX)); 309 locs->set_in(1, Location::RegisterLocation(EDX));
310 locs->set_temp(0, Location::RegisterLocation(EBX)); 310 locs->set_temp(0, Location::RegisterLocation(EBX));
311 locs->set_out(Location::RegisterLocation(EAX)); 311 locs->set_out(Location::RegisterLocation(EAX));
312 return locs; 312 return locs;
313 } 313 }
314 const intptr_t kNumTemps = 0; 314 const intptr_t kNumTemps = 1;
315 LocationSummary* locs = 315 LocationSummary* locs =
316 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 316 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
317 locs->set_in(0, Location::RegisterLocation(ECX)); 317 locs->set_in(0, Location::RegisterLocation(EBX));
318 locs->set_in(1, Location::RegisterLocation(EDX)); 318 locs->set_in(1, Location::RegisterLocation(EDX));
319 locs->set_temp(0, Location::RegisterLocation(ECX));
319 locs->set_out(Location::RegisterLocation(EAX)); 320 locs->set_out(Location::RegisterLocation(EAX));
320 return locs; 321 return locs;
321 } 322 }
322 323
323 324
324 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 325 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
325 intptr_t deopt_id, 326 intptr_t deopt_id,
326 intptr_t token_pos, 327 intptr_t token_pos,
327 Token::Kind kind, 328 Token::Kind kind,
328 LocationSummary* locs) { 329 LocationSummary* locs) {
329 if (!compiler->is_optimizing()) { 330 if (!compiler->is_optimizing()) {
330 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, 331 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
331 deopt_id, 332 deopt_id,
332 token_pos); 333 token_pos);
333 } 334 }
334 const String& operator_name = String::ZoneHandle(Symbols::New("==")); 335 const String& operator_name = String::ZoneHandle(Symbols::New("=="));
335 const int kNumberOfArguments = 2; 336 const int kNumberOfArguments = 2;
336 const Array& kNoArgumentNames = Array::Handle(); 337 const Array& kNoArgumentNames = Array::Handle();
337 const int kNumArgumentsChecked = 2; 338 const int kNumArgumentsChecked = 2;
338 339
339 Label done, false_label, true_label;
340 Register left = locs->in(0).reg();
341 Register right = locs->in(1).reg();
342 __ popl(right);
343 __ popl(left);
344 const Immediate raw_null = 340 const Immediate raw_null =
345 Immediate(reinterpret_cast<intptr_t>(Object::null())); 341 Immediate(reinterpret_cast<intptr_t>(Object::null()));
346 Label check_identity, instance_call; 342 Label check_identity;
347 __ cmpl(right, raw_null); 343 __ cmpl(Address(ESP, 0 * kWordSize), raw_null);
348 __ j(EQUAL, &check_identity, Assembler::kNearJump); 344 __ j(EQUAL, &check_identity, Assembler::kNearJump);
349 __ cmpl(left, raw_null); 345 __ cmpl(Address(ESP, 1 * kWordSize), raw_null);
350 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); 346 __ j(EQUAL, &check_identity, Assembler::kNearJump);
347
348 const ICData& ic_data = compiler->GenerateInstanceCall(deopt_id,
349 token_pos,
350 operator_name,
351 kNumberOfArguments,
352 kNoArgumentNames,
353 kNumArgumentsChecked,
354 locs);
355 Label check_ne;
356 __ jmp(&check_ne);
351 357
352 __ Bind(&check_identity); 358 __ Bind(&check_identity);
353 __ cmpl(left, right); 359 // Call stub, load IC data in register. The stub will update ICData if
354 __ j(EQUAL, &true_label); 360 // necessary.
355 if (kind == Token::kEQ) { 361 Register ic_data_reg = locs->temp(0).reg();
356 __ LoadObject(EAX, compiler->bool_false()); 362 ASSERT(ic_data_reg == ECX); // Stub depends on it.
357 __ jmp(&done); 363 __ LoadObject(ic_data_reg, ic_data);
358 __ Bind(&true_label); 364 compiler->GenerateCall(token_pos,
359 __ LoadObject(EAX, compiler->bool_true()); 365 &StubCode::EqualityWithNullArgLabel(),
360 __ jmp(&done); 366 PcDescriptors::kOther,
361 } else { 367 locs);
362 ASSERT(kind == Token::kNE); 368 __ Drop(2);
363 __ jmp(&false_label); 369 __ Bind(&check_ne);
364 }
365
366 __ Bind(&instance_call);
367 __ pushl(left);
368 __ pushl(right);
369 compiler->GenerateInstanceCall(deopt_id,
370 token_pos,
371 operator_name,
372 kNumberOfArguments,
373 kNoArgumentNames,
374 kNumArgumentsChecked,
375 locs);
376 if (kind == Token::kNE) { 370 if (kind == Token::kNE) {
371 Label false_label, true_label, done;
377 // Negate the condition: true label returns false and vice versa. 372 // Negate the condition: true label returns false and vice versa.
378 __ CompareObject(EAX, compiler->bool_true()); 373 __ CompareObject(EAX, compiler->bool_true());
379 __ j(EQUAL, &true_label, Assembler::kNearJump); 374 __ j(EQUAL, &true_label, Assembler::kNearJump);
380 __ Bind(&false_label); 375 __ Bind(&false_label);
381 __ LoadObject(EAX, compiler->bool_true()); 376 __ LoadObject(EAX, compiler->bool_true());
382 __ jmp(&done, Assembler::kNearJump); 377 __ jmp(&done, Assembler::kNearJump);
383 __ Bind(&true_label); 378 __ Bind(&true_label);
384 __ LoadObject(EAX, compiler->bool_false()); 379 __ LoadObject(EAX, compiler->bool_false());
380 __ Bind(&done);
385 } 381 }
386 __ Bind(&done);
387 } 382 }
388 383
389 384
390 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 385 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
391 const ICData& orig_ic_data, 386 const ICData& orig_ic_data,
392 LocationSummary* locs, 387 LocationSummary* locs,
393 BranchInstr* branch, 388 BranchInstr* branch,
394 Token::Kind kind, 389 Token::Kind kind,
395 intptr_t deopt_id, 390 intptr_t deopt_id,
396 intptr_t token_pos) { 391 intptr_t token_pos) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 572 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
578 const LocationSummary& locs, 573 const LocationSummary& locs,
579 Token::Kind kind, 574 Token::Kind kind,
580 BranchInstr* branch) { 575 BranchInstr* branch) {
581 Location left = locs.in(0); 576 Location left = locs.in(0);
582 Location right = locs.in(1); 577 Location right = locs.in(1);
583 578
584 Condition true_condition = TokenKindToSmiCondition(kind); 579 Condition true_condition = TokenKindToSmiCondition(kind);
585 580
586 if (left.IsConstant() && right.IsConstant()) { 581 if (left.IsConstant() && right.IsConstant()) {
582 bool result = false;
583 // One of them could be NULL (for equality only).
584 if (left.constant().IsNull() || right.constant().IsNull()) {
585 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
586 result = left.constant().IsNull() && right.constant().IsNull();
587 if (kind == Token::kNE) {
588 result = !result;
589 }
590 } else {
587 // TODO(vegorov): should be eliminated earlier by constant propagation. 591 // TODO(vegorov): should be eliminated earlier by constant propagation.
588 const bool result = FlowGraphCompiler::EvaluateCondition( 592 result = FlowGraphCompiler::EvaluateCondition(
589 true_condition, 593 true_condition,
590 Smi::Cast(left.constant()).Value(), 594 Smi::Cast(left.constant()).Value(),
591 Smi::Cast(right.constant()).Value()); 595 Smi::Cast(right.constant()).Value());
596 }
592 597
593 if (branch != NULL) { 598 if (branch != NULL) {
594 branch->EmitBranchOnValue(compiler, result); 599 branch->EmitBranchOnValue(compiler, result);
595 } else { 600 } else {
596 __ LoadObject(locs.out().reg(), result ? compiler->bool_true() 601 __ LoadObject(locs.out().reg(), result ? compiler->bool_true()
597 : compiler->bool_false()); 602 : compiler->bool_false());
598 } 603 }
599 604
600 return; 605 return;
601 } 606 }
(...skipping 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after
2073 summary->set_temp(0, Location::RequiresRegister()); 2078 summary->set_temp(0, Location::RequiresRegister());
2074 return summary; 2079 return summary;
2075 } 2080 }
2076 2081
2077 2082
2078 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2083 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2079 Register value = locs()->in(0).reg(); 2084 Register value = locs()->in(0).reg();
2080 Register temp = locs()->temp(0).reg(); 2085 Register temp = locs()->temp(0).reg();
2081 Label* deopt = compiler->AddDeoptStub(deopt_id(), 2086 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2082 kDeoptCheckClass); 2087 kDeoptCheckClass);
2083 ASSERT(unary_checks().GetReceiverClassIdAt(0) != kSmiCid); 2088 Label is_ok;
2084 __ testl(value, Immediate(kSmiTagMask)); 2089 intptr_t cix = 0;
2085 __ j(ZERO, deopt); 2090 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) {
2091 __ testl(value, Immediate(kSmiTagMask));
2092 __ j(ZERO, &is_ok);
2093 cix++; // Skip first check.
2094 } else {
2095 __ testl(value, Immediate(kSmiTagMask));
2096 __ j(ZERO, deopt);
2097 }
2086 __ LoadClassId(temp, value); 2098 __ LoadClassId(temp, value);
2087 Label is_ok;
2088 const intptr_t num_checks = unary_checks().NumberOfChecks(); 2099 const intptr_t num_checks = unary_checks().NumberOfChecks();
2089 const bool use_near_jump = num_checks < 5; 2100 const bool use_near_jump = num_checks < 5;
2090 for (intptr_t i = 0; i < num_checks; i++) { 2101 for (intptr_t i = cix; i < num_checks; i++) {
2102 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid);
2091 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i))); 2103 __ cmpl(temp, Immediate(unary_checks().GetReceiverClassIdAt(i)));
2092 if (i == (num_checks - 1)) { 2104 if (i == (num_checks - 1)) {
2093 __ j(NOT_EQUAL, deopt); 2105 __ j(NOT_EQUAL, deopt);
2094 } else { 2106 } else {
2095 if (use_near_jump) { 2107 if (use_near_jump) {
2096 __ j(EQUAL, &is_ok, Assembler::kNearJump); 2108 __ j(EQUAL, &is_ok, Assembler::kNearJump);
2097 } else { 2109 } else {
2098 __ j(EQUAL, &is_ok); 2110 __ j(EQUAL, &is_ok);
2099 } 2111 }
2100 } 2112 }
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
2399 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 2411 __ pcmpeqq(XMM0, XMM0); // Generate all 1's.
2400 __ pxor(value, XMM0); 2412 __ pxor(value, XMM0);
2401 } 2413 }
2402 2414
2403 2415
2404 } // namespace dart 2416 } // namespace dart
2405 2417
2406 #undef __ 2418 #undef __
2407 2419
2408 #endif // defined TARGET_ARCH_X64 2420 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698