| 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_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/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 0, | 585 0, |
| 586 kStackOverflowRuntimeEntry); | 586 kStackOverflowRuntimeEntry); |
| 587 __ Bind(&no_stack_overflow); | 587 __ Bind(&no_stack_overflow); |
| 588 } | 588 } |
| 589 | 589 |
| 590 | 590 |
| 591 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { | 591 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { |
| 592 // Unchain the context(s) up to context level 0. | 592 // Unchain the context(s) up to context level 0. |
| 593 intptr_t current_context_level = context_level(); | 593 intptr_t current_context_level = context_level(); |
| 594 ASSERT(current_context_level >= 0); | 594 ASSERT(current_context_level >= 0); |
| 595 if (!parsed_function_.function().IsClosureFunction()) { | 595 if (parsed_function_.saved_context_var() != NULL) { |
| 596 if (current_context_level > 0) { | 596 // CTX on entry was saved, but not linked as context parent. |
| 597 // CTX on entry was saved on the stack, but not linked as context parent. | 597 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var()); |
| 598 __ popl(CTX); | |
| 599 } | |
| 600 } else { | 598 } else { |
| 601 while (current_context_level-- > 0) { | 599 while (current_context_level-- > 0) { |
| 602 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 600 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 603 } | 601 } |
| 604 } | 602 } |
| 605 #ifdef DEBUG | 603 #ifdef DEBUG |
| 606 // Check that the entry stack size matches the exit stack size. | 604 // Check that the entry stack size matches the exit stack size. |
| 607 __ movl(EDX, EBP); | 605 __ movl(EDX, EBP); |
| 608 __ subl(EDX, ESP); | 606 __ subl(EDX, ESP); |
| 609 ASSERT(locals_space_size() >= 0); | 607 ASSERT(locals_space_size() >= 0); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 // The loop local scope declares variables that are captured. | 799 // The loop local scope declares variables that are captured. |
| 802 // Allocate and chain a new context. | 800 // Allocate and chain a new context. |
| 803 __ movl(EDX, Immediate(num_context_variables)); | 801 __ movl(EDX, Immediate(num_context_variables)); |
| 804 const ExternalLabel label("alloc_context", | 802 const ExternalLabel label("alloc_context", |
| 805 StubCode::AllocateContextEntryPoint()); | 803 StubCode::AllocateContextEntryPoint()); |
| 806 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); | 804 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); |
| 807 | 805 |
| 808 // If this node_sequence is the body of the function being compiled, and if | 806 // If this node_sequence is the body of the function being compiled, and if |
| 809 // this function is not a closure, do not link the current context as the | 807 // this function is not a closure, do not link the current context as the |
| 810 // parent of the newly allocated context, as it is not accessible. Instead, | 808 // parent of the newly allocated context, as it is not accessible. Instead, |
| 811 // save it on the stack and restore it on exit. | 809 // save it in a pre-allocated variable and restore it on exit. |
| 812 if ((node_sequence == parsed_function_.node_sequence()) && | 810 if ((node_sequence == parsed_function_.node_sequence()) && |
| 813 !parsed_function_.function().IsClosureFunction()) { | 811 (parsed_function_.saved_context_var() != NULL)) { |
| 814 __ pushl(CTX); | 812 GenerateStoreVariable( |
| 813 *parsed_function_.saved_context_var(), CTX, kNoRegister); |
| 815 const Immediate raw_null = | 814 const Immediate raw_null = |
| 816 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 815 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 817 __ movl(CTX, raw_null); | 816 __ movl(CTX, raw_null); |
| 818 } | 817 } |
| 819 | 818 |
| 820 // Chain the new context in EAX to its parent in CTX. | 819 // Chain the new context in EAX to its parent in CTX. |
| 821 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); | 820 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); |
| 822 // Set new context as current context. | 821 // Set new context as current context. |
| 823 __ movl(CTX, EAX); | 822 __ movl(CTX, EAX); |
| 824 set_context_level(scope->context_level()); | 823 set_context_level(scope->context_level()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 853 // code checking the type of the actual arguments. | 852 // code checking the type of the actual arguments. |
| 854 if (FLAG_enable_type_checks && | 853 if (FLAG_enable_type_checks && |
| 855 (node_sequence == parsed_function_.node_sequence())) { | 854 (node_sequence == parsed_function_.node_sequence())) { |
| 856 GenerateArgumentTypeChecks(); | 855 GenerateArgumentTypeChecks(); |
| 857 } | 856 } |
| 858 for (int i = 0; i < node_sequence->length(); i++) { | 857 for (int i = 0; i < node_sequence->length(); i++) { |
| 859 AstNode* child_node = node_sequence->NodeAt(i); | 858 AstNode* child_node = node_sequence->NodeAt(i); |
| 860 state()->set_root_node(child_node); | 859 state()->set_root_node(child_node); |
| 861 child_node->Visit(this); | 860 child_node->Visit(this); |
| 862 } | 861 } |
| 863 if (num_context_variables > 0) { | 862 |
| 864 // Unchain the previously allocated context. | 863 // Unchain the previously allocated context. |
| 865 if ((node_sequence == parsed_function_.node_sequence()) && | 864 if ((node_sequence == parsed_function_.node_sequence()) && |
| 866 !parsed_function_.function().IsClosureFunction()) { | 865 (parsed_function_.saved_context_var() != NULL)) { |
| 867 __ popl(CTX); | 866 ASSERT(num_context_variables > 0); |
| 868 } else { | 867 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var()); |
| 869 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 868 } else if (num_context_variables > 0) { |
| 870 } | 869 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 871 } | 870 } |
| 871 |
| 872 // If this node sequence is labeled, a break out of the sequence will have | 872 // If this node sequence is labeled, a break out of the sequence will have |
| 873 // taken care of unchaining the context. | 873 // taken care of unchaining the context. |
| 874 if (node_sequence->label() != NULL) { | 874 if (node_sequence->label() != NULL) { |
| 875 __ Bind(node_sequence->label()->break_label()); | 875 __ Bind(node_sequence->label()->break_label()); |
| 876 if ((num_context_variables > 0) && | 876 |
| 877 (node_sequence == parsed_function_.node_sequence()) && | 877 // The context saved on entry must be restored. |
| 878 !parsed_function_.function().IsClosureFunction()) { | 878 if ((node_sequence == parsed_function_.node_sequence()) && |
| 879 __ popl(CTX); | 879 (parsed_function_.saved_context_var() != NULL)) { |
| 880 GenerateLoadVariable(CTX, *parsed_function_.saved_context_var()); |
| 880 } | 881 } |
| 881 } | 882 } |
| 882 set_context_level(previous_context_level); | 883 set_context_level(previous_context_level); |
| 883 } | 884 } |
| 884 | 885 |
| 885 | 886 |
| 886 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { | 887 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { |
| 887 for (int i = 0; i < arguments->length(); i++) { | 888 for (int i = 0; i < arguments->length(); i++) { |
| 888 AstNode* argument = arguments->NodeAt(i); | 889 AstNode* argument = arguments->NodeAt(i); |
| 889 argument->Visit(this); | 890 argument->Visit(this); |
| (...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2531 // and ':stacktrace_var' can never be captured variables. | 2532 // and ':stacktrace_var' can never be captured variables. |
| 2532 // Restore CTX from local variable ':saved_context'. | 2533 // Restore CTX from local variable ':saved_context'. |
| 2533 GenerateLoadVariable(CTX, node->context_var()); | 2534 GenerateLoadVariable(CTX, node->context_var()); |
| 2534 | 2535 |
| 2535 // Restore ESP from EBP as we are coming from a throw and the code for | 2536 // Restore ESP from EBP as we are coming from a throw and the code for |
| 2536 // popping arguments has not been run. | 2537 // popping arguments has not been run. |
| 2537 ASSERT(locals_space_size() >= 0); | 2538 ASSERT(locals_space_size() >= 0); |
| 2538 __ movl(ESP, EBP); | 2539 __ movl(ESP, EBP); |
| 2539 __ subl(ESP, Immediate(locals_space_size())); | 2540 __ subl(ESP, Immediate(locals_space_size())); |
| 2540 | 2541 |
| 2541 if ((context_level() > 0) && | |
| 2542 !parsed_function_.function().IsClosureFunction()) { | |
| 2543 // CTX was saved on entry. | |
| 2544 __ subl(ESP, Immediate(kWordSize)); | |
| 2545 } | |
| 2546 | |
| 2547 // The JumpToExceptionHandler trampoline code sets up | 2542 // The JumpToExceptionHandler trampoline code sets up |
| 2548 // - the exception object in EAX (kExceptionObjectReg) | 2543 // - the exception object in EAX (kExceptionObjectReg) |
| 2549 // - the stacktrace object in register EDX (kStackTraceObjectReg) | 2544 // - the stacktrace object in register EDX (kStackTraceObjectReg) |
| 2550 // We now setup the exception object and the trace object | 2545 // We now setup the exception object and the trace object |
| 2551 // so that the handler code has access to these objects. | 2546 // so that the handler code has access to these objects. |
| 2552 GenerateStoreVariable(node->exception_var(), | 2547 GenerateStoreVariable(node->exception_var(), |
| 2553 kExceptionObjectReg, | 2548 kExceptionObjectReg, |
| 2554 kNoRegister); | 2549 kNoRegister); |
| 2555 GenerateStoreVariable(node->stacktrace_var(), | 2550 GenerateStoreVariable(node->stacktrace_var(), |
| 2556 kStackTraceObjectReg, | 2551 kStackTraceObjectReg, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2687 const Error& error = Error::Handle( | 2682 const Error& error = Error::Handle( |
| 2688 Parser::FormatError(script, token_index, "Error", format, args)); | 2683 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2689 va_end(args); | 2684 va_end(args); |
| 2690 Isolate::Current()->long_jump_base()->Jump(1, error); | 2685 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2691 UNREACHABLE(); | 2686 UNREACHABLE(); |
| 2692 } | 2687 } |
| 2693 | 2688 |
| 2694 } // namespace dart | 2689 } // namespace dart |
| 2695 | 2690 |
| 2696 #endif // defined TARGET_ARCH_IA32 | 2691 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |