| 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 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 0, | 588 0, |
| 589 kStackOverflowRuntimeEntry); | 589 kStackOverflowRuntimeEntry); |
| 590 __ Bind(&no_stack_overflow); | 590 __ Bind(&no_stack_overflow); |
| 591 } | 591 } |
| 592 | 592 |
| 593 | 593 |
| 594 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { | 594 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { |
| 595 // Unchain the context(s) up to context level 0. | 595 // Unchain the context(s) up to context level 0. |
| 596 int context_level = state()->context_level(); | 596 int context_level = state()->context_level(); |
| 597 ASSERT(context_level >= 0); | 597 ASSERT(context_level >= 0); |
| 598 while (context_level-- > 0) { | 598 if (!parsed_function_.function().IsClosureFunction()) { |
| 599 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 599 if (context_level > 0) { |
| 600 // CTX on entry was saved on the stack, but not linked as context parent. |
| 601 __ popl(CTX); |
| 602 } |
| 603 } else { |
| 604 while (context_level-- > 0) { |
| 605 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 606 } |
| 600 } | 607 } |
| 601 #ifdef DEBUG | 608 #ifdef DEBUG |
| 602 // Check that the entry stack size matches the exit stack size. | 609 // Check that the entry stack size matches the exit stack size. |
| 603 __ movl(EDX, EBP); | 610 __ movl(EDX, EBP); |
| 604 __ subl(EDX, ESP); | 611 __ subl(EDX, ESP); |
| 605 ASSERT(locals_space_size() >= 0); | 612 ASSERT(locals_space_size() >= 0); |
| 606 __ cmpl(EDX, Immediate(locals_space_size())); | 613 __ cmpl(EDX, Immediate(locals_space_size())); |
| 607 Label wrong_stack; | 614 Label wrong_stack; |
| 608 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump); | 615 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump); |
| 609 #endif // DEBUG. | 616 #endif // DEBUG. |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 const intptr_t num_context_variables = | 800 const intptr_t num_context_variables = |
| 794 (scope != NULL) ? scope->num_context_variables() : 0; | 801 (scope != NULL) ? scope->num_context_variables() : 0; |
| 795 if (num_context_variables > 0) { | 802 if (num_context_variables > 0) { |
| 796 // The loop local scope declares variables that are captured. | 803 // The loop local scope declares variables that are captured. |
| 797 // Allocate and chain a new context. | 804 // Allocate and chain a new context. |
| 798 __ movl(EDX, Immediate(num_context_variables)); | 805 __ movl(EDX, Immediate(num_context_variables)); |
| 799 const ExternalLabel label("alloc_context", | 806 const ExternalLabel label("alloc_context", |
| 800 StubCode::AllocateContextEntryPoint()); | 807 StubCode::AllocateContextEntryPoint()); |
| 801 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); | 808 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); |
| 802 | 809 |
| 810 // If this node_sequence is the body of the function being compiled, and if |
| 811 // this function is not a closure, do not link the current context as the |
| 812 // parent of the newly allocated context, as it is not accessible. Instead, |
| 813 // save it on the stack and restore it on exit. |
| 814 if ((node_sequence == parsed_function_.node_sequence()) && |
| 815 !parsed_function_.function().IsClosureFunction()) { |
| 816 __ pushl(CTX); |
| 817 const Immediate raw_null = |
| 818 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 819 __ movl(CTX, raw_null); |
| 820 } |
| 821 |
| 803 // Chain the new context in EAX to its parent in CTX. | 822 // Chain the new context in EAX to its parent in CTX. |
| 804 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); | 823 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); |
| 805 // Set new context as current context. | 824 // Set new context as current context. |
| 806 __ movl(CTX, EAX); | 825 __ movl(CTX, EAX); |
| 807 state()->set_context_level(scope->context_level()); | 826 state()->set_context_level(scope->context_level()); |
| 808 | 827 |
| 809 // If this node_sequence is the body of the function being compiled, copy | 828 // If this node_sequence is the body of the function being compiled, copy |
| 810 // the captured parameters from the frame into the context. | 829 // the captured parameters from the frame into the context. |
| 811 if (node_sequence == parsed_function_.node_sequence()) { | 830 if (node_sequence == parsed_function_.node_sequence()) { |
| 812 ASSERT(scope->context_level() == 1); | 831 ASSERT(scope->context_level() == 1); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 838 (node_sequence == parsed_function_.node_sequence())) { | 857 (node_sequence == parsed_function_.node_sequence())) { |
| 839 GenerateArgumentTypeChecks(); | 858 GenerateArgumentTypeChecks(); |
| 840 } | 859 } |
| 841 for (int i = 0; i < node_sequence->length(); i++) { | 860 for (int i = 0; i < node_sequence->length(); i++) { |
| 842 AstNode* child_node = node_sequence->NodeAt(i); | 861 AstNode* child_node = node_sequence->NodeAt(i); |
| 843 state()->set_root_node(child_node); | 862 state()->set_root_node(child_node); |
| 844 child_node->Visit(this); | 863 child_node->Visit(this); |
| 845 } | 864 } |
| 846 if (num_context_variables > 0) { | 865 if (num_context_variables > 0) { |
| 847 // Unchain the previously allocated context. | 866 // Unchain the previously allocated context. |
| 848 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 867 if ((node_sequence == parsed_function_.node_sequence()) && |
| 868 !parsed_function_.function().IsClosureFunction()) { |
| 869 __ popl(CTX); |
| 870 } else { |
| 871 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 872 } |
| 849 } | 873 } |
| 850 // If this node sequence is labeled, a break out of the sequence will have | 874 // If this node sequence is labeled, a break out of the sequence will have |
| 851 // taken care of unchaining the context. | 875 // taken care of unchaining the context. |
| 852 if (node_sequence->label() != NULL) { | 876 if (node_sequence->label() != NULL) { |
| 853 __ Bind(node_sequence->label()->break_label()); | 877 __ Bind(node_sequence->label()->break_label()); |
| 878 if ((num_context_variables > 0) && |
| 879 (node_sequence == parsed_function_.node_sequence()) && |
| 880 !parsed_function_.function().IsClosureFunction()) { |
| 881 __ popl(CTX); |
| 882 } |
| 854 } | 883 } |
| 855 } | 884 } |
| 856 | 885 |
| 857 | 886 |
| 858 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { | 887 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { |
| 859 for (int i = 0; i < arguments->length(); i++) { | 888 for (int i = 0; i < arguments->length(); i++) { |
| 860 AstNode* argument = arguments->NodeAt(i); | 889 AstNode* argument = arguments->NodeAt(i); |
| 861 argument->Visit(this); | 890 argument->Visit(this); |
| 862 } | 891 } |
| 863 } | 892 } |
| (...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 // and ':stacktrace_var' can never be captured variables. | 2532 // and ':stacktrace_var' can never be captured variables. |
| 2504 // Restore CTX from local variable ':saved_context'. | 2533 // Restore CTX from local variable ':saved_context'. |
| 2505 GenerateLoadVariable(CTX, node->context_var()); | 2534 GenerateLoadVariable(CTX, node->context_var()); |
| 2506 | 2535 |
| 2507 // 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 |
| 2508 // popping arguments has not been run. | 2537 // popping arguments has not been run. |
| 2509 ASSERT(locals_space_size() >= 0); | 2538 ASSERT(locals_space_size() >= 0); |
| 2510 __ movl(ESP, EBP); | 2539 __ movl(ESP, EBP); |
| 2511 __ subl(ESP, Immediate(locals_space_size())); | 2540 __ subl(ESP, Immediate(locals_space_size())); |
| 2512 | 2541 |
| 2542 if ((state()->context_level() > 0) && |
| 2543 !parsed_function_.function().IsClosureFunction()) { |
| 2544 // CTX was saved on entry. |
| 2545 __ subl(ESP, Immediate(kWordSize)); |
| 2546 } |
| 2547 |
| 2513 // The JumpToExceptionHandler trampoline code sets up | 2548 // The JumpToExceptionHandler trampoline code sets up |
| 2514 // - the exception object in EAX (kExceptionObjectReg) | 2549 // - the exception object in EAX (kExceptionObjectReg) |
| 2515 // - the stacktrace object in register EDX (kStackTraceObjectReg) | 2550 // - the stacktrace object in register EDX (kStackTraceObjectReg) |
| 2516 // We now setup the exception object and the trace object | 2551 // We now setup the exception object and the trace object |
| 2517 // so that the handler code has access to these objects. | 2552 // so that the handler code has access to these objects. |
| 2518 GenerateStoreVariable(node->exception_var(), | 2553 GenerateStoreVariable(node->exception_var(), |
| 2519 kExceptionObjectReg, | 2554 kExceptionObjectReg, |
| 2520 kNoRegister); | 2555 kNoRegister); |
| 2521 GenerateStoreVariable(node->stacktrace_var(), | 2556 GenerateStoreVariable(node->stacktrace_var(), |
| 2522 kStackTraceObjectReg, | 2557 kStackTraceObjectReg, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2653 const Error& error = Error::Handle( | 2688 const Error& error = Error::Handle( |
| 2654 Parser::FormatError(script, token_index, "Error", format, args)); | 2689 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2655 va_end(args); | 2690 va_end(args); |
| 2656 Isolate::Current()->long_jump_base()->Jump(1, error); | 2691 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2657 UNREACHABLE(); | 2692 UNREACHABLE(); |
| 2658 } | 2693 } |
| 2659 | 2694 |
| 2660 } // namespace dart | 2695 } // namespace dart |
| 2661 | 2696 |
| 2662 #endif // defined TARGET_ARCH_IA32 | 2697 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |