Index: src/scopes.cc |
diff --git a/src/scopes.cc b/src/scopes.cc |
index 39b67a886444fe1db46a54e4006d37abd68d447a..cbb0d5dfe8f855e79eca7825c3f1f366ec1ffd80 100644 |
--- a/src/scopes.cc |
+++ b/src/scopes.cc |
@@ -609,6 +609,12 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, |
} |
} |
+ // Arrow functions can cause the receiver to be copied in the context. |
+ if (receiver_ && receiver_->has_forced_context_allocation()) { |
+ DCHECK(receiver_->IsContextSlot()); |
+ context_locals->Add(receiver_, zone()); |
+ } |
+ |
// Collect temporaries which are always allocated on the stack, unless the |
// context as a whole has forced context allocation. |
for (int i = 0; i < temps_.length(); i++) { |
@@ -1178,25 +1184,40 @@ void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { |
if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) { |
inner_scope_calls_eval_ = true; |
} |
+ |
// If the inner scope is an arrow function, propagate the flags tracking |
// usage of arguments/super/this, but do not propagate them out from normal |
// functions. |
- if (!inner->is_function_scope() || inner->is_arrow_scope()) { |
- if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) { |
+ if (inner->is_arrow_scope()) { |
+ if (inner->scope_uses_this_ || inner->inner_scope_uses_this_) |
+ inner_scope_uses_this_ = true; |
+ if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) |
inner_scope_uses_arguments_ = true; |
- } |
if (inner->scope_uses_super_property_ || |
- inner->inner_scope_uses_super_property_) { |
+ inner->inner_scope_uses_super_property_) |
inner_scope_uses_super_property_ = true; |
- } |
if (inner->uses_super_constructor_call() || |
- inner->inner_scope_uses_super_constructor_call_) { |
+ inner->inner_scope_uses_super_constructor_call_) |
inner_scope_uses_super_constructor_call_ = true; |
- } |
- if (inner->scope_uses_this_ || inner->inner_scope_uses_this_) { |
+ } else if (!inner->is_function_scope()) { |
+ if (inner->scope_uses_this_) |
+ scope_uses_this_ = true; |
+ if (inner->scope_uses_arguments_) |
+ scope_uses_arguments_ = true; |
+ if (inner->scope_uses_super_property_) |
+ scope_uses_super_property_ = true; |
+ if (inner->scope_uses_super_constructor_call_) |
+ scope_uses_super_constructor_call_ = true; |
+ if (inner->inner_scope_uses_this_) |
inner_scope_uses_this_ = true; |
- } |
+ if (inner->inner_scope_uses_arguments_) |
+ inner_scope_uses_arguments_ = true; |
+ if (inner->inner_scope_uses_super_property_) |
+ inner_scope_uses_super_property_ = true; |
+ if (inner->inner_scope_uses_super_constructor_call_) |
+ inner_scope_uses_super_constructor_call_ = true; |
} |
+ |
if (inner->force_eager_compilation_) { |
force_eager_compilation_ = true; |
} |
@@ -1324,6 +1345,18 @@ void Scope::AllocateParameterLocals() { |
} |
} |
} |
+ |
+ // If the scope contains at least one inner arrow function which uses |
+ // "this", the receiver must be copied to the context, from where it will |
+ // be looked up by code emitted in the prologues of arrow functions. |
+ if (inner_scope_uses_this_) { |
+ DCHECK(receiver_); |
+ if (receiver_->IsUnallocated() || !receiver_->IsContextSlot()) { |
+ receiver_->ForceContextAllocation(); |
+ AllocateHeapSlot(receiver_); |
+ } |
+ DCHECK(MustAllocateInContext(receiver_)); |
+ } |
} |