OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 const ICData& original_ic_data) { | 303 const ICData& original_ic_data) { |
304 if (!compiler->is_optimizing()) { | 304 if (!compiler->is_optimizing()) { |
305 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 305 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
306 deopt_id, | 306 deopt_id, |
307 token_pos); | 307 token_pos); |
308 } | 308 } |
309 const int kNumberOfArguments = 2; | 309 const int kNumberOfArguments = 2; |
310 const Array& kNoArgumentNames = Object::null_array(); | 310 const Array& kNoArgumentNames = Object::null_array(); |
311 const int kNumArgumentsChecked = 2; | 311 const int kNumArgumentsChecked = 2; |
312 | 312 |
313 const Immediate& raw_null = | |
314 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
315 Label check_identity; | |
316 __ cmpl(Address(ESP, 0 * kWordSize), raw_null); | |
317 __ j(EQUAL, &check_identity); | |
318 __ cmpl(Address(ESP, 1 * kWordSize), raw_null); | |
319 __ j(EQUAL, &check_identity); | |
320 | |
321 ICData& equality_ic_data = ICData::ZoneHandle(); | 313 ICData& equality_ic_data = ICData::ZoneHandle(); |
322 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 314 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
323 ASSERT(!original_ic_data.IsNull()); | 315 ASSERT(!original_ic_data.IsNull()); |
324 if (original_ic_data.NumberOfChecks() == 0) { | 316 if (original_ic_data.NumberOfChecks() == 0) { |
325 // IC call for reoptimization populates original ICData. | 317 // IC call for reoptimization populates original ICData. |
326 equality_ic_data = original_ic_data.raw(); | 318 equality_ic_data = original_ic_data.raw(); |
327 } else { | 319 } else { |
328 // Megamorphic call. | 320 // Megamorphic call. |
329 equality_ic_data = original_ic_data.AsUnaryClassChecks(); | 321 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
330 } | 322 } |
331 } else { | 323 } else { |
332 const Array& arguments_descriptor = | 324 const Array& arguments_descriptor = |
333 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, | 325 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, |
334 kNoArgumentNames)); | 326 kNoArgumentNames)); |
335 equality_ic_data = ICData::New(compiler->parsed_function().function(), | 327 equality_ic_data = ICData::New(compiler->parsed_function().function(), |
336 Symbols::EqualOperator(), | 328 Symbols::EqualOperator(), |
337 arguments_descriptor, | 329 arguments_descriptor, |
338 deopt_id, | 330 deopt_id, |
339 kNumArgumentsChecked); | 331 kNumArgumentsChecked); |
340 } | 332 } |
341 compiler->GenerateInstanceCall(deopt_id, | 333 compiler->GenerateInstanceCall(deopt_id, |
342 token_pos, | 334 token_pos, |
343 kNumberOfArguments, | 335 kNumberOfArguments, |
344 kNoArgumentNames, | 336 kNoArgumentNames, |
345 locs, | 337 locs, |
346 equality_ic_data); | 338 equality_ic_data); |
347 Label check_ne; | |
348 __ jmp(&check_ne); | |
349 | |
350 __ Bind(&check_identity); | |
351 Label equality_done; | |
352 if (compiler->is_optimizing()) { | |
353 // No need to update IC data. | |
354 Label is_true; | |
355 __ popl(EAX); | |
356 __ popl(EDX); | |
357 __ cmpl(EAX, EDX); | |
358 __ j(EQUAL, &is_true); | |
359 __ LoadObject(EAX, Bool::Get(kind != Token::kEQ)); | |
360 __ jmp(&equality_done); | |
361 __ Bind(&is_true); | |
362 __ LoadObject(EAX, Bool::Get(kind == Token::kEQ)); | |
363 if (kind == Token::kNE) { | |
364 // Skip not-equal result conversion. | |
365 __ jmp(&equality_done); | |
366 } | |
367 } else { | |
368 // Call stub, load IC data in register. The stub will update ICData if | |
369 // necessary. | |
370 Register ic_data_reg = locs->temp(0).reg(); | |
371 ASSERT(ic_data_reg == ECX); // Stub depends on it. | |
372 __ LoadObject(ic_data_reg, equality_ic_data); | |
373 compiler->GenerateCall(token_pos, | |
374 &StubCode::EqualityWithNullArgLabel(), | |
375 PcDescriptors::kRuntimeCall, | |
376 locs); | |
377 __ Drop(2); | |
378 } | |
379 __ Bind(&check_ne); | |
380 if (kind == Token::kNE) { | 339 if (kind == Token::kNE) { |
381 Label true_label, done; | 340 Label true_label, done; |
382 // Negate the condition: true label returns false and vice versa. | 341 // Negate the condition: true label returns false and vice versa. |
383 __ CompareObject(EAX, Bool::True()); | 342 __ CompareObject(EAX, Bool::True()); |
384 __ j(EQUAL, &true_label, Assembler::kNearJump); | 343 __ j(EQUAL, &true_label, Assembler::kNearJump); |
385 __ LoadObject(EAX, Bool::True()); | 344 __ LoadObject(EAX, Bool::True()); |
386 __ jmp(&done, Assembler::kNearJump); | 345 __ jmp(&done, Assembler::kNearJump); |
387 __ Bind(&true_label); | 346 __ Bind(&true_label); |
388 __ LoadObject(EAX, Bool::False()); | 347 __ LoadObject(EAX, Bool::False()); |
389 __ Bind(&done); | 348 __ Bind(&done); |
390 } | 349 } |
391 __ Bind(&equality_done); | |
392 } | 350 } |
393 | 351 |
394 | 352 |
395 static void LoadValueCid(FlowGraphCompiler* compiler, | 353 static void LoadValueCid(FlowGraphCompiler* compiler, |
396 Register value_cid_reg, | 354 Register value_cid_reg, |
397 Register value_reg, | 355 Register value_reg, |
398 Label* value_is_smi = NULL) { | 356 Label* value_is_smi = NULL) { |
399 Label done; | 357 Label done; |
400 if (value_is_smi == NULL) { | 358 if (value_is_smi == NULL) { |
401 __ movl(value_cid_reg, Immediate(kSmiCid)); | 359 __ movl(value_cid_reg, Immediate(kSmiCid)); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 LocationSummary* locs, | 513 LocationSummary* locs, |
556 Token::Kind kind, | 514 Token::Kind kind, |
557 BranchInstr* branch, | 515 BranchInstr* branch, |
558 const ICData& ic_data, | 516 const ICData& ic_data, |
559 intptr_t deopt_id, | 517 intptr_t deopt_id, |
560 intptr_t token_pos) { | 518 intptr_t token_pos) { |
561 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 519 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
562 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 520 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
563 Register left = locs->in(0).reg(); | 521 Register left = locs->in(0).reg(); |
564 Register right = locs->in(1).reg(); | 522 Register right = locs->in(1).reg(); |
565 const Immediate& raw_null = | |
566 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
567 Label done, identity_compare, non_null_compare; | |
568 __ cmpl(right, raw_null); | |
569 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | |
570 __ cmpl(left, raw_null); | |
571 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | |
572 // Comparison with NULL is "===". | |
573 __ Bind(&identity_compare); | |
574 __ cmpl(left, right); | |
575 Condition cond = TokenKindToSmiCondition(kind); | |
576 if (branch != NULL) { | |
577 branch->EmitBranchOnCondition(compiler, cond); | |
578 } else { | |
579 Register result = locs->out().reg(); | |
580 Label load_true; | |
581 __ j(cond, &load_true, Assembler::kNearJump); | |
582 __ LoadObject(result, Bool::False()); | |
583 __ jmp(&done); | |
584 __ Bind(&load_true); | |
585 __ LoadObject(result, Bool::True()); | |
586 } | |
587 __ jmp(&done); | |
588 __ Bind(&non_null_compare); // Receiver is not null. | |
589 __ pushl(left); | 523 __ pushl(left); |
590 __ pushl(right); | 524 __ pushl(right); |
591 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 525 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
592 deopt_id, token_pos); | 526 deopt_id, token_pos); |
593 __ Bind(&done); | |
594 } | 527 } |
595 | 528 |
596 | 529 |
597 static Condition FlipCondition(Condition condition) { | 530 static Condition FlipCondition(Condition condition) { |
598 switch (condition) { | 531 switch (condition) { |
599 case EQUAL: return EQUAL; | 532 case EQUAL: return EQUAL; |
600 case NOT_EQUAL: return NOT_EQUAL; | 533 case NOT_EQUAL: return NOT_EQUAL; |
601 case LESS: return GREATER; | 534 case LESS: return GREATER; |
602 case LESS_EQUAL: return GREATER_EQUAL; | 535 case LESS_EQUAL: return GREATER_EQUAL; |
603 case GREATER: return LESS; | 536 case GREATER: return LESS; |
(...skipping 4629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5233 PcDescriptors::kOther, | 5166 PcDescriptors::kOther, |
5234 locs()); | 5167 locs()); |
5235 __ Drop(2); // Discard type arguments and receiver. | 5168 __ Drop(2); // Discard type arguments and receiver. |
5236 } | 5169 } |
5237 | 5170 |
5238 } // namespace dart | 5171 } // namespace dart |
5239 | 5172 |
5240 #undef __ | 5173 #undef __ |
5241 | 5174 |
5242 #endif // defined TARGET_ARCH_IA32 | 5175 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |