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 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1513 __ jmp(&null_args_loop_condition, Assembler::kNearJump); | 1519 __ jmp(&null_args_loop_condition, Assembler::kNearJump); |
1514 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize); | 1520 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize); |
1515 __ Bind(&null_args_loop); | 1521 __ Bind(&null_args_loop); |
1516 __ movq(original_argument_addr, raw_null); | 1522 __ movq(original_argument_addr, raw_null); |
1517 __ Bind(&null_args_loop_condition); | 1523 __ Bind(&null_args_loop_condition); |
1518 __ decq(RCX); | 1524 __ decq(RCX); |
1519 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); | 1525 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); |
1520 } | 1526 } |
1521 | 1527 |
1522 | 1528 |
1529 bool FlowGraphCompiler::CanOptimize() { | |
1530 return | |
1531 !FLAG_report_usage_count && | |
1532 (FLAG_optimization_counter_threshold >= 0) && | |
1533 !Isolate::Current()->debugger()->IsActive(); | |
1534 } | |
1535 | |
1536 | |
1537 void FlowGraphCompiler::IntrinsifyGetter() { | |
1538 // TOS: return address. | |
1539 // +1 : receiver. | |
1540 // Sequence node has one return node, its input is oad field node. | |
regis
2012/04/17 21:15:31
oad?
srdjan
2012/04/17 21:37:54
toad? road? aaaah .. load!
| |
1541 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | |
1542 ASSERT(sequence_node.length() == 1); | |
1543 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); | |
1544 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); | |
1545 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); | |
1546 const LoadInstanceFieldNode& load_node = | |
1547 *return_node.value()->AsLoadInstanceFieldNode(); | |
1548 __ movq(RAX, Address(RSP, 1 * kWordSize)); | |
1549 __ movq(RAX, FieldAddress(RAX, load_node.field().Offset())); | |
1550 __ ret(); | |
1551 } | |
1552 | |
1553 | |
1554 void FlowGraphCompiler::IntrinsifySetter() { | |
1555 // TOS: return address. | |
1556 // +1 : value | |
1557 // +2 : receiver. | |
1558 // Sequence node has one store node and one return NULL node. | |
1559 const SequenceNode& sequence_node = *parsed_function_.node_sequence(); | |
1560 ASSERT(sequence_node.length() == 2); | |
1561 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); | |
1562 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); | |
1563 const StoreInstanceFieldNode& store_node = | |
1564 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); | |
1565 __ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver. | |
1566 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value. | |
1567 __ StoreIntoObject(RAX, FieldAddress(RAX, store_node.field().Offset()), RBX); | |
1568 const Immediate raw_null = | |
1569 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
1570 __ movq(RAX, raw_null); | |
1571 __ ret(); | |
1572 } | |
1573 | |
1574 | |
1575 // Returns 'true' if code generation for this function is complete, i.e., | |
1576 // no fall-through to regular code is needed. | |
1577 bool FlowGraphCompiler::TryIntrinsify() { | |
1578 if (!CanOptimize()) return false; | |
1579 // Intrinsification skips arguments checks, therefore disable if in checked | |
1580 // mode. | |
1581 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) { | |
1582 if ((parsed_function_.function().kind() == RawFunction::kImplicitGetter)) { | |
1583 IntrinsifyGetter(); | |
1584 return true; | |
1585 } | |
1586 if ((parsed_function_.function().kind() == RawFunction::kImplicitSetter)) { | |
1587 IntrinsifySetter(); | |
1588 return true; | |
1589 } | |
1590 } | |
1591 // Even if an intrinsified version of the function was successfully | |
1592 // generated, it may fall through to the non-intrinsified method body. | |
1593 if (!FLAG_trace_functions) { | |
1594 return Intrinsifier::Intrinsify(parsed_function_.function(), assembler_); | |
1595 } | |
1596 return false; | |
1597 } | |
1598 | |
1599 | |
1523 // TODO(srdjan): Investigate where to put the argument type checks for | 1600 // TODO(srdjan): Investigate where to put the argument type checks for |
1524 // checked mode. | 1601 // checked mode. |
1525 void FlowGraphCompiler::CompileGraph() { | 1602 void FlowGraphCompiler::CompileGraph() { |
1603 if (TryIntrinsify()) { | |
1604 // Make it patchable. | |
1605 __ nop(2); | |
regis
2012/04/17 21:15:31
Why 2?
srdjan
2012/04/17 21:37:54
Patcheable entry needs certain code size. nop(2)
| |
1606 __ int3(); | |
1607 __ jmp(&StubCode::FixCallersTargetLabel()); | |
1608 return; | |
1609 } | |
1526 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 1610 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
1527 const Function& function = parsed_function_.function(); | 1611 const Function& function = parsed_function_.function(); |
1528 | 1612 |
1529 const int parameter_count = function.num_fixed_parameters(); | 1613 const int parameter_count = function.num_fixed_parameters(); |
1530 const int num_copied_params = parsed_function_.copied_parameter_count(); | 1614 const int num_copied_params = parsed_function_.copied_parameter_count(); |
1531 const int local_count = parsed_function_.stack_local_count(); | 1615 const int local_count = parsed_function_.stack_local_count(); |
1532 __ EnterFrame(StackSize() * kWordSize); | 1616 __ EnterFrame(StackSize() * kWordSize); |
1533 | 1617 |
1534 // 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 |
1535 // 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... | |
1659 ASSERT(exception_handlers_list_ != NULL); | 1743 ASSERT(exception_handlers_list_ != NULL); |
1660 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1744 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
1661 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1745 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
1662 code.set_exception_handlers(handlers); | 1746 code.set_exception_handlers(handlers); |
1663 } | 1747 } |
1664 | 1748 |
1665 | 1749 |
1666 } // namespace dart | 1750 } // namespace dart |
1667 | 1751 |
1668 #endif // defined TARGET_ARCH_X64 | 1752 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |