Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(996)

Side by Side Diff: src/scopes.cc

Issue 7523027: Provisional implementation of stack allocated catch variables. Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/scopes.h ('k') | src/v8globals.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 scope_contains_with_ = false; 200 scope_contains_with_ = false;
201 scope_calls_eval_ = false; 201 scope_calls_eval_ = false;
202 // Inherit the strict mode from the parent scope. 202 // Inherit the strict mode from the parent scope.
203 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; 203 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
204 outer_scope_calls_eval_ = false; 204 outer_scope_calls_eval_ = false;
205 outer_scope_calls_non_strict_eval_ = false; 205 outer_scope_calls_non_strict_eval_ = false;
206 inner_scope_calls_eval_ = false; 206 inner_scope_calls_eval_ = false;
207 outer_scope_is_eval_scope_ = false; 207 outer_scope_is_eval_scope_ = false;
208 force_eager_compilation_ = false; 208 force_eager_compilation_ = false;
209 num_var_or_const_ = 0; 209 num_var_or_const_ = 0;
210 num_stack_allocs_ = 0;
210 num_stack_slots_ = 0; 211 num_stack_slots_ = 0;
211 num_heap_slots_ = 0; 212 num_heap_slots_ = 0;
212 scope_info_ = scope_info; 213 scope_info_ = scope_info;
214 if (!scope_info_.is_null()) {
215 source_beg_statement_pos_ = scope_info_->SourceBegStatementPos();
216 source_end_statement_pos_ = scope_info_->SourceEndStatementPos();
217 } else {
218 source_beg_statement_pos_ = -1;
219 source_end_statement_pos_ = -1;
220 }
213 } 221 }
214 222
215 223
216 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, 224 Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
217 Scope* global_scope) { 225 Scope* global_scope) {
218 // Reconstruct the outer scope chain from a closure's context chain. 226 // Reconstruct the outer scope chain from a closure's context chain.
219 ASSERT(!info->closure().is_null()); 227 ASSERT(!info->closure().is_null());
220 Context* context = info->closure()->context(); 228 Context* context = info->closure()->context();
221 Scope* current_scope = NULL; 229 Scope* current_scope = NULL;
222 Scope* innermost_scope = NULL; 230 Scope* innermost_scope = NULL;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 } 295 }
288 296
289 // Declare convenience variables. 297 // Declare convenience variables.
290 // Declare and allocate receiver (even for the global scope, and even 298 // Declare and allocate receiver (even for the global scope, and even
291 // if naccesses_ == 0). 299 // if naccesses_ == 0).
292 // NOTE: When loading parameters in the global scope, we must take 300 // NOTE: When loading parameters in the global scope, we must take
293 // care not to access them as properties of the global object, but 301 // care not to access them as properties of the global object, but
294 // instead load them directly from the stack. Currently, the only 302 // instead load them directly from the stack. Currently, the only
295 // such parameter is 'this' which is passed on the stack when 303 // such parameter is 'this' which is passed on the stack when
296 // invoking scripts 304 // invoking scripts
297 if (is_catch_scope()) { 305 if (is_catch_scope() || is_with_scope()) {
298 ASSERT(outer_scope() != NULL); 306 ASSERT(outer_scope() != NULL);
299 receiver_ = outer_scope()->receiver(); 307 receiver_ = outer_scope()->receiver();
300 } else { 308 } else {
301 Variable* var = 309 Variable* var =
302 variables_.Declare(this, 310 variables_.Declare(this,
303 isolate_->factory()->this_symbol(), 311 isolate_->factory()->this_symbol(),
304 Variable::VAR, 312 Variable::VAR,
305 false, 313 false,
306 Variable::THIS); 314 Variable::THIS);
307 var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1)); 315 var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1));
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 bool Scope::HasTrivialOuterContext() const { 548 bool Scope::HasTrivialOuterContext() const {
541 Scope* outer = outer_scope_; 549 Scope* outer = outer_scope_;
542 if (outer == NULL) return true; 550 if (outer == NULL) return true;
543 // Note that the outer context may be trivial in general, but the current 551 // Note that the outer context may be trivial in general, but the current
544 // scope may be inside a 'with' statement in which case the outer context 552 // scope may be inside a 'with' statement in which case the outer context
545 // for this scope is not trivial. 553 // for this scope is not trivial.
546 return !scope_inside_with_ && outer->HasTrivialContext(); 554 return !scope_inside_with_ && outer->HasTrivialContext();
547 } 555 }
548 556
549 557
558 bool Scope::HasContext() const {
559 return num_heap_slots() > 0 || is_with_scope();
560 }
561
562
550 int Scope::ContextChainLength(Scope* scope) { 563 int Scope::ContextChainLength(Scope* scope) {
551 int n = 0; 564 int n = 0;
552 for (Scope* s = this; s != scope; s = s->outer_scope_) { 565 for (Scope* s = this; s != scope; s = s->outer_scope_) {
553 ASSERT(s != NULL); // scope must be in the scope chain 566 ASSERT(s != NULL); // scope must be in the scope chain
554 if (s->num_heap_slots() > 0) n++; 567 if (s->HasContext()) n++;
555 } 568 }
556 return n; 569 return n;
557 } 570 }
558 571
559 572
560 Scope* Scope::DeclarationScope() { 573 Scope* Scope::DeclarationScope() {
561 Scope* scope = this; 574 Scope* scope = this;
562 while (scope->is_catch_scope()) { 575 while (scope->is_catch_scope() || scope->is_with_scope()) {
563 scope = scope->outer_scope(); 576 scope = scope->outer_scope();
564 } 577 }
565 return scope; 578 return scope;
566 } 579 }
567 580
568 581
569 #ifdef DEBUG 582 #ifdef DEBUG
570 static const char* Header(Scope::Type type) { 583 static const char* Header(Scope::Type type) {
571 switch (type) { 584 switch (type) {
572 case Scope::EVAL_SCOPE: return "eval"; 585 case Scope::EVAL_SCOPE: return "eval";
573 case Scope::FUNCTION_SCOPE: return "function"; 586 case Scope::FUNCTION_SCOPE: return "function";
574 case Scope::GLOBAL_SCOPE: return "global"; 587 case Scope::GLOBAL_SCOPE: return "global";
575 case Scope::CATCH_SCOPE: return "catch"; 588 case Scope::CATCH_SCOPE: return "catch";
589 case Scope::WITH_SCOPE: return "with";
576 } 590 }
577 UNREACHABLE(); 591 UNREACHABLE();
578 return NULL; 592 return NULL;
579 } 593 }
580 594
581 595
582 static void Indent(int n, const char* str) { 596 static void Indent(int n, const char* str) {
583 PrintF("%*s%s", n, "", str); 597 PrintF("%*s%s", n, "", str);
584 } 598 }
585 599
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 Indent(n1, "// outer scope calls 'eval' in non-strict context\n"); 671 Indent(n1, "// outer scope calls 'eval' in non-strict context\n");
658 } 672 }
659 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 673 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
660 if (outer_scope_is_eval_scope_) { 674 if (outer_scope_is_eval_scope_) {
661 Indent(n1, "// outer scope is 'eval' scope\n"); 675 Indent(n1, "// outer scope is 'eval' scope\n");
662 } 676 }
663 if (num_stack_slots_ > 0) { Indent(n1, "// "); 677 if (num_stack_slots_ > 0) { Indent(n1, "// ");
664 PrintF("%d stack slots\n", num_stack_slots_); } 678 PrintF("%d stack slots\n", num_stack_slots_); }
665 if (num_heap_slots_ > 0) { Indent(n1, "// "); 679 if (num_heap_slots_ > 0) { Indent(n1, "// ");
666 PrintF("%d heap slots\n", num_heap_slots_); } 680 PrintF("%d heap slots\n", num_heap_slots_); }
681 if (num_stack_allocs_ > 0) { Indent(n1, "// ");
682 PrintF("%d stack allocs\n", num_stack_allocs_); }
667 683
668 // Print locals. 684 // Print locals.
669 PrettyPrinter printer; 685 PrettyPrinter printer;
670 Indent(n1, "// function var\n"); 686 Indent(n1, "// function var\n");
671 if (function_ != NULL) { 687 if (function_ != NULL) {
672 PrintVar(&printer, n1, function_); 688 PrintVar(&printer, n1, function_);
673 } 689 }
674 690
675 Indent(n1, "// temporary vars\n"); 691 Indent(n1, "// temporary vars\n");
676 for (int i = 0; i < temps_.length(); i++) { 692 for (int i = 0; i < temps_.length(); i++) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 // only present - if at all - for function scopes. 762 // only present - if at all - for function scopes.
747 // 763 //
748 // This lookup corresponds to a lookup in the "intermediate" scope sitting 764 // This lookup corresponds to a lookup in the "intermediate" scope sitting
749 // between this scope and the outer scope. (ECMA-262, 3rd., requires that 765 // between this scope and the outer scope. (ECMA-262, 3rd., requires that
750 // the name of named function literal is kept in an intermediate scope 766 // the name of named function literal is kept in an intermediate scope
751 // in between this scope and the next outer scope.) 767 // in between this scope and the next outer scope.)
752 if (function_ != NULL && function_->name().is_identical_to(name)) { 768 if (function_ != NULL && function_->name().is_identical_to(name)) {
753 var = function_; 769 var = function_;
754 770
755 } else if (outer_scope_ != NULL) { 771 } else if (outer_scope_ != NULL) {
756 var = outer_scope_->LookupRecursive(name, true, invalidated_local); 772 var = outer_scope_->LookupRecursive(name,
773 inner_lookup || is_function_scope(),
774 invalidated_local);
757 // We may have found a variable in an outer scope. However, if 775 // We may have found a variable in an outer scope. However, if
758 // the current scope is inside a 'with', the actual variable may 776 // the current scope is inside a 'with', the actual variable may
759 // be a property introduced via the 'with' statement. Then, the 777 // be a property introduced via the 'with' statement. Then, the
760 // variable we may have found is just a guess. 778 // variable we may have found is just a guess.
761 if (scope_inside_with_) 779 if (scope_inside_with_)
762 guess = true; 780 guess = true;
763 } 781 }
764 782
765 // If we did not find a variable, we are done. 783 // If we did not find a variable, we are done.
766 if (var == NULL) 784 if (var == NULL)
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 954
937 bool Scope::MustAllocateInContext(Variable* var) { 955 bool Scope::MustAllocateInContext(Variable* var) {
938 // If var is accessed from an inner scope, or if there is a possibility 956 // If var is accessed from an inner scope, or if there is a possibility
939 // that it might be accessed from the current or an inner scope (through 957 // that it might be accessed from the current or an inner scope (through
940 // an eval() call or a runtime with lookup), it must be allocated in the 958 // an eval() call or a runtime with lookup), it must be allocated in the
941 // context. 959 // context.
942 // 960 //
943 // Exceptions: temporary variables are never allocated in a context; 961 // Exceptions: temporary variables are never allocated in a context;
944 // catch-bound variables are always allocated in a context. 962 // catch-bound variables are always allocated in a context.
945 if (var->mode() == Variable::TEMPORARY) return false; 963 if (var->mode() == Variable::TEMPORARY) return false;
946 if (is_catch_scope()) return true; 964 if (is_catch_scope() && !DeclarationScope()->is_function_scope()) return true;
947 return var->is_accessed_from_inner_scope() || 965 return var->is_accessed_from_inner_scope() ||
948 scope_calls_eval_ || 966 scope_calls_eval_ ||
949 inner_scope_calls_eval_ || 967 inner_scope_calls_eval_ ||
950 scope_contains_with_ || 968 scope_contains_with_ ||
951 var->is_global(); 969 var->is_global();
952 } 970 }
953 971
954 972
955 bool Scope::HasArgumentsParameter() { 973 bool Scope::HasArgumentsParameter() {
956 for (int i = 0; i < params_.length(); i++) { 974 for (int i = 0; i < params_.length(); i++) {
957 if (params_[i]->name().is_identical_to( 975 if (params_[i]->name().is_identical_to(
958 isolate_->factory()->arguments_symbol())) { 976 isolate_->factory()->arguments_symbol())) {
959 return true; 977 return true;
960 } 978 }
961 } 979 }
962 return false; 980 return false;
963 } 981 }
964 982
965 983
966 void Scope::AllocateStackSlot(Variable* var) { 984 void Scope::AllocateStackSlot(Variable* var) {
967 var->set_rewrite(NewSlot(var, Slot::LOCAL, num_stack_slots_++)); 985 Scope* scope = DeclarationScope();
986 var->set_rewrite(NewSlot(var, Slot::LOCAL, scope->num_stack_allocs_++));
987 num_stack_slots_++;
968 } 988 }
969 989
970 990
971 void Scope::AllocateHeapSlot(Variable* var) { 991 void Scope::AllocateHeapSlot(Variable* var) {
972 var->set_rewrite(NewSlot(var, Slot::CONTEXT, num_heap_slots_++)); 992 var->set_rewrite(NewSlot(var, Slot::CONTEXT, num_heap_slots_++));
973 } 993 }
974 994
975 995
976 void Scope::AllocateParameterLocals() { 996 void Scope::AllocateParameterLocals() {
977 ASSERT(is_function_scope()); 997 ASSERT(is_function_scope());
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 // allocated in the context, it must be the last slot in the context, 1083 // allocated in the context, it must be the last slot in the context,
1064 // because of the current ScopeInfo implementation (see 1084 // because of the current ScopeInfo implementation (see
1065 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). 1085 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1066 if (function_ != NULL) { 1086 if (function_ != NULL) {
1067 AllocateNonParameterLocal(function_); 1087 AllocateNonParameterLocal(function_);
1068 } 1088 }
1069 } 1089 }
1070 1090
1071 1091
1072 void Scope::AllocateVariablesRecursively() { 1092 void Scope::AllocateVariablesRecursively() {
1073 // Allocate variables for inner scopes. 1093 // If scope is already resolved, we still need to allocate
1094 // variables in inner scopes which might not had been resolved yet.
1095 if (!already_resolved()) {
1096 // The number of slots required for variables.
1097 num_stack_slots_ = 0;
1098 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1099
1100 // Allocate variables for this scope.
1101 // Parameters must be allocated first, if any.
1102 if (is_function_scope()) AllocateParameterLocals();
1103 AllocateNonParameterLocals();
1104
1105 // Allocate context if necessary.
1106 bool must_have_local_context = false;
1107 if (scope_calls_eval_ || scope_contains_with_) {
1108 // The context for the eval() call or 'with' statement in this scope.
1109 // Unless we are in the global or an eval scope, we need a local
1110 // context even if we didn't statically allocate any locals in it,
1111 // and the compiler will access the context variable. If we are
1112 // not in an inner scope, the scope is provided from the outside.
1113 must_have_local_context = is_function_scope();
1114 }
1115
1116 // If we didn't allocate any locals in the local context, then we only
1117 // need the minimal number of slots if we must have a local context.
1118 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1119 !must_have_local_context) {
1120 num_heap_slots_ = 0;
1121 }
1122
1123 // Allocation done.
1124 ASSERT(num_heap_slots_ == 0 ||
1125 num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1126 }
1127
1128 // Allocate variables for inner scopes. Must be done after parameters and
1129 // local variables to allow reservation of stack slots for variables from
1130 // nested blocks.
1074 for (int i = 0; i < inner_scopes_.length(); i++) { 1131 for (int i = 0; i < inner_scopes_.length(); i++) {
1075 inner_scopes_[i]->AllocateVariablesRecursively(); 1132 inner_scopes_[i]->AllocateVariablesRecursively();
1076 } 1133 }
1077
1078 // If scope is already resolved, we still need to allocate
1079 // variables in inner scopes which might not had been resolved yet.
1080 if (already_resolved()) return;
1081 // The number of slots required for variables.
1082 num_stack_slots_ = 0;
1083 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1084
1085 // Allocate variables for this scope.
1086 // Parameters must be allocated first, if any.
1087 if (is_function_scope()) AllocateParameterLocals();
1088 AllocateNonParameterLocals();
1089
1090 // Allocate context if necessary.
1091 bool must_have_local_context = false;
1092 if (scope_calls_eval_ || scope_contains_with_) {
1093 // The context for the eval() call or 'with' statement in this scope.
1094 // Unless we are in the global or an eval scope, we need a local
1095 // context even if we didn't statically allocate any locals in it,
1096 // and the compiler will access the context variable. If we are
1097 // not in an inner scope, the scope is provided from the outside.
1098 must_have_local_context = is_function_scope();
1099 }
1100
1101 // If we didn't allocate any locals in the local context, then we only
1102 // need the minimal number of slots if we must have a local context.
1103 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1104 !must_have_local_context) {
1105 num_heap_slots_ = 0;
1106 }
1107
1108 // Allocation done.
1109 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1110 } 1134 }
1111 1135
1112 } } // namespace v8::internal 1136 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | src/v8globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698