OLD | NEW |
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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
11 #include "vm/ast_printer.h" | 11 #include "vm/ast_printer.h" |
12 #include "vm/code_descriptors.h" | 12 #include "vm/code_descriptors.h" |
13 #include "vm/code_generator.h" | 13 #include "vm/code_generator.h" |
| 14 #include "vm/debugger.h" |
14 #include "vm/disassembler.h" | 15 #include "vm/disassembler.h" |
| 16 #include "vm/intrinsifier.h" |
15 #include "vm/longjump.h" | 17 #include "vm/longjump.h" |
16 #include "vm/object_store.h" | 18 #include "vm/object_store.h" |
17 #include "vm/parser.h" | 19 #include "vm/parser.h" |
18 #include "vm/stub_code.h" | 20 #include "vm/stub_code.h" |
19 | 21 |
20 namespace dart { | 22 namespace dart { |
21 | 23 |
22 DECLARE_FLAG(bool, enable_type_checks); | 24 DECLARE_FLAG(bool, enable_type_checks); |
| 25 DECLARE_FLAG(bool, intrinsify); |
| 26 DECLARE_FLAG(bool, optimization_counter_threshold); |
23 DECLARE_FLAG(bool, print_ast); | 27 DECLARE_FLAG(bool, print_ast); |
24 DECLARE_FLAG(bool, print_scopes); | 28 DECLARE_FLAG(bool, print_scopes); |
| 29 DECLARE_FLAG(bool, report_usage_count); |
25 DECLARE_FLAG(bool, trace_functions); | 30 DECLARE_FLAG(bool, trace_functions); |
26 | 31 |
| 32 |
27 FlowGraphCompiler::FlowGraphCompiler( | 33 FlowGraphCompiler::FlowGraphCompiler( |
28 Assembler* assembler, | 34 Assembler* assembler, |
29 const ParsedFunction& parsed_function, | 35 const ParsedFunction& parsed_function, |
30 const GrowableArray<BlockEntryInstr*>& block_order) | 36 const GrowableArray<BlockEntryInstr*>& block_order) |
31 : FlowGraphVisitor(block_order), | 37 : FlowGraphVisitor(block_order), |
32 assembler_(assembler), | 38 assembler_(assembler), |
33 parsed_function_(parsed_function), | 39 parsed_function_(parsed_function), |
34 block_info_(block_order.length()), | 40 block_info_(block_order.length()), |
35 current_block_(NULL), | 41 current_block_(NULL), |
36 pc_descriptors_list_(new DescriptorList()), | 42 pc_descriptors_list_(new DescriptorList()), |
(...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 __ jmp(&null_args_loop_condition, Assembler::kNearJump); | 1518 __ jmp(&null_args_loop_condition, Assembler::kNearJump); |
1513 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize); | 1519 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize); |
1514 __ Bind(&null_args_loop); | 1520 __ Bind(&null_args_loop); |
1515 __ movq(original_argument_addr, raw_null); | 1521 __ movq(original_argument_addr, raw_null); |
1516 __ Bind(&null_args_loop_condition); | 1522 __ Bind(&null_args_loop_condition); |
1517 __ decq(RCX); | 1523 __ decq(RCX); |
1518 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); | 1524 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); |
1519 } | 1525 } |
1520 | 1526 |
1521 | 1527 |
| 1528 bool FlowGraphCompiler::CanOptimize() { |
| 1529 return |
| 1530 !FLAG_report_usage_count && |
| 1531 (FLAG_optimization_counter_threshold >= 0) && |
| 1532 !Isolate::Current()->debugger()->IsActive(); |
| 1533 } |
| 1534 |
| 1535 |
| 1536 void FlowGraphCompiler::IntrinsifyGetter() { |
| 1537 // TOS: return address. |
| 1538 // +1 : receiver. |
| 1539 // Sequence node has one return node, its input is load field node. |
| 1540 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); |
| 1541 ASSERT(sequence_node.length() == 1); |
| 1542 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); |
| 1543 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); |
| 1544 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); |
| 1545 const LoadInstanceFieldNode& load_node = |
| 1546 *return_node.value()->AsLoadInstanceFieldNode(); |
| 1547 __ movq(RAX, Address(RSP, 1 * kWordSize)); |
| 1548 __ movq(RAX, FieldAddress(RAX, load_node.field().Offset())); |
| 1549 __ ret(); |
| 1550 } |
| 1551 |
| 1552 |
| 1553 void FlowGraphCompiler::IntrinsifySetter() { |
| 1554 // TOS: return address. |
| 1555 // +1 : value |
| 1556 // +2 : receiver. |
| 1557 // Sequence node has one store node and one return NULL node. |
| 1558 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); |
| 1559 ASSERT(sequence_node.length() == 2); |
| 1560 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); |
| 1561 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); |
| 1562 const StoreInstanceFieldNode& store_node = |
| 1563 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); |
| 1564 __ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver. |
| 1565 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value. |
| 1566 __ StoreIntoObject(RAX, FieldAddress(RAX, store_node.field().Offset()), RBX); |
| 1567 const Immediate raw_null = |
| 1568 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1569 __ movq(RAX, raw_null); |
| 1570 __ ret(); |
| 1571 } |
| 1572 |
| 1573 |
| 1574 // Returns 'true' if code generation for this function is complete, i.e., |
| 1575 // no fall-through to regular code is needed. |
| 1576 bool FlowGraphCompiler::TryIntrinsify() { |
| 1577 if (!CanOptimize()) return false; |
| 1578 // Intrinsification skips arguments checks, therefore disable if in checked |
| 1579 // mode. |
| 1580 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) { |
| 1581 if ((parsed_function_.function().kind() == RawFunction::kImplicitGetter)) { |
| 1582 IntrinsifyGetter(); |
| 1583 return true; |
| 1584 } |
| 1585 if ((parsed_function_.function().kind() == RawFunction::kImplicitSetter)) { |
| 1586 IntrinsifySetter(); |
| 1587 return true; |
| 1588 } |
| 1589 } |
| 1590 // Even if an intrinsified version of the function was successfully |
| 1591 // generated, it may fall through to the non-intrinsified method body. |
| 1592 if (!FLAG_trace_functions) { |
| 1593 return Intrinsifier::Intrinsify(parsed_function_.function(), assembler_); |
| 1594 } |
| 1595 return false; |
| 1596 } |
| 1597 |
| 1598 |
1522 // TODO(srdjan): Investigate where to put the argument type checks for | 1599 // TODO(srdjan): Investigate where to put the argument type checks for |
1523 // checked mode. | 1600 // checked mode. |
1524 void FlowGraphCompiler::CompileGraph() { | 1601 void FlowGraphCompiler::CompileGraph() { |
| 1602 if (TryIntrinsify()) { |
| 1603 // Make it patchable: code must have a minimum code size, nop(2) increases |
| 1604 // the minimum code size appropriately. |
| 1605 __ nop(2); |
| 1606 __ int3(); |
| 1607 __ jmp(&StubCode::FixCallersTargetLabel()); |
| 1608 return; |
| 1609 } |
1525 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 1610 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
1526 const Function& function = parsed_function_.function(); | 1611 const Function& function = parsed_function_.function(); |
1527 | 1612 |
1528 const int parameter_count = function.num_fixed_parameters(); | 1613 const int parameter_count = function.num_fixed_parameters(); |
1529 const int num_copied_params = parsed_function_.copied_parameter_count(); | 1614 const int num_copied_params = parsed_function_.copied_parameter_count(); |
1530 const int local_count = parsed_function_.stack_local_count(); | 1615 const int local_count = parsed_function_.stack_local_count(); |
1531 __ EnterFrame(StackSize() * kWordSize); | 1616 __ EnterFrame(StackSize() * kWordSize); |
1532 | 1617 |
1533 // We check the number of passed arguments when we have to copy them due to | 1618 // We check the number of passed arguments when we have to copy them due to |
1534 // the presence of optional named parameters. | 1619 // the presence of optional named parameters. |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1658 ASSERT(exception_handlers_list_ != NULL); | 1743 ASSERT(exception_handlers_list_ != NULL); |
1659 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1744 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
1660 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1745 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
1661 code.set_exception_handlers(handlers); | 1746 code.set_exception_handlers(handlers); |
1662 } | 1747 } |
1663 | 1748 |
1664 | 1749 |
1665 } // namespace dart | 1750 } // namespace dart |
1666 | 1751 |
1667 #endif // defined TARGET_ARCH_X64 | 1752 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |