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

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
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | 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_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/il_printer.h" 13 #include "vm/il_printer.h"
13 #include "vm/locations.h" 14 #include "vm/locations.h"
14 #include "vm/stub_code.h" 15 #include "vm/stub_code.h"
15 16
16 namespace dart { 17 namespace dart {
17 18
18 DECLARE_FLAG(bool, code_comments); 19 DECLARE_FLAG(bool, code_comments);
19 DECLARE_FLAG(bool, compiler_stats); 20 DECLARE_FLAG(bool, compiler_stats);
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 402
402 void FlowGraphCompiler::GenerateCall(intptr_t token_index, 403 void FlowGraphCompiler::GenerateCall(intptr_t token_index,
403 intptr_t try_index, 404 intptr_t try_index,
404 const ExternalLabel* label, 405 const ExternalLabel* label,
405 PcDescriptors::Kind kind) { 406 PcDescriptors::Kind kind) {
406 __ call(label); 407 __ call(label);
407 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); 408 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index);
408 } 409 }
409 410
410 411
412 // If instanceof type test cannot be performed successfully at compile time and
413 // therefore eliminated, optimize it by adding inlined tests for:
414 // - NULL -> return false.
415 // - Smi -> compile time subtype check (only if dst class is not parameterized).
416 // - Class equality (only if class is not parameterized).
417 // Inputs:
418 // - EAX: object.
419 // - EDX: instantiator type arguments or raw_null.
420 // - ECX: instantiator or raw_null.
421 // Returns:
422 // - true or false in EAX.
423 void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid,
424 intptr_t token_index,
425 intptr_t try_index,
426 const AbstractType& type,
427 bool negate_result) {
428 ASSERT(type.IsFinalized() && !type.IsMalformed());
429 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
430 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
431
432 const Immediate raw_null =
433 Immediate(reinterpret_cast<intptr_t>(Object::null()));
434 Label is_instance, is_not_instance;
435 __ pushl(ECX); // Store instantiator on stack.
436 __ pushl(EDX); // Store instantiator type arguments.
437 // If type is instantiated and non-parameterized, we can inline code
438 // checking whether the tested instance is a Smi.
439 if (type.IsInstantiated()) {
440 // A null object is only an instance of Object and Dynamic, which has
441 // already been checked above (if the type is instantiated). So we can
442 // return false here if the instance is null (and if the type is
443 // instantiated).
444 // We can only inline this null check if the type is instantiated at compile
445 // time, since an uninstantiated type at compile time could be Object or
446 // Dynamic at run time.
447 __ cmpl(EAX, raw_null);
448 __ j(EQUAL, &is_not_instance);
449 }
450 // TODO(srdjan): Enable inlined checks.
451 // Generate inline instanceof test.
452 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
453 // test_cache = GenerateInlineInstanceof(cid, token_index, type,
454 // &is_instance, &is_not_instance);
455
456 // Generate runtime call.
457 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
458 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
459 __ PushObject(Object::ZoneHandle()); // Make room for the result.
460 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
461 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
462 __ pushl(EAX); // Push the instance.
463 __ PushObject(type); // Push the type.
464 __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null.
465 __ pushl(EDX); // Instantiator type arguments.
466 __ LoadObject(EAX, test_cache);
467 __ pushl(EAX);
468 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry);
469 // Pop the two parameters supplied to the runtime entry. The result of the
470 // instanceof runtime call will be left as the result of the operation.
471 __ Drop(7);
472 Label done;
473 if (negate_result) {
474 __ popl(EDX);
475 __ LoadObject(EAX, bool_true);
476 __ cmpl(EDX, EAX);
477 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
478 __ LoadObject(EAX, bool_false);
479 } else {
480 __ popl(EAX);
481 }
482 __ jmp(&done, Assembler::kNearJump);
483
484 __ Bind(&is_not_instance);
485 __ LoadObject(EAX, negate_result ? bool_true : bool_false);
486 __ jmp(&done, Assembler::kNearJump);
487
488 __ Bind(&is_instance);
489 __ LoadObject(EAX, negate_result ? bool_false : bool_true);
490 __ Bind(&done);
491 __ popl(EDX); // Remove pushed instantiator type arguments.
492 __ popl(ECX); // Remove pushed instantiator.
493 }
494
495
496 // Optimize assignable type check by adding inlined tests for:
497 // - NULL -> return NULL.
498 // - Smi -> compile time subtype check (only if dst class is not parameterized).
499 // - Class equality (only if class is not parameterized).
500 // Inputs:
501 // - EAX: object.
502 // - EDX: instantiator type arguments or raw_null.
503 // - ECX: instantiator or raw_null.
504 // Returns:
505 // - object in EAX for successful assignable check (or throws TypeError).
506 // Performance notes: positive checks must be quick, negative checks can be slow
507 // as they throw an exception.
508 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid,
509 intptr_t token_index,
510 intptr_t try_index,
511 const AbstractType& dst_type,
512 const String& dst_name) {
513 ASSERT(FLAG_enable_type_checks);
514 ASSERT(token_index >= 0);
515 ASSERT(!dst_type.IsNull());
516 ASSERT(dst_type.IsFinalized());
517 // Assignable check is skipped in FlowGraphBuilder, not here.
518 ASSERT(dst_type.IsMalformed() ||
519 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
520 ASSERT(!dst_type.IsVoidType());
521 __ pushl(ECX); // Store instantiator.
522 __ pushl(EDX); // Store instantiator type arguments.
523 // A null object is always assignable and is returned as result.
524 const Immediate raw_null =
525 Immediate(reinterpret_cast<intptr_t>(Object::null()));
526 Label is_assignable, runtime_call;
527 __ cmpl(EAX, raw_null);
528 __ j(EQUAL, &is_assignable);
529
530 // Generate throw new TypeError() if the type is malformed.
531 if (dst_type.IsMalformed()) {
532 const Error& error = Error::Handle(dst_type.malformed_error());
533 const String& error_message = String::ZoneHandle(
534 String::NewSymbol(error.ToErrorCString()));
535 __ PushObject(Object::ZoneHandle()); // Make room for the result.
536 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
537 __ pushl(EAX); // Push the source object.
538 __ PushObject(dst_name); // Push the name of the destination.
539 __ PushObject(error_message);
540 GenerateCallRuntime(cid,
541 token_index,
542 try_index,
543 kMalformedTypeErrorRuntimeEntry);
544 // We should never return here.
545 __ int3();
546
547 __ Bind(&is_assignable); // For a null object.
548 return;
549 }
550
551 // TODO(srdjan): Enable subtype test cache.
552 // Generate inline type check, linking to runtime call if not assignable.
553 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
554 // test_cache = GenerateInlineInstanceof(cid, token_index, dst_type,
555 // &is_assignable, &runtime_call);
556
557 __ Bind(&runtime_call);
558 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
559 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
560 __ PushObject(Object::ZoneHandle()); // Make room for the result.
561 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
562 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
563 __ pushl(EAX); // Push the source object.
564 __ PushObject(dst_type); // Push the type of the destination.
565 __ pushl(ECX); // Instantiator.
566 __ pushl(EDX); // Instantiator type arguments.
567 __ PushObject(dst_name); // Push the name of the destination.
568 __ LoadObject(EAX, test_cache);
569 __ pushl(EAX);
570 GenerateCallRuntime(cid,
571 token_index,
572 try_index,
573 kTypeCheckRuntimeEntry);
574 // Pop the parameters supplied to the runtime entry. The result of the
575 // type check runtime call is the checked value.
576 __ Drop(8);
577 __ popl(EAX);
578
579 __ Bind(&is_assignable);
580 __ popl(EDX); // Remove pushed instantiator type arguments..
581 __ popl(ECX); // Remove pushed instantiator.
582 }
583
584
411 void FlowGraphCompiler::EmitComment(Instruction* instr) { 585 void FlowGraphCompiler::EmitComment(Instruction* instr) {
412 char buffer[80]; 586 char buffer[80];
413 BufferFormatter f(buffer, sizeof(buffer)); 587 BufferFormatter f(buffer, sizeof(buffer));
414 instr->PrintTo(&f); 588 instr->PrintTo(&f);
415 __ Comment("@%d: %s", instr->cid(), buffer); 589 __ Comment("@%d: %s", instr->cid(), buffer);
416 } 590 }
417 591
418 592
419 void FlowGraphCompiler::BailoutOnInstruction(Instruction* instr) { 593 void FlowGraphCompiler::BailoutOnInstruction(Instruction* instr) {
420 char buffer[80]; 594 char buffer[80];
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 } 642 }
469 } 643 }
470 } 644 }
471 } 645 }
472 646
473 #undef __ 647 #undef __
474 648
475 } // namespace dart 649 } // namespace dart
476 650
477 #endif // defined TARGET_ARCH_IA32 651 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698