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

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

Issue 10466006: Implemented in ia32: branch, strict compare, instance setter, instanceof and assertassigneable with… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h"
10 #include "vm/ast_printer.h" 11 #include "vm/ast_printer.h"
11 #include "vm/compiler_stats.h" 12 #include "vm/compiler_stats.h"
12 #include "vm/debugger.h" 13 #include "vm/debugger.h"
13 #include "vm/il_printer.h" 14 #include "vm/il_printer.h"
14 #include "vm/intrinsifier.h" 15 #include "vm/intrinsifier.h"
15 #include "vm/locations.h" 16 #include "vm/locations.h"
16 #include "vm/longjump.h" 17 #include "vm/longjump.h"
17 #include "vm/stub_code.h" 18 #include "vm/stub_code.h"
18 19
19 namespace dart { 20 namespace dart {
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 499
499 void FlowGraphCompiler::GenerateCall(intptr_t token_index, 500 void FlowGraphCompiler::GenerateCall(intptr_t token_index,
500 intptr_t try_index, 501 intptr_t try_index,
501 const ExternalLabel* label, 502 const ExternalLabel* label,
502 PcDescriptors::Kind kind) { 503 PcDescriptors::Kind kind) {
503 __ call(label); 504 __ call(label);
504 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); 505 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index);
505 } 506 }
506 507
507 508
509 // If instanceof type test cannot be performed successfully at compile time and
510 // therefore eliminated, optimize it by adding inlined tests for:
511 // - NULL -> return false.
512 // - Smi -> compile time subtype check (only if dst class is not parameterized).
513 // - Class equality (only if class is not parameterized).
514 // Inputs:
515 // - EAX: object.
516 // - EDX: instantiator type arguments or raw_null.
517 // - ECX: instantiator or raw_null.
518 // Returns:
519 // - true or false in EAX.
520 void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid,
521 intptr_t token_index,
522 intptr_t try_index,
523 const AbstractType& type,
524 bool negate_result) {
525 ASSERT(type.IsFinalized() && !type.IsMalformed());
526 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
527 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
528
529 const Immediate raw_null =
530 Immediate(reinterpret_cast<intptr_t>(Object::null()));
531 Label is_instance, is_not_instance;
532 __ pushl(ECX); // Store instantiator on stack.
533 __ pushl(EDX); // Store instantiator type arguments.
534 // If type is instantiated and non-parameterized, we can inline code
535 // checking whether the tested instance is a Smi.
536 if (type.IsInstantiated()) {
537 // A null object is only an instance of Object and Dynamic, which has
538 // already been checked above (if the type is instantiated). So we can
539 // return false here if the instance is null (and if the type is
540 // instantiated).
541 // We can only inline this null check if the type is instantiated at compile
542 // time, since an uninstantiated type at compile time could be Object or
543 // Dynamic at run time.
544 __ cmpl(EAX, raw_null);
545 __ j(EQUAL, &is_not_instance);
546 }
547 // TODO(srdjan): Enable inlined checks.
548 // Generate inline instanceof test.
549 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
550 // test_cache = GenerateInlineInstanceof(cid, token_index, type,
551 // &is_instance, &is_not_instance);
552
553 // Generate runtime call.
554 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
555 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
556 __ PushObject(Object::ZoneHandle()); // Make room for the result.
557 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
558 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
559 __ pushl(EAX); // Push the instance.
560 __ PushObject(type); // Push the type.
561 __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null.
562 __ pushl(EDX); // Instantiator type arguments.
563 __ LoadObject(EAX, test_cache);
564 __ pushl(EAX);
565 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry);
566 // Pop the two parameters supplied to the runtime entry. The result of the
567 // instanceof runtime call will be left as the result of the operation.
568 __ Drop(7);
569 Label done;
570 if (negate_result) {
571 __ popl(EDX);
572 __ LoadObject(EAX, bool_true);
573 __ cmpl(EDX, EAX);
574 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
575 __ LoadObject(EAX, bool_false);
576 } else {
577 __ popl(EAX);
578 }
579 __ jmp(&done, Assembler::kNearJump);
580
581 __ Bind(&is_not_instance);
582 __ LoadObject(EAX, negate_result ? bool_true : bool_false);
583 __ jmp(&done, Assembler::kNearJump);
584
585 __ Bind(&is_instance);
586 __ LoadObject(EAX, negate_result ? bool_false : bool_true);
587 __ Bind(&done);
588 __ popl(EDX); // Remove pushed instantiator type arguments.
589 __ popl(ECX); // Remove pushed instantiator.
590 }
591
592
593 // Optimize assignable type check by adding inlined tests for:
594 // - NULL -> return NULL.
595 // - Smi -> compile time subtype check (only if dst class is not parameterized).
596 // - Class equality (only if class is not parameterized).
597 // Inputs:
598 // - EAX: object.
599 // - EDX: instantiator type arguments or raw_null.
600 // - ECX: instantiator or raw_null.
601 // Returns:
602 // - object in EAX for successful assignable check (or throws TypeError).
603 // Performance notes: positive checks must be quick, negative checks can be slow
604 // as they throw an exception.
605 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid,
606 intptr_t token_index,
607 intptr_t try_index,
608 const AbstractType& dst_type,
609 const String& dst_name) {
610 ASSERT(FLAG_enable_type_checks);
611 ASSERT(token_index >= 0);
612 ASSERT(!dst_type.IsNull());
613 ASSERT(dst_type.IsFinalized());
614 // Assignable check is skipped in FlowGraphBuilder, not here.
615 ASSERT(dst_type.IsMalformed() ||
616 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
617 ASSERT(!dst_type.IsVoidType());
618 __ pushl(ECX); // Store instantiator.
619 __ pushl(EDX); // Store instantiator type arguments.
620 // A null object is always assignable and is returned as result.
621 const Immediate raw_null =
622 Immediate(reinterpret_cast<intptr_t>(Object::null()));
623 Label is_assignable, runtime_call;
624 __ cmpl(EAX, raw_null);
625 __ j(EQUAL, &is_assignable);
626
627 // Generate throw new TypeError() if the type is malformed.
628 if (dst_type.IsMalformed()) {
629 const Error& error = Error::Handle(dst_type.malformed_error());
630 const String& error_message = String::ZoneHandle(
631 String::NewSymbol(error.ToErrorCString()));
632 __ PushObject(Object::ZoneHandle()); // Make room for the result.
633 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
634 __ pushl(EAX); // Push the source object.
635 __ PushObject(dst_name); // Push the name of the destination.
636 __ PushObject(error_message);
637 GenerateCallRuntime(cid,
638 token_index,
639 try_index,
640 kMalformedTypeErrorRuntimeEntry);
641 // We should never return here.
642 __ int3();
643
644 __ Bind(&is_assignable); // For a null object.
645 return;
646 }
647
648 // TODO(srdjan): Enable subtype test cache.
649 // Generate inline type check, linking to runtime call if not assignable.
650 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
651 // test_cache = GenerateInlineInstanceof(cid, token_index, dst_type,
652 // &is_assignable, &runtime_call);
653
654 __ Bind(&runtime_call);
655 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
656 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
657 __ PushObject(Object::ZoneHandle()); // Make room for the result.
658 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
659 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
660 __ pushl(EAX); // Push the source object.
661 __ PushObject(dst_type); // Push the type of the destination.
662 __ pushl(ECX); // Instantiator.
663 __ pushl(EDX); // Instantiator type arguments.
664 __ PushObject(dst_name); // Push the name of the destination.
665 __ LoadObject(EAX, test_cache);
666 __ pushl(EAX);
667 GenerateCallRuntime(cid,
668 token_index,
669 try_index,
670 kTypeCheckRuntimeEntry);
671 // Pop the parameters supplied to the runtime entry. The result of the
672 // type check runtime call is the checked value.
673 __ Drop(8);
674 __ popl(EAX);
675
676 __ Bind(&is_assignable);
677 __ popl(EDX); // Remove pushed instantiator type arguments..
678 __ popl(ECX); // Remove pushed instantiator.
679 }
680
681
508 void FlowGraphCompiler::EmitComment(Instruction* instr) { 682 void FlowGraphCompiler::EmitComment(Instruction* instr) {
509 char buffer[80]; 683 char buffer[80];
510 BufferFormatter f(buffer, sizeof(buffer)); 684 BufferFormatter f(buffer, sizeof(buffer));
511 instr->PrintTo(&f); 685 instr->PrintTo(&f);
512 __ Comment("@%d: %s", instr->cid(), buffer); 686 __ Comment("@%d: %s", instr->cid(), buffer);
513 } 687 }
514 688
515 689
516 void FlowGraphCompiler::BailoutOnInstruction(Instruction* instr) { 690 void FlowGraphCompiler::BailoutOnInstruction(Instruction* instr) {
517 char buffer[80]; 691 char buffer[80];
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 } 739 }
566 } 740 }
567 } 741 }
568 } 742 }
569 743
570 #undef __ 744 #undef __
571 745
572 } // namespace dart 746 } // namespace dart
573 747
574 #endif // defined TARGET_ARCH_IA32 748 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698