| Index: src/scopes.cc
 | 
| diff --git a/src/scopes.cc b/src/scopes.cc
 | 
| index 74d0c2a2e258f4140fa7f0b344b4eadfa8172854..e159257164086840e690f66f4006a202fb00df54 100644
 | 
| --- a/src/scopes.cc
 | 
| +++ b/src/scopes.cc
 | 
| @@ -157,6 +157,27 @@ Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
 | 
|    }
 | 
|  
 | 
|    AddInnerScope(inner_scope);
 | 
| +
 | 
| +  // This scope's arguments shadow (if present) is context-allocated if an inner
 | 
| +  // scope accesses this one's parameters.  Allocate the arguments_shadow_
 | 
| +  // variable if necessary.
 | 
| +  Isolate* isolate = Isolate::Current();
 | 
| +  Variable::Mode mode;
 | 
| +  int arguments_shadow_index =
 | 
| +      scope_info_->ContextSlotIndex(
 | 
| +          isolate->heap()->arguments_shadow_symbol(), &mode);
 | 
| +  if (arguments_shadow_index >= 0) {
 | 
| +    ASSERT(mode == Variable::INTERNAL);
 | 
| +    arguments_shadow_ = new Variable(
 | 
| +        this,
 | 
| +        isolate->factory()->arguments_shadow_symbol(),
 | 
| +        Variable::INTERNAL,
 | 
| +        true,
 | 
| +        Variable::ARGUMENTS);
 | 
| +    arguments_shadow_->set_rewrite(
 | 
| +        new Slot(arguments_shadow_, Slot::CONTEXT, arguments_shadow_index));
 | 
| +    arguments_shadow_->set_is_used(true);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -170,6 +191,7 @@ void Scope::SetDefaults(Type type,
 | 
|    receiver_ = NULL;
 | 
|    function_ = NULL;
 | 
|    arguments_ = NULL;
 | 
| +  arguments_shadow_ = NULL;
 | 
|    illegal_redecl_ = NULL;
 | 
|    scope_inside_with_ = false;
 | 
|    scope_contains_with_ = false;
 | 
| @@ -277,33 +299,52 @@ Variable* Scope::LocalLookup(Handle<String> name) {
 | 
|    if (result != NULL || !resolved()) {
 | 
|      return result;
 | 
|    }
 | 
| -  // If the scope is resolved, we can find a variable in serialized scope
 | 
| -  // info.
 | 
| -  //
 | 
| -  // We should never lookup 'arguments' in this scope as it is implicitly
 | 
| -  // present in every scope.
 | 
| +  // If the scope is resolved, we can find a variable in serialized scope info.
 | 
| +
 | 
| +  // We should never lookup 'arguments' in this scope
 | 
| +  // as it is implicitly present in any scope.
 | 
|    ASSERT(*name != *FACTORY->arguments_symbol());
 | 
| -  // There should be no local slot with the given name.
 | 
| +
 | 
| +  // Assert that there is no local slot with the given name.
 | 
|    ASSERT(scope_info_->StackSlotIndex(*name) < 0);
 | 
|  
 | 
|    // Check context slot lookup.
 | 
|    Variable::Mode mode;
 | 
|    int index = scope_info_->ContextSlotIndex(*name, &mode);
 | 
| -  if (index < 0) {
 | 
| -    // Check parameters.
 | 
| -    mode = Variable::VAR;
 | 
| -    index = scope_info_->ParameterIndex(*name);
 | 
| -    if (index < 0) {
 | 
| -      // Check the function name.
 | 
| -      index = scope_info_->FunctionContextSlotIndex(*name);
 | 
| -      if (index < 0) return NULL;
 | 
| -    }
 | 
| +  if (index >= 0) {
 | 
| +    Variable* var =
 | 
| +        variables_.Declare(this, name, mode, true, Variable::NORMAL);
 | 
| +    var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
 | 
| +    return var;
 | 
|    }
 | 
|  
 | 
| -  Variable* var =
 | 
| -      variables_.Declare(this, name, mode, true, Variable::NORMAL);
 | 
| -  var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
 | 
| -  return var;
 | 
| +  index = scope_info_->ParameterIndex(*name);
 | 
| +  if (index >= 0) {
 | 
| +    // ".arguments" must be present in context slots.
 | 
| +    ASSERT(arguments_shadow_ != NULL);
 | 
| +    Variable* var =
 | 
| +        variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
 | 
| +    Property* rewrite =
 | 
| +        new Property(new VariableProxy(arguments_shadow_),
 | 
| +                     new Literal(Handle<Object>(Smi::FromInt(index))),
 | 
| +                     RelocInfo::kNoPosition,
 | 
| +                     Property::SYNTHETIC);
 | 
| +    rewrite->set_is_arguments_access(true);
 | 
| +    var->set_rewrite(rewrite);
 | 
| +    return var;
 | 
| +  }
 | 
| +
 | 
| +  index = scope_info_->FunctionContextSlotIndex(*name);
 | 
| +  if (index >= 0) {
 | 
| +    // Check that there is no local slot with the given name.
 | 
| +    ASSERT(scope_info_->StackSlotIndex(*name) < 0);
 | 
| +    Variable* var =
 | 
| +        variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
 | 
| +    var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
 | 
| +    return var;
 | 
| +  }
 | 
| +
 | 
| +  return NULL;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -911,17 +952,36 @@ void Scope::AllocateParameterLocals() {
 | 
|    Variable* arguments = LocalLookup(FACTORY->arguments_symbol());
 | 
|    ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
 | 
|  
 | 
| -  bool uses_nonstrict_arguments = false;
 | 
| +  // Parameters are rewritten to arguments[i] if 'arguments' is used in
 | 
| +  // a non-strict mode function. Strict mode code doesn't alias arguments.
 | 
| +  bool rewrite_parameters = false;
 | 
|  
 | 
|    if (MustAllocate(arguments) && !HasArgumentsParameter()) {
 | 
|      // 'arguments' is used. Unless there is also a parameter called
 | 
| -    // 'arguments', we must be conservative and allocate all parameters to
 | 
| -    // the context assuming they will be captured by the arguments object.
 | 
| -    // If we have a parameter named 'arguments', a (new) value is always
 | 
| -    // assigned to it via the function invocation. Then 'arguments' denotes
 | 
| -    // that specific parameter value and cannot be used to access the
 | 
| -    // parameters, which is why we don't need to allocate an arguments
 | 
| -    // object in that case.
 | 
| +    // 'arguments', we must be conservative and access all parameters via
 | 
| +    // the arguments object: The i'th parameter is rewritten into
 | 
| +    // '.arguments[i]' (*). If we have a parameter named 'arguments', a
 | 
| +    // (new) value is always assigned to it via the function
 | 
| +    // invocation. Then 'arguments' denotes that specific parameter value
 | 
| +    // and cannot be used to access the parameters, which is why we don't
 | 
| +    // need to rewrite in that case.
 | 
| +    //
 | 
| +    // (*) Instead of having a parameter called 'arguments', we may have an
 | 
| +    // assignment to 'arguments' in the function body, at some arbitrary
 | 
| +    // point in time (possibly through an 'eval()' call!). After that
 | 
| +    // assignment any re-write of parameters would be invalid (was bug
 | 
| +    // 881452). Thus, we introduce a shadow '.arguments'
 | 
| +    // variable which also points to the arguments object. For rewrites we
 | 
| +    // use '.arguments' which remains valid even if we assign to
 | 
| +    // 'arguments'. To summarize: If we need to rewrite, we allocate an
 | 
| +    // 'arguments' object dynamically upon function invocation. The compiler
 | 
| +    // introduces 2 local variables 'arguments' and '.arguments', both of
 | 
| +    // which originally point to the arguments object that was
 | 
| +    // allocated. All parameters are rewritten into property accesses via
 | 
| +    // the '.arguments' variable. Thus, any changes to properties of
 | 
| +    // 'arguments' are reflected in the variables and vice versa. If the
 | 
| +    // 'arguments' variable is changed, '.arguments' still points to the
 | 
| +    // correct arguments object and the rewrites still work.
 | 
|  
 | 
|      // We are using 'arguments'. Tell the code generator that is needs to
 | 
|      // allocate the arguments object by setting 'arguments_'.
 | 
| @@ -930,31 +990,75 @@ void Scope::AllocateParameterLocals() {
 | 
|      // In strict mode 'arguments' does not alias formal parameters.
 | 
|      // Therefore in strict mode we allocate parameters as if 'arguments'
 | 
|      // were not used.
 | 
| -    uses_nonstrict_arguments = !is_strict_mode();
 | 
| +    rewrite_parameters = !is_strict_mode();
 | 
|    }
 | 
|  
 | 
| -  // The same parameter may occur multiple times in the parameters_ list.
 | 
| -  // If it does, and if it is not copied into the context object, it must
 | 
| -  // receive the highest parameter index for that parameter; thus iteration
 | 
| -  // order is relevant!
 | 
| -  for (int i = params_.length() - 1; i >= 0; --i) {
 | 
| -    Variable* var = params_[i];
 | 
| -    ASSERT(var->scope() == this);
 | 
| -    if (uses_nonstrict_arguments) {
 | 
| -      // Give the parameter a use from an inner scope, to force allocation
 | 
| -      // to the context.
 | 
| -      var->MarkAsAccessedFromInnerScope();
 | 
| +  if (rewrite_parameters) {
 | 
| +    // We also need the '.arguments' shadow variable. Declare it and create
 | 
| +    // and bind the corresponding proxy. It's ok to declare it only now
 | 
| +    // because it's a local variable that is allocated after the parameters
 | 
| +    // have been allocated.
 | 
| +    //
 | 
| +    // Note: This is "almost" at temporary variable but we cannot use
 | 
| +    // NewTemporary() because the mode needs to be INTERNAL since this
 | 
| +    // variable may be allocated in the heap-allocated context (temporaries
 | 
| +    // are never allocated in the context).
 | 
| +    arguments_shadow_ = new Variable(this,
 | 
| +                                     FACTORY->arguments_shadow_symbol(),
 | 
| +                                     Variable::INTERNAL,
 | 
| +                                     true,
 | 
| +                                     Variable::ARGUMENTS);
 | 
| +    arguments_shadow_->set_is_used(true);
 | 
| +    temps_.Add(arguments_shadow_);
 | 
| +
 | 
| +    // Allocate the parameters by rewriting them into '.arguments[i]' accesses.
 | 
| +    for (int i = 0; i < params_.length(); i++) {
 | 
| +      Variable* var = params_[i];
 | 
| +      ASSERT(var->scope() == this);
 | 
| +      if (MustAllocate(var)) {
 | 
| +        if (MustAllocateInContext(var)) {
 | 
| +          // It is ok to set this only now, because arguments is a local
 | 
| +          // variable that is allocated after the parameters have been
 | 
| +          // allocated.
 | 
| +          arguments_shadow_->MarkAsAccessedFromInnerScope();
 | 
| +        }
 | 
| +        Property* rewrite =
 | 
| +            new Property(new VariableProxy(arguments_shadow_),
 | 
| +                         new Literal(Handle<Object>(Smi::FromInt(i))),
 | 
| +                         RelocInfo::kNoPosition,
 | 
| +                         Property::SYNTHETIC);
 | 
| +        rewrite->set_is_arguments_access(true);
 | 
| +        var->set_rewrite(rewrite);
 | 
| +      }
 | 
|      }
 | 
|  
 | 
| -    if (MustAllocate(var)) {
 | 
| -      if (MustAllocateInContext(var)) {
 | 
| -        ASSERT(var->rewrite() == NULL || var->IsContextSlot());
 | 
| -        if (var->rewrite() == NULL) {
 | 
| -          AllocateHeapSlot(var);
 | 
| -        }
 | 
| -      } else {
 | 
| -        ASSERT(var->rewrite() == NULL || var->IsParameter());
 | 
| -        if (var->rewrite() == NULL) {
 | 
| +  } else {
 | 
| +    // The arguments object is not used, so we can access parameters directly.
 | 
| +    // The same parameter may occur multiple times in the parameters_ list.
 | 
| +    // If it does, and if it is not copied into the context object, it must
 | 
| +    // receive the highest parameter index for that parameter; thus iteration
 | 
| +    // order is relevant!
 | 
| +    for (int i = 0; i < params_.length(); i++) {
 | 
| +      Variable* var = params_[i];
 | 
| +      ASSERT(var->scope() == this);
 | 
| +      if (MustAllocate(var)) {
 | 
| +        if (MustAllocateInContext(var)) {
 | 
| +          ASSERT(var->rewrite() == NULL ||
 | 
| +                 (var->AsSlot() != NULL &&
 | 
| +                  var->AsSlot()->type() == Slot::CONTEXT));
 | 
| +          if (var->rewrite() == NULL) {
 | 
| +            // Only set the heap allocation if the parameter has not
 | 
| +            // been allocated yet.
 | 
| +            AllocateHeapSlot(var);
 | 
| +          }
 | 
| +        } else {
 | 
| +          ASSERT(var->rewrite() == NULL ||
 | 
| +                 (var->AsSlot() != NULL &&
 | 
| +                  var->AsSlot()->type() == Slot::PARAMETER));
 | 
| +          // Set the parameter index always, even if the parameter
 | 
| +          // was seen before! (We need to access the actual parameter
 | 
| +          // supplied for the last occurrence of a multiply declared
 | 
| +          // parameter.)
 | 
|            var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
 | 
|          }
 | 
|        }
 | 
| @@ -966,9 +1070,8 @@ void Scope::AllocateParameterLocals() {
 | 
|  void Scope::AllocateNonParameterLocal(Variable* var) {
 | 
|    ASSERT(var->scope() == this);
 | 
|    ASSERT(var->rewrite() == NULL ||
 | 
| -         !var->IsVariable(FACTORY->result_symbol()) ||
 | 
| -         var->AsSlot() == NULL ||
 | 
| -         var->AsSlot()->type() != Slot::LOCAL);
 | 
| +         (!var->IsVariable(FACTORY->result_symbol())) ||
 | 
| +         (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL));
 | 
|    if (var->rewrite() == NULL && MustAllocate(var)) {
 | 
|      if (MustAllocateInContext(var)) {
 | 
|        AllocateHeapSlot(var);
 | 
| 
 |