| 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 23 matching lines...) Expand all Loading... |
| 34 // CodeGenerator::HandlerList can probably be moved to code_generator.cc, since | 34 // CodeGenerator::HandlerList can probably be moved to code_generator.cc, since |
| 35 // they seem to be architecture independent. | 35 // they seem to be architecture independent. |
| 36 | 36 |
| 37 | 37 |
| 38 CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen) | 38 CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen) |
| 39 : StackResource(Isolate::Current()), | 39 : StackResource(Isolate::Current()), |
| 40 codegen_(codegen), | 40 codegen_(codegen), |
| 41 parent_(codegen->state()) { | 41 parent_(codegen->state()) { |
| 42 if (parent_ != NULL) { | 42 if (parent_ != NULL) { |
| 43 root_node_ = parent_->root_node_; | 43 root_node_ = parent_->root_node_; |
| 44 loop_level_ = parent_->loop_level_; | |
| 45 context_level_ = parent_->context_level_; | |
| 46 current_try_index_ = parent_->current_try_index_; | 44 current_try_index_ = parent_->current_try_index_; |
| 47 } else { | 45 } else { |
| 48 root_node_ = NULL; | 46 root_node_ = NULL; |
| 49 loop_level_ = 0; | |
| 50 context_level_ = 0; | |
| 51 current_try_index_ = CatchClauseNode::kInvalidTryIndex; | 47 current_try_index_ = CatchClauseNode::kInvalidTryIndex; |
| 52 } | 48 } |
| 53 codegen_->set_state(this); | 49 codegen_->set_state(this); |
| 54 } | 50 } |
| 55 | 51 |
| 56 | 52 |
| 57 CodeGeneratorState::~CodeGeneratorState() { | 53 CodeGeneratorState::~CodeGeneratorState() { |
| 58 codegen_->set_state(parent_); | 54 codegen_->set_state(parent_); |
| 59 } | 55 } |
| 60 | 56 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 104 |
| 109 | 105 |
| 110 CodeGenerator::CodeGenerator(Assembler* assembler, | 106 CodeGenerator::CodeGenerator(Assembler* assembler, |
| 111 const ParsedFunction& parsed_function) | 107 const ParsedFunction& parsed_function) |
| 112 : assembler_(assembler), | 108 : assembler_(assembler), |
| 113 parsed_function_(parsed_function), | 109 parsed_function_(parsed_function), |
| 114 locals_space_size_(-1), | 110 locals_space_size_(-1), |
| 115 state_(NULL), | 111 state_(NULL), |
| 116 pc_descriptors_list_(NULL), | 112 pc_descriptors_list_(NULL), |
| 117 exception_handlers_list_(NULL), | 113 exception_handlers_list_(NULL), |
| 118 try_index_(CatchClauseNode::kInvalidTryIndex) { | 114 try_index_(CatchClauseNode::kInvalidTryIndex), |
| 115 context_level_(0) { |
| 119 ASSERT(assembler_ != NULL); | 116 ASSERT(assembler_ != NULL); |
| 120 ASSERT(parsed_function.node_sequence() != NULL); | 117 ASSERT(parsed_function.node_sequence() != NULL); |
| 121 ASSERT(Isolate::Current()->long_jump_base()->IsSafeToJump()); | 118 ASSERT(Isolate::Current()->long_jump_base()->IsSafeToJump()); |
| 122 pc_descriptors_list_ = new CodeGenerator::DescriptorList(); | 119 pc_descriptors_list_ = new CodeGenerator::DescriptorList(); |
| 123 exception_handlers_list_ = new CodeGenerator::HandlerList(); | 120 exception_handlers_list_ = new CodeGenerator::HandlerList(); |
| 124 } | 121 } |
| 125 | 122 |
| 126 | 123 |
| 127 bool CodeGenerator::IsResultNeeded(AstNode* node) const { | 124 bool CodeGenerator::IsResultNeeded(AstNode* node) const { |
| 128 return !state()->IsRootNode(node); | 125 return !state()->IsRootNode(node); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 230 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 234 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 231 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 235 code.set_exception_handlers(handlers); | 232 code.set_exception_handlers(handlers); |
| 236 } | 233 } |
| 237 | 234 |
| 238 | 235 |
| 239 void CodeGenerator::GenerateLoadVariable(Register dst, | 236 void CodeGenerator::GenerateLoadVariable(Register dst, |
| 240 const LocalVariable& variable) { | 237 const LocalVariable& variable) { |
| 241 if (variable.is_captured()) { | 238 if (variable.is_captured()) { |
| 242 // The variable lives in the context. | 239 // The variable lives in the context. |
| 243 int delta = state()->context_level() - variable.owner()->context_level(); | 240 intptr_t delta = context_level() - variable.owner()->context_level(); |
| 244 ASSERT(delta >= 0); | 241 ASSERT(delta >= 0); |
| 245 Register base = CTX; | 242 Register base = CTX; |
| 246 while (delta-- > 0) { | 243 while (delta-- > 0) { |
| 247 __ movq(dst, FieldAddress(base, Context::parent_offset())); | 244 __ movq(dst, FieldAddress(base, Context::parent_offset())); |
| 248 base = dst; | 245 base = dst; |
| 249 } | 246 } |
| 250 __ movq(dst, | 247 __ movq(dst, |
| 251 FieldAddress(base, Context::variable_offset(variable.index()))); | 248 FieldAddress(base, Context::variable_offset(variable.index()))); |
| 252 } else { | 249 } else { |
| 253 // The variable lives in the current stack frame. | 250 // The variable lives in the current stack frame. |
| 254 __ movq(dst, Address(RBP, variable.index() * kWordSize)); | 251 __ movq(dst, Address(RBP, variable.index() * kWordSize)); |
| 255 } | 252 } |
| 256 } | 253 } |
| 257 | 254 |
| 258 | 255 |
| 259 void CodeGenerator::GenerateStoreVariable(const LocalVariable& variable, | 256 void CodeGenerator::GenerateStoreVariable(const LocalVariable& variable, |
| 260 Register src, | 257 Register src, |
| 261 Register scratch) { | 258 Register scratch) { |
| 262 if (variable.is_captured()) { | 259 if (variable.is_captured()) { |
| 263 // The variable lives in the context. | 260 // The variable lives in the context. |
| 264 int delta = state()->context_level() - variable.owner()->context_level(); | 261 intptr_t delta = context_level() - variable.owner()->context_level(); |
| 265 ASSERT(delta >= 0); | 262 ASSERT(delta >= 0); |
| 266 Register base = CTX; | 263 Register base = CTX; |
| 267 while (delta-- > 0) { | 264 while (delta-- > 0) { |
| 268 __ movq(scratch, FieldAddress(base, Context::parent_offset())); | 265 __ movq(scratch, FieldAddress(base, Context::parent_offset())); |
| 269 base = scratch; | 266 base = scratch; |
| 270 } | 267 } |
| 271 __ StoreIntoObject( | 268 __ StoreIntoObject( |
| 272 base, | 269 base, |
| 273 FieldAddress(base, Context::variable_offset(variable.index())), | 270 FieldAddress(base, Context::variable_offset(variable.index())), |
| 274 src); | 271 src); |
| 275 } else { | 272 } else { |
| 276 // The variable lives in the current stack frame. | 273 // The variable lives in the current stack frame. |
| 277 __ movq(Address(RBP, variable.index() * kWordSize), src); | 274 __ movq(Address(RBP, variable.index() * kWordSize), src); |
| 278 } | 275 } |
| 279 } | 276 } |
| 280 | 277 |
| 281 | 278 |
| 282 void CodeGenerator::GeneratePushVariable(const LocalVariable& variable, | 279 void CodeGenerator::GeneratePushVariable(const LocalVariable& variable, |
| 283 Register scratch) { | 280 Register scratch) { |
| 284 if (variable.is_captured()) { | 281 if (variable.is_captured()) { |
| 285 // The variable lives in the context. | 282 // The variable lives in the context. |
| 286 int delta = state()->context_level() - variable.owner()->context_level(); | 283 intptr_t delta = context_level() - variable.owner()->context_level(); |
| 287 ASSERT(delta >= 0); | 284 ASSERT(delta >= 0); |
| 288 Register base = CTX; | 285 Register base = CTX; |
| 289 while (delta-- > 0) { | 286 while (delta-- > 0) { |
| 290 __ movq(scratch, FieldAddress(base, Context::parent_offset())); | 287 __ movq(scratch, FieldAddress(base, Context::parent_offset())); |
| 291 base = scratch; | 288 base = scratch; |
| 292 } | 289 } |
| 293 __ pushq(FieldAddress(base, Context::variable_offset(variable.index()))); | 290 __ pushq(FieldAddress(base, Context::variable_offset(variable.index()))); |
| 294 } else { | 291 } else { |
| 295 // The variable lives in the current stack frame. | 292 // The variable lives in the current stack frame. |
| 296 __ pushq(Address(RBP, variable.index() * kWordSize)); | 293 __ pushq(Address(RBP, variable.index() * kWordSize)); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 __ j(ABOVE, &no_stack_overflow); | 603 __ j(ABOVE, &no_stack_overflow); |
| 607 GenerateCallRuntime(AstNode::kNoId, | 604 GenerateCallRuntime(AstNode::kNoId, |
| 608 0, | 605 0, |
| 609 kStackOverflowRuntimeEntry); | 606 kStackOverflowRuntimeEntry); |
| 610 __ Bind(&no_stack_overflow); | 607 __ Bind(&no_stack_overflow); |
| 611 } | 608 } |
| 612 | 609 |
| 613 | 610 |
| 614 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { | 611 void CodeGenerator::GenerateReturnEpilog(ReturnNode* node) { |
| 615 // Unchain the context(s) up to context level 0. | 612 // Unchain the context(s) up to context level 0. |
| 616 int context_level = state()->context_level(); | 613 intptr_t current_context_level = context_level(); |
| 617 ASSERT(context_level >= 0); | 614 ASSERT(current_context_level >= 0); |
| 618 if (!parsed_function_.function().IsClosureFunction()) { | 615 if (!parsed_function_.function().IsClosureFunction()) { |
| 619 if (context_level > 0) { | 616 if (current_context_level > 0) { |
| 620 // CTX on entry was saved on the stack, but not linked as context parent. | 617 // CTX on entry was saved on the stack, but not linked as context parent. |
| 621 __ popq(CTX); | 618 __ popq(CTX); |
| 622 } | 619 } |
| 623 } else { | 620 } else { |
| 624 while (context_level-- > 0) { | 621 while (current_context_level-- > 0) { |
| 625 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); | 622 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 626 } | 623 } |
| 627 } | 624 } |
| 628 #ifdef DEBUG | 625 #ifdef DEBUG |
| 629 // Check that the entry stack size matches the exit stack size. | 626 // Check that the entry stack size matches the exit stack size. |
| 630 __ movq(R10, RBP); | 627 __ movq(R10, RBP); |
| 631 __ subq(R10, RSP); | 628 __ subq(R10, RSP); |
| 632 ASSERT(locals_space_size() >= 0); | 629 ASSERT(locals_space_size() >= 0); |
| 633 __ cmpq(R10, Immediate(locals_space_size())); | 630 __ cmpq(R10, Immediate(locals_space_size())); |
| 634 Label wrong_stack; | 631 Label wrong_stack; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 } | 738 } |
| 742 } | 739 } |
| 743 | 740 |
| 744 | 741 |
| 745 void CodeGenerator::VisitClosureNode(ClosureNode* node) { | 742 void CodeGenerator::VisitClosureNode(ClosureNode* node) { |
| 746 const Function& function = node->function(); | 743 const Function& function = node->function(); |
| 747 if (function.IsNonImplicitClosureFunction()) { | 744 if (function.IsNonImplicitClosureFunction()) { |
| 748 // The context scope may have already been set by the new non-optimizing | 745 // The context scope may have already been set by the new non-optimizing |
| 749 // compiler. If it was not, set it here. | 746 // compiler. If it was not, set it here. |
| 750 if (function.context_scope() == ContextScope::null()) { | 747 if (function.context_scope() == ContextScope::null()) { |
| 751 const int current_context_level = state()->context_level(); | 748 const intptr_t current_context_level = context_level(); |
| 752 const ContextScope& context_scope = ContextScope::ZoneHandle( | 749 const ContextScope& context_scope = ContextScope::ZoneHandle( |
| 753 node->scope()->PreserveOuterScope(current_context_level)); | 750 node->scope()->PreserveOuterScope(current_context_level)); |
| 754 ASSERT(!function.HasCode()); | 751 ASSERT(!function.HasCode()); |
| 755 function.set_context_scope(context_scope); | 752 function.set_context_scope(context_scope); |
| 756 } | 753 } |
| 757 } else if (function.IsImplicitInstanceClosureFunction()) { | 754 } else if (function.IsImplicitInstanceClosureFunction()) { |
| 758 node->receiver()->Visit(this); | 755 node->receiver()->Visit(this); |
| 759 } | 756 } |
| 760 ASSERT(function.context_scope() != ContextScope::null()); | 757 ASSERT(function.context_scope() != ContextScope::null()); |
| 761 | 758 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 __ popq(RAX); | 795 __ popq(RAX); |
| 799 __ popq(CTX); // result: cloned context. Set as current context. | 796 __ popq(CTX); // result: cloned context. Set as current context. |
| 800 } | 797 } |
| 801 | 798 |
| 802 | 799 |
| 803 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { | 800 void CodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { |
| 804 CodeGeneratorState codegen_state(this); | 801 CodeGeneratorState codegen_state(this); |
| 805 LocalScope* scope = node_sequence->scope(); | 802 LocalScope* scope = node_sequence->scope(); |
| 806 const intptr_t num_context_variables = | 803 const intptr_t num_context_variables = |
| 807 (scope != NULL) ? scope->num_context_variables() : 0; | 804 (scope != NULL) ? scope->num_context_variables() : 0; |
| 805 intptr_t previous_context_level = context_level(); |
| 808 if (num_context_variables > 0) { | 806 if (num_context_variables > 0) { |
| 809 // The loop local scope declares variables that are captured. | 807 // The loop local scope declares variables that are captured. |
| 810 // Allocate and chain a new context. | 808 // Allocate and chain a new context. |
| 811 __ movq(R10, Immediate(num_context_variables)); | 809 __ movq(R10, Immediate(num_context_variables)); |
| 812 const ExternalLabel label("alloc_context", | 810 const ExternalLabel label("alloc_context", |
| 813 StubCode::AllocateContextEntryPoint()); | 811 StubCode::AllocateContextEntryPoint()); |
| 814 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); | 812 GenerateCall(node_sequence->token_index(), &label, PcDescriptors::kOther); |
| 815 | 813 |
| 816 // If this node_sequence is the body of the function being compiled, and if | 814 // If this node_sequence is the body of the function being compiled, and if |
| 817 // this function is not a closure, do not link the current context as the | 815 // this function is not a closure, do not link the current context as the |
| 818 // parent of the newly allocated context, as it is not accessible. Instead, | 816 // parent of the newly allocated context, as it is not accessible. Instead, |
| 819 // save it on the stack and restore it on exit. | 817 // save it on the stack and restore it on exit. |
| 820 if ((node_sequence == parsed_function_.node_sequence()) && | 818 if ((node_sequence == parsed_function_.node_sequence()) && |
| 821 !parsed_function_.function().IsClosureFunction()) { | 819 !parsed_function_.function().IsClosureFunction()) { |
| 822 __ pushq(CTX); | 820 __ pushq(CTX); |
| 823 const Immediate raw_null = | 821 const Immediate raw_null = |
| 824 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 822 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 825 __ movq(CTX, raw_null); | 823 __ movq(CTX, raw_null); |
| 826 } | 824 } |
| 827 | 825 |
| 828 // Chain the new context in RAX to its parent in CTX. | 826 // Chain the new context in RAX to its parent in CTX. |
| 829 __ StoreIntoObject(RAX, | 827 __ StoreIntoObject(RAX, |
| 830 FieldAddress(RAX, Context::parent_offset()), | 828 FieldAddress(RAX, Context::parent_offset()), |
| 831 CTX); | 829 CTX); |
| 832 // Set new context as current context. | 830 // Set new context as current context. |
| 833 __ movq(CTX, RAX); | 831 __ movq(CTX, RAX); |
| 834 state()->set_context_level(scope->context_level()); | 832 set_context_level(scope->context_level()); |
| 835 | 833 |
| 836 // If this node_sequence is the body of the function being compiled, copy | 834 // If this node_sequence is the body of the function being compiled, copy |
| 837 // the captured parameters from the frame into the context. | 835 // the captured parameters from the frame into the context. |
| 838 if (node_sequence == parsed_function_.node_sequence()) { | 836 if (node_sequence == parsed_function_.node_sequence()) { |
| 839 ASSERT(scope->context_level() == 1); | 837 ASSERT(scope->context_level() == 1); |
| 840 const Immediate raw_null = | 838 const Immediate raw_null = |
| 841 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 839 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 842 const Function& function = parsed_function_.function(); | 840 const Function& function = parsed_function_.function(); |
| 843 const int num_params = function.NumberOfParameters(); | 841 const int num_params = function.NumberOfParameters(); |
| 844 int param_frame_index = | 842 int param_frame_index = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 // 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 |
| 883 // taken care of unchaining the context. | 881 // taken care of unchaining the context. |
| 884 if (node_sequence->label() != NULL) { | 882 if (node_sequence->label() != NULL) { |
| 885 __ Bind(node_sequence->label()->break_label()); | 883 __ Bind(node_sequence->label()->break_label()); |
| 886 if ((num_context_variables > 0) && | 884 if ((num_context_variables > 0) && |
| 887 (node_sequence == parsed_function_.node_sequence()) && | 885 (node_sequence == parsed_function_.node_sequence()) && |
| 888 !parsed_function_.function().IsClosureFunction()) { | 886 !parsed_function_.function().IsClosureFunction()) { |
| 889 __ popq(CTX); | 887 __ popq(CTX); |
| 890 } | 888 } |
| 891 } | 889 } |
| 890 set_context_level(previous_context_level); |
| 892 } | 891 } |
| 893 | 892 |
| 894 | 893 |
| 895 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { | 894 void CodeGenerator::VisitArgumentListNode(ArgumentListNode* arguments) { |
| 896 for (int i = 0; i < arguments->length(); i++) { | 895 for (int i = 0; i < arguments->length(); i++) { |
| 897 AstNode* argument = arguments->NodeAt(i); | 896 AstNode* argument = arguments->NodeAt(i); |
| 898 argument->Visit(this); | 897 argument->Visit(this); |
| 899 } | 898 } |
| 900 } | 899 } |
| 901 | 900 |
| (...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 | 1857 |
| 1859 // Generate inlined code for all finally blocks as we may transfer | 1858 // Generate inlined code for all finally blocks as we may transfer |
| 1860 // control out of the 'try' blocks if any. | 1859 // control out of the 'try' blocks if any. |
| 1861 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1860 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 1862 node->InlinedFinallyNodeAt(i)->Visit(this); | 1861 node->InlinedFinallyNodeAt(i)->Visit(this); |
| 1863 } | 1862 } |
| 1864 | 1863 |
| 1865 // Unchain the context(s) up to the outer context level of the scope which | 1864 // Unchain the context(s) up to the outer context level of the scope which |
| 1866 // contains the destination label. | 1865 // contains the destination label. |
| 1867 ASSERT(label->owner() != NULL); | 1866 ASSERT(label->owner() != NULL); |
| 1868 int target_context_level = 0; | 1867 intptr_t target_context_level = 0; |
| 1869 LocalScope* target_scope = label->owner(); | 1868 LocalScope* target_scope = label->owner(); |
| 1870 if (target_scope->num_context_variables() > 0) { | 1869 if (target_scope->num_context_variables() > 0) { |
| 1871 // The scope of the target label allocates a context, therefore its outer | 1870 // The scope of the target label allocates a context, therefore its outer |
| 1872 // scope is at a lower context level. | 1871 // scope is at a lower context level. |
| 1873 target_context_level = target_scope->context_level() - 1; | 1872 target_context_level = target_scope->context_level() - 1; |
| 1874 } else { | 1873 } else { |
| 1875 // The scope of the target label does not allocate a context, so its outer | 1874 // The scope of the target label does not allocate a context, so its outer |
| 1876 // scope is at the same context level. Find it. | 1875 // scope is at the same context level. Find it. |
| 1877 while ((target_scope != NULL) && | 1876 while ((target_scope != NULL) && |
| 1878 (target_scope->num_context_variables() == 0)) { | 1877 (target_scope->num_context_variables() == 0)) { |
| 1879 target_scope = target_scope->parent(); | 1878 target_scope = target_scope->parent(); |
| 1880 } | 1879 } |
| 1881 if (target_scope != NULL) { | 1880 if (target_scope != NULL) { |
| 1882 target_context_level = target_scope->context_level(); | 1881 target_context_level = target_scope->context_level(); |
| 1883 } | 1882 } |
| 1884 } | 1883 } |
| 1885 ASSERT(target_context_level >= 0); | 1884 ASSERT(target_context_level >= 0); |
| 1886 int context_level = state()->context_level(); | 1885 int current_context_level = context_level(); |
| 1887 ASSERT(context_level >= target_context_level); | 1886 ASSERT(current_context_level >= target_context_level); |
| 1888 while (context_level-- > target_context_level) { | 1887 while (current_context_level-- > target_context_level) { |
| 1889 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); | 1888 __ movq(CTX, FieldAddress(CTX, Context::parent_offset())); |
| 1890 } | 1889 } |
| 1891 | 1890 |
| 1892 if (node->kind() == Token::kBREAK) { | 1891 if (node->kind() == Token::kBREAK) { |
| 1893 __ jmp(label->break_label()); | 1892 __ jmp(label->break_label()); |
| 1894 } else { | 1893 } else { |
| 1895 __ jmp(label->continue_label()); | 1894 __ jmp(label->continue_label()); |
| 1896 } | 1895 } |
| 1897 } | 1896 } |
| 1898 | 1897 |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 // and ':stacktrace_var' can never be captured variables. | 2539 // and ':stacktrace_var' can never be captured variables. |
| 2541 // Restore CTX from local variable ':saved_context'. | 2540 // Restore CTX from local variable ':saved_context'. |
| 2542 GenerateLoadVariable(CTX, node->context_var()); | 2541 GenerateLoadVariable(CTX, node->context_var()); |
| 2543 | 2542 |
| 2544 // Restore RSP from RBP as we are coming from a throw and the code for | 2543 // Restore RSP from RBP as we are coming from a throw and the code for |
| 2545 // popping arguments has not been run. | 2544 // popping arguments has not been run. |
| 2546 ASSERT(locals_space_size() >= 0); | 2545 ASSERT(locals_space_size() >= 0); |
| 2547 __ movq(RSP, RBP); | 2546 __ movq(RSP, RBP); |
| 2548 __ subq(RSP, Immediate(locals_space_size())); | 2547 __ subq(RSP, Immediate(locals_space_size())); |
| 2549 | 2548 |
| 2550 if ((state()->context_level() > 0) && | 2549 if ((context_level() > 0) && |
| 2551 !parsed_function_.function().IsClosureFunction()) { | 2550 !parsed_function_.function().IsClosureFunction()) { |
| 2552 // CTX was saved on entry. | 2551 // CTX was saved on entry. |
| 2553 __ subq(RSP, Immediate(kWordSize)); | 2552 __ subq(RSP, Immediate(kWordSize)); |
| 2554 } | 2553 } |
| 2555 | 2554 |
| 2556 // The JumpToExceptionHandler trampoline code sets up | 2555 // The JumpToExceptionHandler trampoline code sets up |
| 2557 // - the exception object in RAX (kExceptionObjectReg) | 2556 // - the exception object in RAX (kExceptionObjectReg) |
| 2558 // - the stacktrace object in register RDX (kStackTraceObjectReg) | 2557 // - the stacktrace object in register RDX (kStackTraceObjectReg) |
| 2559 // We now setup the exception object and the trace object | 2558 // We now setup the exception object and the trace object |
| 2560 // so that the handler code has access to these objects. | 2559 // so that the handler code has access to these objects. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2696 const Error& error = Error::Handle( | 2695 const Error& error = Error::Handle( |
| 2697 Parser::FormatError(script, token_index, "Error", format, args)); | 2696 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2698 va_end(args); | 2697 va_end(args); |
| 2699 Isolate::Current()->long_jump_base()->Jump(1, error); | 2698 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2700 UNREACHABLE(); | 2699 UNREACHABLE(); |
| 2701 } | 2700 } |
| 2702 | 2701 |
| 2703 } // namespace dart | 2702 } // namespace dart |
| 2704 | 2703 |
| 2705 #endif // defined TARGET_ARCH_X64 | 2704 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |