| 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/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 0, | 605 0, |
| 606 kStackOverflowRuntimeEntry); | 606 kStackOverflowRuntimeEntry); |
| 607 __ Bind(&no_stack_overflow); | 607 __ Bind(&no_stack_overflow); |
| 608 } | 608 } |
| 609 | 609 |
| 610 | 610 |
| 611 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { | 611 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { |
| 612 // Unchain the context(s) up to context level 0. | 612 // Unchain the context(s) up to context level 0. |
| 613 intptr_t current_context_level = context_level(); | 613 intptr_t current_context_level = context_level(); |
| 614 ASSERT(current_context_level >= 0); | 614 ASSERT(current_context_level >= 0); |
| 615 if (!parsed_function_.function().IsClosureFunction()) { | 615 if (parsed_function_.saved_context_var() != NULL) { |
| 616 if (current_context_level > 0) { | 616 // CTX on entry was saved, but not linked as context parent. |
| 617 // CTX on entry was saved on the stack, but not linked as context parent. | 617 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var()); |
| 618 __ popq(CTX); | |
| 619 } | |
| 620 } else { | 618 } else { |
| 621 while (current_context_level-- > 0) { | 619 while (current_context_level-- > 0) { |
| 622 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); | 620 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 623 } | 621 } |
| 624 } | 622 } |
| 625 #ifdef DEBUG | 623 #ifdef DEBUG |
| 626 // Check that the entry stack size matches the exit stack size. | 624 // Check that the entry stack size matches the exit stack size. |
| 627 __ movq(R10, RBP); | 625 __ movq(R10, RBP); |
| 628 __ subq(R10, RSP); | 626 __ subq(R10, RSP); |
| 629 ASSERT(locals_space_size() >= 0); | 627 ASSERT(locals_space_size() >= 0); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 // The loop local scope declares variables that are captured. | 805 // The loop local scope declares variables that are captured. |
| 808 // Allocate and chain a new context. | 806 // Allocate and chain a new context. |
| 809 __ movq(R10, Immediate(num_context_variables)); | 807 __ movq(R10, Immediate(num_context_variables)); |
| 810 const ExternalLabel label("alloc_context", | 808 const ExternalLabel label("alloc_context", |
| 811 StubCode::AllocateContextEntryPoint()); | 809 StubCode::AllocateContextEntryPoint()); |
| 812 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); | 810 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); |
| 813 | 811 |
| 814 // If this node_sequence is the body of the function being compiled, and if | 812 // If this node_sequence is the body of the function being compiled, and if |
| 815 // this function is not a closure, do not link the current context as the | 813 // this function is not a closure, do not link the current context as the |
| 816 // parent of the newly allocated context, as it is not accessible. Instead, | 814 // parent of the newly allocated context, as it is not accessible. Instead, |
| 817 // save it on the stack and restore it on exit. | 815 // save it in a pre-allocated variable and restore it on exit. |
| 818 if ((node_sequence == parsed_function_.node_sequence()) && | 816 if ((node_sequence == parsed_function_.node_sequence()) && |
| 819 !parsed_function_.function().IsClosureFunction()) { | 817 (parsed_function_.saved_context_var() != NULL)) { |
| 820 __ pushq(CTX); | 818 GenerateStoreVariable( |
| 819 *parsed_function_.saved_context_var(), CTX, kNoRegister); |
| 821 const Immediate raw_null = | 820 const Immediate raw_null = |
| 822 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 821 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 823 __ movq(CTX, raw_null); | 822 __ movq(CTX, raw_null); |
| 824 } | 823 } |
| 825 | 824 |
| 826 // Chain the new context in RAX to its parent in CTX. | 825 // Chain the new context in RAX to its parent in CTX. |
| 827 __ StoreIntoObject(RAX, | 826 __ StoreIntoObject(RAX, |
| 828 FieldAddress(RAX, Context::parent_offset()), | 827 FieldAddress(RAX, Context::parent_offset()), |
| 829 CTX); | 828 CTX); |
| 830 // Set new context as current context. | 829 // Set new context as current context. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 861 // code checking the type of the actual arguments. | 860 // code checking the type of the actual arguments. |
| 862 if (FLAG_enable_type_checks && | 861 if (FLAG_enable_type_checks && |
| 863 (node_sequence == parsed_function_.node_sequence())) { | 862 (node_sequence == parsed_function_.node_sequence())) { |
| 864 GenerateArgumentTypeChecks(); | 863 GenerateArgumentTypeChecks(); |
| 865 } | 864 } |
| 866 for (int i = 0; i < node_sequence->length(); i++) { | 865 for (int i = 0; i < node_sequence->length(); i++) { |
| 867 AstNode* child_node = node_sequence->NodeAt(i); | 866 AstNode* child_node = node_sequence->NodeAt(i); |
| 868 state()->set_root_node(child_node); | 867 state()->set_root_node(child_node); |
| 869 child_node->Visit(this); | 868 child_node->Visit(this); |
| 870 } | 869 } |
| 871 if (num_context_variables > 0) { | 870 |
| 872 // Unchain the previously allocated context. | 871 // Unchain the previously allocated context. |
| 873 if ((node_sequence == parsed_function_.node_sequence()) && | 872 if ((node_sequence == parsed_function_.node_sequence()) && |
| 874 !parsed_function_.function().IsClosureFunction()) { | 873 (parsed_function_.saved_context_var() != NULL)) { |
| 875 __ popq(CTX); | 874 ASSERT(num_context_variables > 0); |
| 876 } else { | 875 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var()); |
| 877 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); | 876 } else if (num_context_variables > 0) { |
| 878 } | 877 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 879 } | 878 } |
| 879 |
| 880 // If this node sequence is labeled, a break out of the sequence will have | 880 // If this node sequence is labeled, a break out of the sequence will have |
| 881 // taken care of unchaining the context. | 881 // taken care of unchaining the context. |
| 882 if (node_sequence->label() != NULL) { | 882 if (node_sequence->label() != NULL) { |
| 883 __ Bind(node_sequence->label()->break_label()); | 883 __ Bind(node_sequence->label()->break_label()); |
| 884 if ((num_context_variables > 0) && | 884 |
| 885 (node_sequence == parsed_function_.node_sequence()) && | 885 // The context saved on entry must be restored. |
| 886 !parsed_function_.function().IsClosureFunction()) { | 886 if ((node_sequence == parsed_function_.node_sequence()) && |
| 887 __ popq(CTX); | 887 (parsed_function_.saved_context_var() != NULL)) { |
| 888 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var()); |
| 888 } | 889 } |
| 889 } | 890 } |
| 890 set_context_level(previous_context_level); | 891 set_context_level(previous_context_level); |
| 891 } | 892 } |
| 892 | 893 |
| 893 | 894 |
| 894 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { | 895 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { |
| 895 for (int i = 0; i < arguments->length(); i++) { | 896 for (int i = 0; i < arguments->length(); i++) { |
| 896 AstNode* argument = arguments->NodeAt(i); | 897 AstNode* argument = arguments->NodeAt(i); |
| 897 argument->Visit(this); | 898 argument->Visit(this); |
| (...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2539 // and ':stacktrace_var' can never be captured variables. | 2540 // and ':stacktrace_var' can never be captured variables. |
| 2540 // Restore CTX from local variable ':saved_context'. | 2541 // Restore CTX from local variable ':saved_context'. |
| 2541 GenerateLoadVariable(CTX, node->context_var()); | 2542 GenerateLoadVariable(CTX, node->context_var()); |
| 2542 | 2543 |
| 2543 // Restore RSP from RBP as we are coming from a throw and the code for | 2544 // Restore RSP from RBP as we are coming from a throw and the code for |
| 2544 // popping arguments has not been run. | 2545 // popping arguments has not been run. |
| 2545 ASSERT(locals_space_size() >= 0); | 2546 ASSERT(locals_space_size() >= 0); |
| 2546 __ movq(RSP, RBP); | 2547 __ movq(RSP, RBP); |
| 2547 __ subq(RSP, Immediate(locals_space_size())); | 2548 __ subq(RSP, Immediate(locals_space_size())); |
| 2548 | 2549 |
| 2549 if ((context_level() > 0) && | |
| 2550 !parsed_function_.function().IsClosureFunction()) { | |
| 2551 // CTX was saved on entry. | |
| 2552 __ subq(RSP, Immediate(kWordSize)); | |
| 2553 } | |
| 2554 | |
| 2555 // The JumpToExceptionHandler trampoline code sets up | 2550 // The JumpToExceptionHandler trampoline code sets up |
| 2556 // - the exception object in RAX (kExceptionObjectReg) | 2551 // - the exception object in RAX (kExceptionObjectReg) |
| 2557 // - the stacktrace object in register RDX (kStackTraceObjectReg) | 2552 // - the stacktrace object in register RDX (kStackTraceObjectReg) |
| 2558 // We now setup the exception object and the trace object | 2553 // We now setup the exception object and the trace object |
| 2559 // so that the handler code has access to these objects. | 2554 // so that the handler code has access to these objects. |
| 2560 GenerateStoreVariable(node->exception_var(), | 2555 GenerateStoreVariable(node->exception_var(), |
| 2561 kExceptionObjectReg, | 2556 kExceptionObjectReg, |
| 2562 kNoRegister); | 2557 kNoRegister); |
| 2563 GenerateStoreVariable(node->stacktrace_var(), | 2558 GenerateStoreVariable(node->stacktrace_var(), |
| 2564 kStackTraceObjectReg, | 2559 kStackTraceObjectReg, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2695 const Error& error = Error::Handle( | 2690 const Error& error = Error::Handle( |
| 2696 Parser::FormatError(script, token_index, "Error", format, args)); | 2691 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2697 va_end(args); | 2692 va_end(args); |
| 2698 Isolate::Current()->long_jump_base()->Jump(1, error); | 2693 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2699 UNREACHABLE(); | 2694 UNREACHABLE(); |
| 2700 } | 2695 } |
| 2701 | 2696 |
| 2702 } // namespace dart | 2697 } // namespace dart |
| 2703 | 2698 |
| 2704 #endif // defined TARGET_ARCH_X64 | 2699 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |