| 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 21 matching lines...) Expand all Loading... |
| 32 | 32 |
| 33 #define __ assembler_-> | 33 #define __ assembler_-> |
| 34 | 34 |
| 35 | 35 |
| 36 CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen) | 36 CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen) |
| 37 : StackResource(Isolate::Current()), | 37 : StackResource(Isolate::Current()), |
| 38 codegen_(codegen), | 38 codegen_(codegen), |
| 39 parent_(codegen->state()) { | 39 parent_(codegen->state()) { |
| 40 if (parent_ != NULL) { | 40 if (parent_ != NULL) { |
| 41 root_node_ = parent_->root_node_; | 41 root_node_ = parent_->root_node_; |
| 42 loop_level_ = parent_->loop_level_; | |
| 43 context_level_ = parent_->context_level_; | |
| 44 current_try_index_ = parent_->current_try_index_; | 42 current_try_index_ = parent_->current_try_index_; |
| 45 } else { | 43 } else { |
| 46 root_node_ = NULL; | 44 root_node_ = NULL; |
| 47 loop_level_ = 0; | |
| 48 context_level_ = 0; | |
| 49 current_try_index_ = CatchClauseNode::kInvalidTryIndex; | 45 current_try_index_ = CatchClauseNode::kInvalidTryIndex; |
| 50 } | 46 } |
| 51 codegen_->set_state(this); | 47 codegen_->set_state(this); |
| 52 } | 48 } |
| 53 | 49 |
| 54 | 50 |
| 55 CodeGeneratorState::~CodeGeneratorState() { | 51 CodeGeneratorState::~CodeGeneratorState() { |
| 56 codegen_->set_state(parent_); | 52 codegen_->set_state(parent_); |
| 57 } | 53 } |
| 58 | 54 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 | 102 |
| 107 | 103 |
| 108 CodeGenerator::CodeGenerator(Assembler* assembler, | 104 CodeGenerator::CodeGenerator(Assembler* assembler, |
| 109 const ParsedFunction& parsed_function) | 105 const ParsedFunction& parsed_function) |
| 110 : assembler_(assembler), | 106 : assembler_(assembler), |
| 111 parsed_function_(parsed_function), | 107 parsed_function_(parsed_function), |
| 112 locals_space_size_(-1), | 108 locals_space_size_(-1), |
| 113 state_(NULL), | 109 state_(NULL), |
| 114 pc_descriptors_list_(NULL), | 110 pc_descriptors_list_(NULL), |
| 115 exception_handlers_list_(NULL), | 111 exception_handlers_list_(NULL), |
| 116 try_index_(CatchClauseNode::kInvalidTryIndex) { | 112 try_index_(CatchClauseNode::kInvalidTryIndex), |
| 113 context_level_(0) { |
| 117 ASSERT(assembler_ != NULL); | 114 ASSERT(assembler_ != NULL); |
| 118 ASSERT(parsed_function.node_sequence() != NULL); | 115 ASSERT(parsed_function.node_sequence() != NULL); |
| 119 ASSERT(Isolate::Current()->long_jump_base()->IsSafeToJump()); | 116 ASSERT(Isolate::Current()->long_jump_base()->IsSafeToJump()); |
| 120 pc_descriptors_list_ = new CodeGenerator::DescriptorList(); | 117 pc_descriptors_list_ = new CodeGenerator::DescriptorList(); |
| 121 exception_handlers_list_ = new CodeGenerator::HandlerList(); | 118 exception_handlers_list_ = new CodeGenerator::HandlerList(); |
| 122 } | 119 } |
| 123 | 120 |
| 124 | 121 |
| 125 bool CodeGenerator::IsResultNeeded(AstNode* node) const { | 122 bool CodeGenerator::IsResultNeeded(AstNode* node) const { |
| 126 return !state()->IsRootNode(node); | 123 return !state()->IsRootNode(node); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 226 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 230 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 227 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 231 code.set_exception_handlers(handlers); | 228 code.set_exception_handlers(handlers); |
| 232 } | 229 } |
| 233 | 230 |
| 234 | 231 |
| 235 void CodeGenerator::GenerateLoadVariable(Register dst, | 232 void CodeGenerator::GenerateLoadVariable(Register dst, |
| 236 const LocalVariable& variable) { | 233 const LocalVariable& variable) { |
| 237 if (variable.is_captured()) { | 234 if (variable.is_captured()) { |
| 238 // The variable lives in the context. | 235 // The variable lives in the context. |
| 239 int delta = state()->context_level() - variable.owner()->context_level(); | 236 intptr_t delta = context_level() - variable.owner()->context_level(); |
| 240 ASSERT(delta >= 0); | 237 ASSERT(delta >= 0); |
| 241 Register base = CTX; | 238 Register base = CTX; |
| 242 while (delta-- > 0) { | 239 while (delta-- > 0) { |
| 243 __ movl(dst, FieldAddress(base, Context::parent_offset())); | 240 __ movl(dst, FieldAddress(base, Context::parent_offset())); |
| 244 base = dst; | 241 base = dst; |
| 245 } | 242 } |
| 246 __ movl(dst, | 243 __ movl(dst, |
| 247 FieldAddress(base, Context::variable_offset(variable.index()))); | 244 FieldAddress(base, Context::variable_offset(variable.index()))); |
| 248 } else { | 245 } else { |
| 249 // The variable lives in the current stack frame. | 246 // The variable lives in the current stack frame. |
| 250 __ movl(dst, Address(EBP, variable.index() * kWordSize)); | 247 __ movl(dst, Address(EBP, variable.index() * kWordSize)); |
| 251 } | 248 } |
| 252 } | 249 } |
| 253 | 250 |
| 254 | 251 |
| 255 void CodeGenerator::GenerateStoreVariable(const LocalVariable& variable, | 252 void CodeGenerator::GenerateStoreVariable(const LocalVariable& variable, |
| 256 Register src, | 253 Register src, |
| 257 Register scratch) { | 254 Register scratch) { |
| 258 if (variable.is_captured()) { | 255 if (variable.is_captured()) { |
| 259 // The variable lives in the context. | 256 // The variable lives in the context. |
| 260 int delta = state()->context_level() - variable.owner()->context_level(); | 257 intptr_t delta = context_level() - variable.owner()->context_level(); |
| 261 ASSERT(delta >= 0); | 258 ASSERT(delta >= 0); |
| 262 Register base = CTX; | 259 Register base = CTX; |
| 263 while (delta-- > 0) { | 260 while (delta-- > 0) { |
| 264 __ movl(scratch, FieldAddress(base, Context::parent_offset())); | 261 __ movl(scratch, FieldAddress(base, Context::parent_offset())); |
| 265 base = scratch; | 262 base = scratch; |
| 266 } | 263 } |
| 267 __ StoreIntoObject( | 264 __ StoreIntoObject( |
| 268 base, | 265 base, |
| 269 FieldAddress(base, Context::variable_offset(variable.index())), | 266 FieldAddress(base, Context::variable_offset(variable.index())), |
| 270 src); | 267 src); |
| 271 } else { | 268 } else { |
| 272 // The variable lives in the current stack frame. | 269 // The variable lives in the current stack frame. |
| 273 __ movl(Address(EBP, variable.index() * kWordSize), src); | 270 __ movl(Address(EBP, variable.index() * kWordSize), src); |
| 274 } | 271 } |
| 275 } | 272 } |
| 276 | 273 |
| 277 | 274 |
| 278 void CodeGenerator::GeneratePushVariable(const LocalVariable& variable, | 275 void CodeGenerator::GeneratePushVariable(const LocalVariable& variable, |
| 279 Register scratch) { | 276 Register scratch) { |
| 280 if (variable.is_captured()) { | 277 if (variable.is_captured()) { |
| 281 // The variable lives in the context. | 278 // The variable lives in the context. |
| 282 int delta = state()->context_level() - variable.owner()->context_level(); | 279 intptr_t delta = context_level() - variable.owner()->context_level(); |
| 283 ASSERT(delta >= 0); | 280 ASSERT(delta >= 0); |
| 284 Register base = CTX; | 281 Register base = CTX; |
| 285 while (delta-- > 0) { | 282 while (delta-- > 0) { |
| 286 __ movl(scratch, FieldAddress(base, Context::parent_offset())); | 283 __ movl(scratch, FieldAddress(base, Context::parent_offset())); |
| 287 base = scratch; | 284 base = scratch; |
| 288 } | 285 } |
| 289 __ pushl(FieldAddress(base, Context::variable_offset(variable.index()))); | 286 __ pushl(FieldAddress(base, Context::variable_offset(variable.index()))); |
| 290 } else { | 287 } else { |
| 291 // The variable lives in the current stack frame. | 288 // The variable lives in the current stack frame. |
| 292 __ pushl(Address(EBP, variable.index() * kWordSize)); | 289 __ pushl(Address(EBP, variable.index() * kWordSize)); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 __ j(ABOVE, &no_stack_overflow); | 583 __ j(ABOVE, &no_stack_overflow); |
| 587 GenerateCallRuntime(AstNode::kNoId, | 584 GenerateCallRuntime(AstNode::kNoId, |
| 588 0, | 585 0, |
| 589 kStackOverflowRuntimeEntry); | 586 kStackOverflowRuntimeEntry); |
| 590 __ Bind(&no_stack_overflow); | 587 __ Bind(&no_stack_overflow); |
| 591 } | 588 } |
| 592 | 589 |
| 593 | 590 |
| 594 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { | 591 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { |
| 595 // Unchain the context(s) up to context level 0. | 592 // Unchain the context(s) up to context level 0. |
| 596 int context_level = state()->context_level(); | 593 intptr_t current_context_level = context_level(); |
| 597 ASSERT(context_level >= 0); | 594 ASSERT(current_context_level >= 0); |
| 598 if (!parsed_function_.function().IsClosureFunction()) { | 595 if (!parsed_function_.function().IsClosureFunction()) { |
| 599 if (context_level > 0) { | 596 if (current_context_level > 0) { |
| 600 // CTX on entry was saved on the stack, but not linked as context parent. | 597 // CTX on entry was saved on the stack, but not linked as context parent. |
| 601 __ popl(CTX); | 598 __ popl(CTX); |
| 602 } | 599 } |
| 603 } else { | 600 } else { |
| 604 while (context_level-- > 0) { | 601 while (current_context_level-- > 0) { |
| 605 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 602 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 606 } | 603 } |
| 607 } | 604 } |
| 608 #ifdef DEBUG | 605 #ifdef DEBUG |
| 609 // Check that the entry stack size matches the exit stack size. | 606 // Check that the entry stack size matches the exit stack size. |
| 610 __ movl(EDX, EBP); | 607 __ movl(EDX, EBP); |
| 611 __ subl(EDX, ESP); | 608 __ subl(EDX, ESP); |
| 612 ASSERT(locals_space_size() >= 0); | 609 ASSERT(locals_space_size() >= 0); |
| 613 __ cmpl(EDX, Immediate(locals_space_size())); | 610 __ cmpl(EDX, Immediate(locals_space_size())); |
| 614 Label wrong_stack; | 611 Label wrong_stack; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 } | 732 } |
| 736 } | 733 } |
| 737 | 734 |
| 738 | 735 |
| 739 void CodeGenerator::VisitClosureNode(ClosureNode* node) { | 736 void CodeGenerator::VisitClosureNode(ClosureNode* node) { |
| 740 const Function& function = node->function(); | 737 const Function& function = node->function(); |
| 741 if (function.IsNonImplicitClosureFunction()) { | 738 if (function.IsNonImplicitClosureFunction()) { |
| 742 // The context scope may have already been set by the new non-optimizing | 739 // The context scope may have already been set by the new non-optimizing |
| 743 // compiler. If it was not, set it here. | 740 // compiler. If it was not, set it here. |
| 744 if (function.context_scope() == ContextScope::null()) { | 741 if (function.context_scope() == ContextScope::null()) { |
| 745 const int current_context_level = state()->context_level(); | 742 const intptr_t current_context_level = context_level(); |
| 746 const ContextScope& context_scope = ContextScope::ZoneHandle( | 743 const ContextScope& context_scope = ContextScope::ZoneHandle( |
| 747 node->scope()->PreserveOuterScope(current_context_level)); | 744 node->scope()->PreserveOuterScope(current_context_level)); |
| 748 ASSERT(!function.HasCode()); | 745 ASSERT(!function.HasCode()); |
| 749 function.set_context_scope(context_scope); | 746 function.set_context_scope(context_scope); |
| 750 } | 747 } |
| 751 } else if (function.IsImplicitInstanceClosureFunction()) { | 748 } else if (function.IsImplicitInstanceClosureFunction()) { |
| 752 node->receiver()->Visit(this); | 749 node->receiver()->Visit(this); |
| 753 } | 750 } |
| 754 ASSERT(function.context_scope() != ContextScope::null()); | 751 ASSERT(function.context_scope() != ContextScope::null()); |
| 755 | 752 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 __ popl(EAX); | 789 __ popl(EAX); |
| 793 __ popl(CTX); // result: cloned context. Set as current context. | 790 __ popl(CTX); // result: cloned context. Set as current context. |
| 794 } | 791 } |
| 795 | 792 |
| 796 | 793 |
| 797 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { | 794 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { |
| 798 CodeGeneratorState codegen_state(this); | 795 CodeGeneratorState codegen_state(this); |
| 799 LocalScope* scope = node_sequence->scope(); | 796 LocalScope* scope = node_sequence->scope(); |
| 800 const intptr_t num_context_variables = | 797 const intptr_t num_context_variables = |
| 801 (scope != NULL) ? scope->num_context_variables() : 0; | 798 (scope != NULL) ? scope->num_context_variables() : 0; |
| 799 intptr_t previous_context_level = context_level(); |
| 802 if (num_context_variables > 0) { | 800 if (num_context_variables > 0) { |
| 803 // The loop local scope declares variables that are captured. | 801 // The loop local scope declares variables that are captured. |
| 804 // Allocate and chain a new context. | 802 // Allocate and chain a new context. |
| 805 __ movl(EDX, Immediate(num_context_variables)); | 803 __ movl(EDX, Immediate(num_context_variables)); |
| 806 const ExternalLabel label("alloc_context", | 804 const ExternalLabel label("alloc_context", |
| 807 StubCode::AllocateContextEntryPoint()); | 805 StubCode::AllocateContextEntryPoint()); |
| 808 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); | 806 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); |
| 809 | 807 |
| 810 // If this node_sequence is the body of the function being compiled, and if | 808 // 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 | 809 // 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, | 810 // parent of the newly allocated context, as it is not accessible. Instead, |
| 813 // save it on the stack and restore it on exit. | 811 // save it on the stack and restore it on exit. |
| 814 if ((node_sequence == parsed_function_.node_sequence()) && | 812 if ((node_sequence == parsed_function_.node_sequence()) && |
| 815 !parsed_function_.function().IsClosureFunction()) { | 813 !parsed_function_.function().IsClosureFunction()) { |
| 816 __ pushl(CTX); | 814 __ pushl(CTX); |
| 817 const Immediate raw_null = | 815 const Immediate raw_null = |
| 818 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 816 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 819 __ movl(CTX, raw_null); | 817 __ movl(CTX, raw_null); |
| 820 } | 818 } |
| 821 | 819 |
| 822 // Chain the new context in EAX to its parent in CTX. | 820 // Chain the new context in EAX to its parent in CTX. |
| 823 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); | 821 __ StoreIntoObject(EAX, FieldAddress(EAX, Context::parent_offset()), CTX); |
| 824 // Set new context as current context. | 822 // Set new context as current context. |
| 825 __ movl(CTX, EAX); | 823 __ movl(CTX, EAX); |
| 826 state()->set_context_level(scope->context_level()); | 824 set_context_level(scope->context_level()); |
| 827 | 825 |
| 828 // If this node_sequence is the body of the function being compiled, copy | 826 // If this node_sequence is the body of the function being compiled, copy |
| 829 // the captured parameters from the frame into the context. | 827 // the captured parameters from the frame into the context. |
| 830 if (node_sequence == parsed_function_.node_sequence()) { | 828 if (node_sequence == parsed_function_.node_sequence()) { |
| 831 ASSERT(scope->context_level() == 1); | 829 ASSERT(scope->context_level() == 1); |
| 832 const Immediate raw_null = | 830 const Immediate raw_null = |
| 833 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 831 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 834 const Function& function = parsed_function_.function(); | 832 const Function& function = parsed_function_.function(); |
| 835 const int num_params = function.NumberOfParameters(); | 833 const int num_params = function.NumberOfParameters(); |
| 836 int param_frame_index = | 834 int param_frame_index = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 // 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 |
| 875 // taken care of unchaining the context. | 873 // taken care of unchaining the context. |
| 876 if (node_sequence->label() != NULL) { | 874 if (node_sequence->label() != NULL) { |
| 877 __ Bind(node_sequence->label()->break_label()); | 875 __ Bind(node_sequence->label()->break_label()); |
| 878 if ((num_context_variables > 0) && | 876 if ((num_context_variables > 0) && |
| 879 (node_sequence == parsed_function_.node_sequence()) && | 877 (node_sequence == parsed_function_.node_sequence()) && |
| 880 !parsed_function_.function().IsClosureFunction()) { | 878 !parsed_function_.function().IsClosureFunction()) { |
| 881 __ popl(CTX); | 879 __ popl(CTX); |
| 882 } | 880 } |
| 883 } | 881 } |
| 882 set_context_level(previous_context_level); |
| 884 } | 883 } |
| 885 | 884 |
| 886 | 885 |
| 887 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { | 886 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { |
| 888 for (int i = 0; i < arguments->length(); i++) { | 887 for (int i = 0; i < arguments->length(); i++) { |
| 889 AstNode* argument = arguments->NodeAt(i); | 888 AstNode* argument = arguments->NodeAt(i); |
| 890 argument->Visit(this); | 889 argument->Visit(this); |
| 891 } | 890 } |
| 892 } | 891 } |
| 893 | 892 |
| (...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1850 | 1849 |
| 1851 // Generate inlined code for all finally blocks as we may transfer | 1850 // Generate inlined code for all finally blocks as we may transfer |
| 1852 // control out of the 'try' blocks if any. | 1851 // control out of the 'try' blocks if any. |
| 1853 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1852 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 1854 node->InlinedFinallyNodeAt(i)->Visit(this); | 1853 node->InlinedFinallyNodeAt(i)->Visit(this); |
| 1855 } | 1854 } |
| 1856 | 1855 |
| 1857 // Unchain the context(s) up to the outer context level of the scope which | 1856 // Unchain the context(s) up to the outer context level of the scope which |
| 1858 // contains the destination label. | 1857 // contains the destination label. |
| 1859 ASSERT(label->owner() != NULL); | 1858 ASSERT(label->owner() != NULL); |
| 1860 int target_context_level = 0; | 1859 intptr_t target_context_level = 0; |
| 1861 LocalScope* target_scope = label->owner(); | 1860 LocalScope* target_scope = label->owner(); |
| 1862 if (target_scope->num_context_variables() > 0) { | 1861 if (target_scope->num_context_variables() > 0) { |
| 1863 // The scope of the target label allocates a context, therefore its outer | 1862 // The scope of the target label allocates a context, therefore its outer |
| 1864 // scope is at a lower context level. | 1863 // scope is at a lower context level. |
| 1865 target_context_level = target_scope->context_level() - 1; | 1864 target_context_level = target_scope->context_level() - 1; |
| 1866 } else { | 1865 } else { |
| 1867 // The scope of the target label does not allocate a context, so its outer | 1866 // The scope of the target label does not allocate a context, so its outer |
| 1868 // scope is at the same context level. Find it. | 1867 // scope is at the same context level. Find it. |
| 1869 while ((target_scope != NULL) && | 1868 while ((target_scope != NULL) && |
| 1870 (target_scope->num_context_variables() == 0)) { | 1869 (target_scope->num_context_variables() == 0)) { |
| 1871 target_scope = target_scope->parent(); | 1870 target_scope = target_scope->parent(); |
| 1872 } | 1871 } |
| 1873 if (target_scope != NULL) { | 1872 if (target_scope != NULL) { |
| 1874 target_context_level = target_scope->context_level(); | 1873 target_context_level = target_scope->context_level(); |
| 1875 } | 1874 } |
| 1876 } | 1875 } |
| 1877 ASSERT(target_context_level >= 0); | 1876 ASSERT(target_context_level >= 0); |
| 1878 int context_level = state()->context_level(); | 1877 int current_context_level = context_level(); |
| 1879 ASSERT(context_level >= target_context_level); | 1878 ASSERT(current_context_level >= target_context_level); |
| 1880 while (context_level-- > target_context_level) { | 1879 while (current_context_level-- > target_context_level) { |
| 1881 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 1880 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 1882 } | 1881 } |
| 1883 | 1882 |
| 1884 if (node->kind() == Token::kBREAK) { | 1883 if (node->kind() == Token::kBREAK) { |
| 1885 __ jmp(label->break_label()); | 1884 __ jmp(label->break_label()); |
| 1886 } else { | 1885 } else { |
| 1887 __ jmp(label->continue_label()); | 1886 __ jmp(label->continue_label()); |
| 1888 } | 1887 } |
| 1889 } | 1888 } |
| 1890 | 1889 |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2532 // and ':stacktrace_var' can never be captured variables. | 2531 // and ':stacktrace_var' can never be captured variables. |
| 2533 // Restore CTX from local variable ':saved_context'. | 2532 // Restore CTX from local variable ':saved_context'. |
| 2534 GenerateLoadVariable(CTX, node->context_var()); | 2533 GenerateLoadVariable(CTX, node->context_var()); |
| 2535 | 2534 |
| 2536 // Restore ESP from EBP as we are coming from a throw and the code for | 2535 // Restore ESP from EBP as we are coming from a throw and the code for |
| 2537 // popping arguments has not been run. | 2536 // popping arguments has not been run. |
| 2538 ASSERT(locals_space_size() >= 0); | 2537 ASSERT(locals_space_size() >= 0); |
| 2539 __ movl(ESP, EBP); | 2538 __ movl(ESP, EBP); |
| 2540 __ subl(ESP, Immediate(locals_space_size())); | 2539 __ subl(ESP, Immediate(locals_space_size())); |
| 2541 | 2540 |
| 2542 if ((state()->context_level() > 0) && | 2541 if ((context_level() > 0) && |
| 2543 !parsed_function_.function().IsClosureFunction()) { | 2542 !parsed_function_.function().IsClosureFunction()) { |
| 2544 // CTX was saved on entry. | 2543 // CTX was saved on entry. |
| 2545 __ subl(ESP, Immediate(kWordSize)); | 2544 __ subl(ESP, Immediate(kWordSize)); |
| 2546 } | 2545 } |
| 2547 | 2546 |
| 2548 // The JumpToExceptionHandler trampoline code sets up | 2547 // The JumpToExceptionHandler trampoline code sets up |
| 2549 // - the exception object in EAX (kExceptionObjectReg) | 2548 // - the exception object in EAX (kExceptionObjectReg) |
| 2550 // - the stacktrace object in register EDX (kStackTraceObjectReg) | 2549 // - the stacktrace object in register EDX (kStackTraceObjectReg) |
| 2551 // We now setup the exception object and the trace object | 2550 // We now setup the exception object and the trace object |
| 2552 // so that the handler code has access to these objects. | 2551 // so that the handler code has access to these objects. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2688 const Error& error = Error::Handle( | 2687 const Error& error = Error::Handle( |
| 2689 Parser::FormatError(script, token_index, "Error", format, args)); | 2688 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2690 va_end(args); | 2689 va_end(args); |
| 2691 Isolate::Current()->long_jump_base()->Jump(1, error); | 2690 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2692 UNREACHABLE(); | 2691 UNREACHABLE(); |
| 2693 } | 2692 } |
| 2694 | 2693 |
| 2695 } // namespace dart | 2694 } // namespace dart |
| 2696 | 2695 |
| 2697 #endif // defined TARGET_ARCH_IA32 | 2696 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |