The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / scopes.cc @ f230a1cf

History | View | Annotate | Download (45 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include "v8.h"
29

    
30
#include "scopes.h"
31

    
32
#include "accessors.h"
33
#include "bootstrapper.h"
34
#include "compiler.h"
35
#include "messages.h"
36
#include "scopeinfo.h"
37

    
38
#include "allocation-inl.h"
39

    
40
namespace v8 {
41
namespace internal {
42

    
43
// ----------------------------------------------------------------------------
44
// Implementation of LocalsMap
45
//
46
// Note: We are storing the handle locations as key values in the hash map.
47
//       When inserting a new variable via Declare(), we rely on the fact that
48
//       the handle location remains alive for the duration of that variable
49
//       use. Because a Variable holding a handle with the same location exists
50
//       this is ensured.
51

    
52
static bool Match(void* key1, void* key2) {
53
  String* name1 = *reinterpret_cast<String**>(key1);
54
  String* name2 = *reinterpret_cast<String**>(key2);
55
  ASSERT(name1->IsInternalizedString());
56
  ASSERT(name2->IsInternalizedString());
57
  return name1 == name2;
58
}
59

    
60

    
61
VariableMap::VariableMap(Zone* zone)
62
    : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)),
63
      zone_(zone) {}
64
VariableMap::~VariableMap() {}
65

    
66

    
67
Variable* VariableMap::Declare(
68
    Scope* scope,
69
    Handle<String> name,
70
    VariableMode mode,
71
    bool is_valid_lhs,
72
    Variable::Kind kind,
73
    InitializationFlag initialization_flag,
74
    Interface* interface) {
75
  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true,
76
                                 ZoneAllocationPolicy(zone()));
77
  if (p->value == NULL) {
78
    // The variable has not been declared yet -> insert it.
79
    ASSERT(p->key == name.location());
80
    p->value = new(zone()) Variable(scope,
81
                                    name,
82
                                    mode,
83
                                    is_valid_lhs,
84
                                    kind,
85
                                    initialization_flag,
86
                                    interface);
87
  }
88
  return reinterpret_cast<Variable*>(p->value);
89
}
90

    
91

    
92
Variable* VariableMap::Lookup(Handle<String> name) {
93
  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false,
94
                                 ZoneAllocationPolicy(NULL));
95
  if (p != NULL) {
96
    ASSERT(*reinterpret_cast<String**>(p->key) == *name);
97
    ASSERT(p->value != NULL);
98
    return reinterpret_cast<Variable*>(p->value);
99
  }
100
  return NULL;
101
}
102

    
103

    
104
// ----------------------------------------------------------------------------
105
// Implementation of Scope
106

    
107
Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
108
    : isolate_(zone->isolate()),
109
      inner_scopes_(4, zone),
110
      variables_(zone),
111
      internals_(4, zone),
112
      temps_(4, zone),
113
      params_(4, zone),
114
      unresolved_(16, zone),
115
      decls_(4, zone),
116
      interface_(FLAG_harmony_modules &&
117
                 (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
118
                     ? Interface::NewModule(zone) : NULL),
119
      already_resolved_(false),
120
      zone_(zone) {
121
  SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
122
  // The outermost scope must be a global scope.
123
  ASSERT(scope_type == GLOBAL_SCOPE || outer_scope != NULL);
124
  ASSERT(!HasIllegalRedeclaration());
125
}
126

    
127

    
128
Scope::Scope(Scope* inner_scope,
129
             ScopeType scope_type,
130
             Handle<ScopeInfo> scope_info,
131
             Zone* zone)
132
    : isolate_(zone->isolate()),
133
      inner_scopes_(4, zone),
134
      variables_(zone),
135
      internals_(4, zone),
136
      temps_(4, zone),
137
      params_(4, zone),
138
      unresolved_(16, zone),
139
      decls_(4, zone),
140
      interface_(NULL),
141
      already_resolved_(true),
142
      zone_(zone) {
143
  SetDefaults(scope_type, NULL, scope_info);
144
  if (!scope_info.is_null()) {
145
    num_heap_slots_ = scope_info_->ContextLength();
146
  }
147
  // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
148
  num_heap_slots_ = Max(num_heap_slots_,
149
                        static_cast<int>(Context::MIN_CONTEXT_SLOTS));
150
  AddInnerScope(inner_scope);
151
}
152

    
153

    
154
Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
155
    : isolate_(zone->isolate()),
156
      inner_scopes_(1, zone),
157
      variables_(zone),
158
      internals_(0, zone),
159
      temps_(0, zone),
160
      params_(0, zone),
161
      unresolved_(0, zone),
162
      decls_(0, zone),
163
      interface_(NULL),
164
      already_resolved_(true),
165
      zone_(zone) {
166
  SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
167
  AddInnerScope(inner_scope);
168
  ++num_var_or_const_;
169
  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
170
  Variable* variable = variables_.Declare(this,
171
                                          catch_variable_name,
172
                                          VAR,
173
                                          true,  // Valid left-hand side.
174
                                          Variable::NORMAL,
175
                                          kCreatedInitialized);
176
  AllocateHeapSlot(variable);
177
}
178

    
179

    
180
void Scope::SetDefaults(ScopeType scope_type,
181
                        Scope* outer_scope,
182
                        Handle<ScopeInfo> scope_info) {
183
  outer_scope_ = outer_scope;
184
  scope_type_ = scope_type;
185
  scope_name_ = isolate_->factory()->empty_string();
186
  dynamics_ = NULL;
187
  receiver_ = NULL;
188
  function_ = NULL;
189
  arguments_ = NULL;
190
  illegal_redecl_ = NULL;
191
  scope_inside_with_ = false;
192
  scope_contains_with_ = false;
193
  scope_calls_eval_ = false;
194
  // Inherit the strict mode from the parent scope.
195
  language_mode_ = (outer_scope != NULL)
196
      ? outer_scope->language_mode_ : CLASSIC_MODE;
197
  outer_scope_calls_non_strict_eval_ = false;
198
  inner_scope_calls_eval_ = false;
199
  force_eager_compilation_ = false;
200
  force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
201
      ? outer_scope->has_forced_context_allocation() : false;
202
  num_var_or_const_ = 0;
203
  num_stack_slots_ = 0;
204
  num_heap_slots_ = 0;
205
  num_modules_ = 0;
206
  module_var_ = NULL,
207
  scope_info_ = scope_info;
208
  start_position_ = RelocInfo::kNoPosition;
209
  end_position_ = RelocInfo::kNoPosition;
210
  if (!scope_info.is_null()) {
211
    scope_calls_eval_ = scope_info->CallsEval();
212
    language_mode_ = scope_info->language_mode();
213
  }
214
}
215

    
216

    
217
Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
218
                                    Zone* zone) {
219
  // Reconstruct the outer scope chain from a closure's context chain.
220
  Scope* current_scope = NULL;
221
  Scope* innermost_scope = NULL;
222
  bool contains_with = false;
223
  while (!context->IsNativeContext()) {
224
    if (context->IsWithContext()) {
225
      Scope* with_scope = new(zone) Scope(current_scope,
226
                                          WITH_SCOPE,
227
                                          Handle<ScopeInfo>::null(),
228
                                          zone);
229
      current_scope = with_scope;
230
      // All the inner scopes are inside a with.
231
      contains_with = true;
232
      for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
233
        s->scope_inside_with_ = true;
234
      }
235
    } else if (context->IsGlobalContext()) {
236
      ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
237
      current_scope = new(zone) Scope(current_scope,
238
                                      GLOBAL_SCOPE,
239
                                      Handle<ScopeInfo>(scope_info),
240
                                      zone);
241
    } else if (context->IsModuleContext()) {
242
      ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
243
      current_scope = new(zone) Scope(current_scope,
244
                                      MODULE_SCOPE,
245
                                      Handle<ScopeInfo>(scope_info),
246
                                      zone);
247
    } else if (context->IsFunctionContext()) {
248
      ScopeInfo* scope_info = context->closure()->shared()->scope_info();
249
      current_scope = new(zone) Scope(current_scope,
250
                                      FUNCTION_SCOPE,
251
                                      Handle<ScopeInfo>(scope_info),
252
                                      zone);
253
    } else if (context->IsBlockContext()) {
254
      ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
255
      current_scope = new(zone) Scope(current_scope,
256
                                      BLOCK_SCOPE,
257
                                      Handle<ScopeInfo>(scope_info),
258
                                      zone);
259
    } else {
260
      ASSERT(context->IsCatchContext());
261
      String* name = String::cast(context->extension());
262
      current_scope = new(zone) Scope(
263
          current_scope, Handle<String>(name), zone);
264
    }
265
    if (contains_with) current_scope->RecordWithStatement();
266
    if (innermost_scope == NULL) innermost_scope = current_scope;
267

    
268
    // Forget about a with when we move to a context for a different function.
269
    if (context->previous()->closure() != context->closure()) {
270
      contains_with = false;
271
    }
272
    context = context->previous();
273
  }
274

    
275
  global_scope->AddInnerScope(current_scope);
276
  global_scope->PropagateScopeInfo(false);
277
  return (innermost_scope == NULL) ? global_scope : innermost_scope;
278
}
279

    
280

    
281
bool Scope::Analyze(CompilationInfo* info) {
282
  ASSERT(info->function() != NULL);
283
  Scope* scope = info->function()->scope();
284
  Scope* top = scope;
285

    
286
  // Traverse the scope tree up to the first unresolved scope or the global
287
  // scope and start scope resolution and variable allocation from that scope.
288
  while (!top->is_global_scope() &&
289
         !top->outer_scope()->already_resolved()) {
290
    top = top->outer_scope();
291
  }
292

    
293
  // Allocate the variables.
294
  {
295
    AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate(),
296
                                                    info->zone());
297
    if (!top->AllocateVariables(info, &ast_node_factory)) return false;
298
  }
299

    
300
#ifdef DEBUG
301
  if (info->isolate()->bootstrapper()->IsActive()
302
          ? FLAG_print_builtin_scopes
303
          : FLAG_print_scopes) {
304
    scope->Print();
305
  }
306

    
307
  if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) {
308
    PrintF("global : ");
309
    top->interface()->Print();
310
  }
311
#endif
312

    
313
  info->SetScope(scope);
314
  return true;
315
}
316

    
317

    
318
void Scope::Initialize() {
319
  ASSERT(!already_resolved());
320

    
321
  // Add this scope as a new inner scope of the outer scope.
322
  if (outer_scope_ != NULL) {
323
    outer_scope_->inner_scopes_.Add(this, zone());
324
    scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
325
  } else {
326
    scope_inside_with_ = is_with_scope();
327
  }
328

    
329
  // Declare convenience variables.
330
  // Declare and allocate receiver (even for the global scope, and even
331
  // if naccesses_ == 0).
332
  // NOTE: When loading parameters in the global scope, we must take
333
  // care not to access them as properties of the global object, but
334
  // instead load them directly from the stack. Currently, the only
335
  // such parameter is 'this' which is passed on the stack when
336
  // invoking scripts
337
  if (is_declaration_scope()) {
338
    Variable* var =
339
        variables_.Declare(this,
340
                           isolate_->factory()->this_string(),
341
                           VAR,
342
                           false,
343
                           Variable::THIS,
344
                           kCreatedInitialized);
345
    var->AllocateTo(Variable::PARAMETER, -1);
346
    receiver_ = var;
347
  } else {
348
    ASSERT(outer_scope() != NULL);
349
    receiver_ = outer_scope()->receiver();
350
  }
351

    
352
  if (is_function_scope()) {
353
    // Declare 'arguments' variable which exists in all functions.
354
    // Note that it might never be accessed, in which case it won't be
355
    // allocated during variable allocation.
356
    variables_.Declare(this,
357
                       isolate_->factory()->arguments_string(),
358
                       VAR,
359
                       true,
360
                       Variable::ARGUMENTS,
361
                       kCreatedInitialized);
362
  }
363
}
364

    
365

    
366
Scope* Scope::FinalizeBlockScope() {
367
  ASSERT(is_block_scope());
368
  ASSERT(internals_.is_empty());
369
  ASSERT(temps_.is_empty());
370
  ASSERT(params_.is_empty());
371

    
372
  if (num_var_or_const() > 0) return this;
373

    
374
  // Remove this scope from outer scope.
375
  for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
376
    if (outer_scope_->inner_scopes_[i] == this) {
377
      outer_scope_->inner_scopes_.Remove(i);
378
      break;
379
    }
380
  }
381

    
382
  // Reparent inner scopes.
383
  for (int i = 0; i < inner_scopes_.length(); i++) {
384
    outer_scope()->AddInnerScope(inner_scopes_[i]);
385
  }
386

    
387
  // Move unresolved variables
388
  for (int i = 0; i < unresolved_.length(); i++) {
389
    outer_scope()->unresolved_.Add(unresolved_[i], zone());
390
  }
391

    
392
  return NULL;
393
}
394

    
395

    
396
Variable* Scope::LocalLookup(Handle<String> name) {
397
  Variable* result = variables_.Lookup(name);
398
  if (result != NULL || scope_info_.is_null()) {
399
    return result;
400
  }
401
  // If we have a serialized scope info, we might find the variable there.
402
  // There should be no local slot with the given name.
403
  ASSERT(scope_info_->StackSlotIndex(*name) < 0);
404

    
405
  // Check context slot lookup.
406
  VariableMode mode;
407
  Variable::Location location = Variable::CONTEXT;
408
  InitializationFlag init_flag;
409
  int index = scope_info_->ContextSlotIndex(*name, &mode, &init_flag);
410
  if (index < 0) {
411
    // Check parameters.
412
    index = scope_info_->ParameterIndex(*name);
413
    if (index < 0) return NULL;
414

    
415
    mode = DYNAMIC;
416
    location = Variable::LOOKUP;
417
    init_flag = kCreatedInitialized;
418
  }
419

    
420
  Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
421
                                     init_flag);
422
  var->AllocateTo(location, index);
423
  return var;
424
}
425

    
426

    
427
Variable* Scope::LookupFunctionVar(Handle<String> name,
428
                                   AstNodeFactory<AstNullVisitor>* factory) {
429
  if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
430
    return function_->proxy()->var();
431
  } else if (!scope_info_.is_null()) {
432
    // If we are backed by a scope info, try to lookup the variable there.
433
    VariableMode mode;
434
    int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
435
    if (index < 0) return NULL;
436
    Variable* var = new(zone()) Variable(
437
        this, name, mode, true /* is valid LHS */,
438
        Variable::NORMAL, kCreatedInitialized);
439
    VariableProxy* proxy = factory->NewVariableProxy(var);
440
    VariableDeclaration* declaration = factory->NewVariableDeclaration(
441
        proxy, mode, this, RelocInfo::kNoPosition);
442
    DeclareFunctionVar(declaration);
443
    var->AllocateTo(Variable::CONTEXT, index);
444
    return var;
445
  } else {
446
    return NULL;
447
  }
448
}
449

    
450

    
451
Variable* Scope::Lookup(Handle<String> name) {
452
  for (Scope* scope = this;
453
       scope != NULL;
454
       scope = scope->outer_scope()) {
455
    Variable* var = scope->LocalLookup(name);
456
    if (var != NULL) return var;
457
  }
458
  return NULL;
459
}
460

    
461

    
462
void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
463
  ASSERT(!already_resolved());
464
  ASSERT(is_function_scope());
465
  Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
466
                                     kCreatedInitialized);
467
  params_.Add(var, zone());
468
}
469

    
470

    
471
Variable* Scope::DeclareLocal(Handle<String> name,
472
                              VariableMode mode,
473
                              InitializationFlag init_flag,
474
                              Interface* interface) {
475
  ASSERT(!already_resolved());
476
  // This function handles VAR and CONST modes.  DYNAMIC variables are
477
  // introduces during variable allocation, INTERNAL variables are allocated
478
  // explicitly, and TEMPORARY variables are allocated via NewTemporary().
479
  ASSERT(IsDeclaredVariableMode(mode));
480
  ++num_var_or_const_;
481
  return variables_.Declare(
482
      this, name, mode, true, Variable::NORMAL, init_flag, interface);
483
}
484

    
485

    
486
Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
487
  ASSERT(is_global_scope());
488
  return variables_.Declare(this,
489
                            name,
490
                            DYNAMIC_GLOBAL,
491
                            true,
492
                            Variable::NORMAL,
493
                            kCreatedInitialized);
494
}
495

    
496

    
497
void Scope::RemoveUnresolved(VariableProxy* var) {
498
  // Most likely (always?) any variable we want to remove
499
  // was just added before, so we search backwards.
500
  for (int i = unresolved_.length(); i-- > 0;) {
501
    if (unresolved_[i] == var) {
502
      unresolved_.Remove(i);
503
      return;
504
    }
505
  }
506
}
507

    
508

    
509
Variable* Scope::NewInternal(Handle<String> name) {
510
  ASSERT(!already_resolved());
511
  Variable* var = new(zone()) Variable(this,
512
                                       name,
513
                                       INTERNAL,
514
                                       false,
515
                                       Variable::NORMAL,
516
                                       kCreatedInitialized);
517
  internals_.Add(var, zone());
518
  return var;
519
}
520

    
521

    
522
Variable* Scope::NewTemporary(Handle<String> name) {
523
  ASSERT(!already_resolved());
524
  Variable* var = new(zone()) Variable(this,
525
                                       name,
526
                                       TEMPORARY,
527
                                       true,
528
                                       Variable::NORMAL,
529
                                       kCreatedInitialized);
530
  temps_.Add(var, zone());
531
  return var;
532
}
533

    
534

    
535
void Scope::AddDeclaration(Declaration* declaration) {
536
  decls_.Add(declaration, zone());
537
}
538

    
539

    
540
void Scope::SetIllegalRedeclaration(Expression* expression) {
541
  // Record only the first illegal redeclaration.
542
  if (!HasIllegalRedeclaration()) {
543
    illegal_redecl_ = expression;
544
  }
545
  ASSERT(HasIllegalRedeclaration());
546
}
547

    
548

    
549
void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
550
  ASSERT(HasIllegalRedeclaration());
551
  illegal_redecl_->Accept(visitor);
552
}
553

    
554

    
555
Declaration* Scope::CheckConflictingVarDeclarations() {
556
  int length = decls_.length();
557
  for (int i = 0; i < length; i++) {
558
    Declaration* decl = decls_[i];
559
    if (decl->mode() != VAR) continue;
560
    Handle<String> name = decl->proxy()->name();
561

    
562
    // Iterate through all scopes until and including the declaration scope.
563
    Scope* previous = NULL;
564
    Scope* current = decl->scope();
565
    do {
566
      // There is a conflict if there exists a non-VAR binding.
567
      Variable* other_var = current->variables_.Lookup(name);
568
      if (other_var != NULL && other_var->mode() != VAR) {
569
        return decl;
570
      }
571
      previous = current;
572
      current = current->outer_scope_;
573
    } while (!previous->is_declaration_scope());
574
  }
575
  return NULL;
576
}
577

    
578

    
579
class VarAndOrder {
580
 public:
581
  VarAndOrder(Variable* var, int order) : var_(var), order_(order) { }
582
  Variable* var() const { return var_; }
583
  int order() const { return order_; }
584
  static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
585
    return a->order_ - b->order_;
586
  }
587

    
588
 private:
589
  Variable* var_;
590
  int order_;
591
};
592

    
593

    
594
void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
595
                                         ZoneList<Variable*>* context_locals) {
596
  ASSERT(stack_locals != NULL);
597
  ASSERT(context_locals != NULL);
598

    
599
  // Collect internals which are always allocated on the heap.
600
  for (int i = 0; i < internals_.length(); i++) {
601
    Variable* var = internals_[i];
602
    if (var->is_used()) {
603
      ASSERT(var->IsContextSlot());
604
      context_locals->Add(var, zone());
605
    }
606
  }
607

    
608
  // Collect temporaries which are always allocated on the stack, unless the
609
  // context as a whole has forced context allocation.
610
  for (int i = 0; i < temps_.length(); i++) {
611
    Variable* var = temps_[i];
612
    if (var->is_used()) {
613
      if (var->IsContextSlot()) {
614
        ASSERT(has_forced_context_allocation());
615
        context_locals->Add(var, zone());
616
      } else {
617
        ASSERT(var->IsStackLocal());
618
        stack_locals->Add(var, zone());
619
      }
620
    }
621
  }
622

    
623
  // Collect declared local variables.
624
  ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
625
  for (VariableMap::Entry* p = variables_.Start();
626
       p != NULL;
627
       p = variables_.Next(p)) {
628
    Variable* var = reinterpret_cast<Variable*>(p->value);
629
    if (var->is_used()) {
630
      vars.Add(VarAndOrder(var, p->order), zone());
631
    }
632
  }
633
  vars.Sort(VarAndOrder::Compare);
634
  int var_count = vars.length();
635
  for (int i = 0; i < var_count; i++) {
636
    Variable* var = vars[i].var();
637
    if (var->IsStackLocal()) {
638
      stack_locals->Add(var, zone());
639
    } else if (var->IsContextSlot()) {
640
      context_locals->Add(var, zone());
641
    }
642
  }
643
}
644

    
645

    
646
bool Scope::AllocateVariables(CompilationInfo* info,
647
                              AstNodeFactory<AstNullVisitor>* factory) {
648
  // 1) Propagate scope information.
649
  bool outer_scope_calls_non_strict_eval = false;
650
  if (outer_scope_ != NULL) {
651
    outer_scope_calls_non_strict_eval =
652
        outer_scope_->outer_scope_calls_non_strict_eval() |
653
        outer_scope_->calls_non_strict_eval();
654
  }
655
  PropagateScopeInfo(outer_scope_calls_non_strict_eval);
656

    
657
  // 2) Allocate module instances.
658
  if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) {
659
    ASSERT(num_modules_ == 0);
660
    AllocateModulesRecursively(this);
661
  }
662

    
663
  // 3) Resolve variables.
664
  if (!ResolveVariablesRecursively(info, factory)) return false;
665

    
666
  // 4) Allocate variables.
667
  AllocateVariablesRecursively();
668

    
669
  return true;
670
}
671

    
672

    
673
bool Scope::HasTrivialContext() const {
674
  // A function scope has a trivial context if it always is the global
675
  // context. We iteratively scan out the context chain to see if
676
  // there is anything that makes this scope non-trivial; otherwise we
677
  // return true.
678
  for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
679
    if (scope->is_eval_scope()) return false;
680
    if (scope->scope_inside_with_) return false;
681
    if (scope->num_heap_slots_ > 0) return false;
682
  }
683
  return true;
684
}
685

    
686

    
687
bool Scope::HasTrivialOuterContext() const {
688
  Scope* outer = outer_scope_;
689
  if (outer == NULL) return true;
690
  // Note that the outer context may be trivial in general, but the current
691
  // scope may be inside a 'with' statement in which case the outer context
692
  // for this scope is not trivial.
693
  return !scope_inside_with_ && outer->HasTrivialContext();
694
}
695

    
696

    
697
bool Scope::HasLazyCompilableOuterContext() const {
698
  Scope* outer = outer_scope_;
699
  if (outer == NULL) return true;
700
  // We have to prevent lazy compilation if this scope is inside a with scope
701
  // and all declaration scopes between them have empty contexts. Such
702
  // declaration scopes may become invisible during scope info deserialization.
703
  outer = outer->DeclarationScope();
704
  bool found_non_trivial_declarations = false;
705
  for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) {
706
    if (scope->is_with_scope() && !found_non_trivial_declarations) return false;
707
    if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) {
708
      found_non_trivial_declarations = true;
709
    }
710
  }
711
  return true;
712
}
713

    
714

    
715
bool Scope::AllowsLazyCompilation() const {
716
  return !force_eager_compilation_ && HasLazyCompilableOuterContext();
717
}
718

    
719

    
720
bool Scope::AllowsLazyCompilationWithoutContext() const {
721
  return !force_eager_compilation_ && HasTrivialOuterContext();
722
}
723

    
724

    
725
int Scope::ContextChainLength(Scope* scope) {
726
  int n = 0;
727
  for (Scope* s = this; s != scope; s = s->outer_scope_) {
728
    ASSERT(s != NULL);  // scope must be in the scope chain
729
    if (s->is_with_scope() || s->num_heap_slots() > 0) n++;
730
    // Catch and module scopes always have heap slots.
731
    ASSERT(!s->is_catch_scope() || s->num_heap_slots() > 0);
732
    ASSERT(!s->is_module_scope() || s->num_heap_slots() > 0);
733
  }
734
  return n;
735
}
736

    
737

    
738
Scope* Scope::GlobalScope() {
739
  Scope* scope = this;
740
  while (!scope->is_global_scope()) {
741
    scope = scope->outer_scope();
742
  }
743
  return scope;
744
}
745

    
746

    
747
Scope* Scope::DeclarationScope() {
748
  Scope* scope = this;
749
  while (!scope->is_declaration_scope()) {
750
    scope = scope->outer_scope();
751
  }
752
  return scope;
753
}
754

    
755

    
756
Handle<ScopeInfo> Scope::GetScopeInfo() {
757
  if (scope_info_.is_null()) {
758
    scope_info_ = ScopeInfo::Create(this, zone());
759
  }
760
  return scope_info_;
761
}
762

    
763

    
764
void Scope::GetNestedScopeChain(
765
    List<Handle<ScopeInfo> >* chain,
766
    int position) {
767
  if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo()));
768

    
769
  for (int i = 0; i < inner_scopes_.length(); i++) {
770
    Scope* scope = inner_scopes_[i];
771
    int beg_pos = scope->start_position();
772
    int end_pos = scope->end_position();
773
    ASSERT(beg_pos >= 0 && end_pos >= 0);
774
    if (beg_pos <= position && position < end_pos) {
775
      scope->GetNestedScopeChain(chain, position);
776
      return;
777
    }
778
  }
779
}
780

    
781

    
782
#ifdef DEBUG
783
static const char* Header(ScopeType scope_type) {
784
  switch (scope_type) {
785
    case EVAL_SCOPE: return "eval";
786
    case FUNCTION_SCOPE: return "function";
787
    case MODULE_SCOPE: return "module";
788
    case GLOBAL_SCOPE: return "global";
789
    case CATCH_SCOPE: return "catch";
790
    case BLOCK_SCOPE: return "block";
791
    case WITH_SCOPE: return "with";
792
  }
793
  UNREACHABLE();
794
  return NULL;
795
}
796

    
797

    
798
static void Indent(int n, const char* str) {
799
  PrintF("%*s%s", n, "", str);
800
}
801

    
802

    
803
static void PrintName(Handle<String> name) {
804
  SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
805
  PrintF("%s", *s);
806
}
807

    
808

    
809
static void PrintLocation(Variable* var) {
810
  switch (var->location()) {
811
    case Variable::UNALLOCATED:
812
      break;
813
    case Variable::PARAMETER:
814
      PrintF("parameter[%d]", var->index());
815
      break;
816
    case Variable::LOCAL:
817
      PrintF("local[%d]", var->index());
818
      break;
819
    case Variable::CONTEXT:
820
      PrintF("context[%d]", var->index());
821
      break;
822
    case Variable::LOOKUP:
823
      PrintF("lookup");
824
      break;
825
  }
826
}
827

    
828

    
829
static void PrintVar(int indent, Variable* var) {
830
  if (var->is_used() || !var->IsUnallocated()) {
831
    Indent(indent, Variable::Mode2String(var->mode()));
832
    PrintF(" ");
833
    PrintName(var->name());
834
    PrintF(";  // ");
835
    PrintLocation(var);
836
    if (var->has_forced_context_allocation()) {
837
      if (!var->IsUnallocated()) PrintF(", ");
838
      PrintF("forced context allocation");
839
    }
840
    PrintF("\n");
841
  }
842
}
843

    
844

    
845
static void PrintMap(int indent, VariableMap* map) {
846
  for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
847
    Variable* var = reinterpret_cast<Variable*>(p->value);
848
    PrintVar(indent, var);
849
  }
850
}
851

    
852

    
853
void Scope::Print(int n) {
854
  int n0 = (n > 0 ? n : 0);
855
  int n1 = n0 + 2;  // indentation
856

    
857
  // Print header.
858
  Indent(n0, Header(scope_type_));
859
  if (scope_name_->length() > 0) {
860
    PrintF(" ");
861
    PrintName(scope_name_);
862
  }
863

    
864
  // Print parameters, if any.
865
  if (is_function_scope()) {
866
    PrintF(" (");
867
    for (int i = 0; i < params_.length(); i++) {
868
      if (i > 0) PrintF(", ");
869
      PrintName(params_[i]->name());
870
    }
871
    PrintF(")");
872
  }
873

    
874
  PrintF(" { // (%d, %d)\n", start_position(), end_position());
875

    
876
  // Function name, if any (named function literals, only).
877
  if (function_ != NULL) {
878
    Indent(n1, "// (local) function name: ");
879
    PrintName(function_->proxy()->name());
880
    PrintF("\n");
881
  }
882

    
883
  // Scope info.
884
  if (HasTrivialOuterContext()) {
885
    Indent(n1, "// scope has trivial outer context\n");
886
  }
887
  switch (language_mode()) {
888
    case CLASSIC_MODE:
889
      break;
890
    case STRICT_MODE:
891
      Indent(n1, "// strict mode scope\n");
892
      break;
893
    case EXTENDED_MODE:
894
      Indent(n1, "// extended mode scope\n");
895
      break;
896
  }
897
  if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
898
  if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
899
  if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
900
  if (outer_scope_calls_non_strict_eval_) {
901
    Indent(n1, "// outer scope calls 'eval' in non-strict context\n");
902
  }
903
  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
904
  if (num_stack_slots_ > 0) { Indent(n1, "// ");
905
  PrintF("%d stack slots\n", num_stack_slots_); }
906
  if (num_heap_slots_ > 0) { Indent(n1, "// ");
907
  PrintF("%d heap slots\n", num_heap_slots_); }
908

    
909
  // Print locals.
910
  if (function_ != NULL) {
911
    Indent(n1, "// function var:\n");
912
    PrintVar(n1, function_->proxy()->var());
913
  }
914

    
915
  if (temps_.length() > 0) {
916
    Indent(n1, "// temporary vars:\n");
917
    for (int i = 0; i < temps_.length(); i++) {
918
      PrintVar(n1, temps_[i]);
919
    }
920
  }
921

    
922
  if (internals_.length() > 0) {
923
    Indent(n1, "// internal vars:\n");
924
    for (int i = 0; i < internals_.length(); i++) {
925
      PrintVar(n1, internals_[i]);
926
    }
927
  }
928

    
929
  if (variables_.Start() != NULL) {
930
    Indent(n1, "// local vars:\n");
931
    PrintMap(n1, &variables_);
932
  }
933

    
934
  if (dynamics_ != NULL) {
935
    Indent(n1, "// dynamic vars:\n");
936
    PrintMap(n1, dynamics_->GetMap(DYNAMIC));
937
    PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
938
    PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
939
  }
940

    
941
  // Print inner scopes (disable by providing negative n).
942
  if (n >= 0) {
943
    for (int i = 0; i < inner_scopes_.length(); i++) {
944
      PrintF("\n");
945
      inner_scopes_[i]->Print(n1);
946
    }
947
  }
948

    
949
  Indent(n0, "}\n");
950
}
951
#endif  // DEBUG
952

    
953

    
954
Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
955
  if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone());
956
  VariableMap* map = dynamics_->GetMap(mode);
957
  Variable* var = map->Lookup(name);
958
  if (var == NULL) {
959
    // Declare a new non-local.
960
    InitializationFlag init_flag = (mode == VAR)
961
        ? kCreatedInitialized : kNeedsInitialization;
962
    var = map->Declare(NULL,
963
                       name,
964
                       mode,
965
                       true,
966
                       Variable::NORMAL,
967
                       init_flag);
968
    // Allocate it by giving it a dynamic lookup.
969
    var->AllocateTo(Variable::LOOKUP, -1);
970
  }
971
  return var;
972
}
973

    
974

    
975
Variable* Scope::LookupRecursive(Handle<String> name,
976
                                 BindingKind* binding_kind,
977
                                 AstNodeFactory<AstNullVisitor>* factory) {
978
  ASSERT(binding_kind != NULL);
979
  if (already_resolved() && is_with_scope()) {
980
    // Short-cut: if the scope is deserialized from a scope info, variable
981
    // allocation is already fixed.  We can simply return with dynamic lookup.
982
    *binding_kind = DYNAMIC_LOOKUP;
983
    return NULL;
984
  }
985

    
986
  // Try to find the variable in this scope.
987
  Variable* var = LocalLookup(name);
988

    
989
  // We found a variable and we are done. (Even if there is an 'eval' in
990
  // this scope which introduces the same variable again, the resulting
991
  // variable remains the same.)
992
  if (var != NULL) {
993
    *binding_kind = BOUND;
994
    return var;
995
  }
996

    
997
  // We did not find a variable locally. Check against the function variable,
998
  // if any. We can do this for all scopes, since the function variable is
999
  // only present - if at all - for function scopes.
1000
  *binding_kind = UNBOUND;
1001
  var = LookupFunctionVar(name, factory);
1002
  if (var != NULL) {
1003
    *binding_kind = BOUND;
1004
  } else if (outer_scope_ != NULL) {
1005
    var = outer_scope_->LookupRecursive(name, binding_kind, factory);
1006
    if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
1007
      var->ForceContextAllocation();
1008
    }
1009
  } else {
1010
    ASSERT(is_global_scope());
1011
  }
1012

    
1013
  if (is_with_scope()) {
1014
    ASSERT(!already_resolved());
1015
    // The current scope is a with scope, so the variable binding can not be
1016
    // statically resolved. However, note that it was necessary to do a lookup
1017
    // in the outer scope anyway, because if a binding exists in an outer scope,
1018
    // the associated variable has to be marked as potentially being accessed
1019
    // from inside of an inner with scope (the property may not be in the 'with'
1020
    // object).
1021
    *binding_kind = DYNAMIC_LOOKUP;
1022
    return NULL;
1023
  } else if (calls_non_strict_eval()) {
1024
    // A variable binding may have been found in an outer scope, but the current
1025
    // scope makes a non-strict 'eval' call, so the found variable may not be
1026
    // the correct one (the 'eval' may introduce a binding with the same name).
1027
    // In that case, change the lookup result to reflect this situation.
1028
    if (*binding_kind == BOUND) {
1029
      *binding_kind = BOUND_EVAL_SHADOWED;
1030
    } else if (*binding_kind == UNBOUND) {
1031
      *binding_kind = UNBOUND_EVAL_SHADOWED;
1032
    }
1033
  }
1034
  return var;
1035
}
1036

    
1037

    
1038
bool Scope::ResolveVariable(CompilationInfo* info,
1039
                            VariableProxy* proxy,
1040
                            AstNodeFactory<AstNullVisitor>* factory) {
1041
  ASSERT(info->global_scope()->is_global_scope());
1042

    
1043
  // If the proxy is already resolved there's nothing to do
1044
  // (functions and consts may be resolved by the parser).
1045
  if (proxy->var() != NULL) return true;
1046

    
1047
  // Otherwise, try to resolve the variable.
1048
  BindingKind binding_kind;
1049
  Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
1050
  switch (binding_kind) {
1051
    case BOUND:
1052
      // We found a variable binding.
1053
      break;
1054

    
1055
    case BOUND_EVAL_SHADOWED:
1056
      // We either found a variable binding that might be shadowed by eval  or
1057
      // gave up on it (e.g. by encountering a local with the same in the outer
1058
      // scope which was not promoted to a context, this can happen if we use
1059
      // debugger to evaluate arbitrary expressions at a break point).
1060
      if (var->IsGlobalObjectProperty()) {
1061
        var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
1062
      } else if (var->is_dynamic()) {
1063
        var = NonLocal(proxy->name(), DYNAMIC);
1064
      } else {
1065
        Variable* invalidated = var;
1066
        var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
1067
        var->set_local_if_not_shadowed(invalidated);
1068
      }
1069
      break;
1070

    
1071
    case UNBOUND:
1072
      // No binding has been found. Declare a variable on the global object.
1073
      var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
1074
      break;
1075

    
1076
    case UNBOUND_EVAL_SHADOWED:
1077
      // No binding has been found. But some scope makes a
1078
      // non-strict 'eval' call.
1079
      var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
1080
      break;
1081

    
1082
    case DYNAMIC_LOOKUP:
1083
      // The variable could not be resolved statically.
1084
      var = NonLocal(proxy->name(), DYNAMIC);
1085
      break;
1086
  }
1087

    
1088
  ASSERT(var != NULL);
1089

    
1090
  if (FLAG_harmony_scoping && is_extended_mode() &&
1091
      var->is_const_mode() && proxy->IsLValue()) {
1092
    // Assignment to const. Throw a syntax error.
1093
    MessageLocation location(
1094
        info->script(), proxy->position(), proxy->position());
1095
    Isolate* isolate = info->isolate();
1096
    Factory* factory = isolate->factory();
1097
    Handle<JSArray> array = factory->NewJSArray(0);
1098
    Handle<Object> result =
1099
        factory->NewSyntaxError("harmony_const_assign", array);
1100
    isolate->Throw(*result, &location);
1101
    return false;
1102
  }
1103

    
1104
  if (FLAG_harmony_modules) {
1105
    bool ok;
1106
#ifdef DEBUG
1107
    if (FLAG_print_interface_details)
1108
      PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
1109
#endif
1110
    proxy->interface()->Unify(var->interface(), zone(), &ok);
1111
    if (!ok) {
1112
#ifdef DEBUG
1113
      if (FLAG_print_interfaces) {
1114
        PrintF("SCOPES TYPE ERROR\n");
1115
        PrintF("proxy: ");
1116
        proxy->interface()->Print();
1117
        PrintF("var: ");
1118
        var->interface()->Print();
1119
      }
1120
#endif
1121

    
1122
      // Inconsistent use of module. Throw a syntax error.
1123
      // TODO(rossberg): generate more helpful error message.
1124
      MessageLocation location(
1125
          info->script(), proxy->position(), proxy->position());
1126
      Isolate* isolate = info->isolate();
1127
      Factory* factory = isolate->factory();
1128
      Handle<JSArray> array = factory->NewJSArray(1);
1129
      USE(JSObject::SetElement(array, 0, var->name(), NONE, kStrictMode));
1130
      Handle<Object> result =
1131
          factory->NewSyntaxError("module_type_error", array);
1132
      isolate->Throw(*result, &location);
1133
      return false;
1134
    }
1135
  }
1136

    
1137
  proxy->BindTo(var);
1138

    
1139
  return true;
1140
}
1141

    
1142

    
1143
bool Scope::ResolveVariablesRecursively(
1144
    CompilationInfo* info,
1145
    AstNodeFactory<AstNullVisitor>* factory) {
1146
  ASSERT(info->global_scope()->is_global_scope());
1147

    
1148
  // Resolve unresolved variables for this scope.
1149
  for (int i = 0; i < unresolved_.length(); i++) {
1150
    if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1151
  }
1152

    
1153
  // Resolve unresolved variables for inner scopes.
1154
  for (int i = 0; i < inner_scopes_.length(); i++) {
1155
    if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
1156
      return false;
1157
  }
1158

    
1159
  return true;
1160
}
1161

    
1162

    
1163
bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) {
1164
  if (outer_scope_calls_non_strict_eval) {
1165
    outer_scope_calls_non_strict_eval_ = true;
1166
  }
1167

    
1168
  bool calls_non_strict_eval =
1169
      this->calls_non_strict_eval() || outer_scope_calls_non_strict_eval_;
1170
  for (int i = 0; i < inner_scopes_.length(); i++) {
1171
    Scope* inner_scope = inner_scopes_[i];
1172
    if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) {
1173
      inner_scope_calls_eval_ = true;
1174
    }
1175
    if (inner_scope->force_eager_compilation_) {
1176
      force_eager_compilation_ = true;
1177
    }
1178
  }
1179

    
1180
  return scope_calls_eval_ || inner_scope_calls_eval_;
1181
}
1182

    
1183

    
1184
bool Scope::MustAllocate(Variable* var) {
1185
  // Give var a read/write use if there is a chance it might be accessed
1186
  // via an eval() call.  This is only possible if the variable has a
1187
  // visible name.
1188
  if ((var->is_this() || var->name()->length() > 0) &&
1189
      (var->has_forced_context_allocation() ||
1190
       scope_calls_eval_ ||
1191
       inner_scope_calls_eval_ ||
1192
       scope_contains_with_ ||
1193
       is_catch_scope() ||
1194
       is_block_scope() ||
1195
       is_module_scope() ||
1196
       is_global_scope())) {
1197
    var->set_is_used(true);
1198
  }
1199
  // Global variables do not need to be allocated.
1200
  return !var->IsGlobalObjectProperty() && var->is_used();
1201
}
1202

    
1203

    
1204
bool Scope::MustAllocateInContext(Variable* var) {
1205
  // If var is accessed from an inner scope, or if there is a possibility
1206
  // that it might be accessed from the current or an inner scope (through
1207
  // an eval() call or a runtime with lookup), it must be allocated in the
1208
  // context.
1209
  //
1210
  // Exceptions: If the scope as a whole has forced context allocation, all
1211
  // variables will have context allocation, even temporaries.  Otherwise
1212
  // temporary variables are always stack-allocated.  Catch-bound variables are
1213
  // always context-allocated.
1214
  if (has_forced_context_allocation()) return true;
1215
  if (var->mode() == TEMPORARY) return false;
1216
  if (var->mode() == INTERNAL) return true;
1217
  if (is_catch_scope() || is_block_scope() || is_module_scope()) return true;
1218
  if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true;
1219
  return var->has_forced_context_allocation() ||
1220
      scope_calls_eval_ ||
1221
      inner_scope_calls_eval_ ||
1222
      scope_contains_with_;
1223
}
1224

    
1225

    
1226
bool Scope::HasArgumentsParameter() {
1227
  for (int i = 0; i < params_.length(); i++) {
1228
    if (params_[i]->name().is_identical_to(
1229
            isolate_->factory()->arguments_string())) {
1230
      return true;
1231
    }
1232
  }
1233
  return false;
1234
}
1235

    
1236

    
1237
void Scope::AllocateStackSlot(Variable* var) {
1238
  var->AllocateTo(Variable::LOCAL, num_stack_slots_++);
1239
}
1240

    
1241

    
1242
void Scope::AllocateHeapSlot(Variable* var) {
1243
  var->AllocateTo(Variable::CONTEXT, num_heap_slots_++);
1244
}
1245

    
1246

    
1247
void Scope::AllocateParameterLocals() {
1248
  ASSERT(is_function_scope());
1249
  Variable* arguments = LocalLookup(isolate_->factory()->arguments_string());
1250
  ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
1251

    
1252
  bool uses_nonstrict_arguments = false;
1253

    
1254
  if (MustAllocate(arguments) && !HasArgumentsParameter()) {
1255
    // 'arguments' is used. Unless there is also a parameter called
1256
    // 'arguments', we must be conservative and allocate all parameters to
1257
    // the context assuming they will be captured by the arguments object.
1258
    // If we have a parameter named 'arguments', a (new) value is always
1259
    // assigned to it via the function invocation. Then 'arguments' denotes
1260
    // that specific parameter value and cannot be used to access the
1261
    // parameters, which is why we don't need to allocate an arguments
1262
    // object in that case.
1263

    
1264
    // We are using 'arguments'. Tell the code generator that is needs to
1265
    // allocate the arguments object by setting 'arguments_'.
1266
    arguments_ = arguments;
1267

    
1268
    // In strict mode 'arguments' does not alias formal parameters.
1269
    // Therefore in strict mode we allocate parameters as if 'arguments'
1270
    // were not used.
1271
    uses_nonstrict_arguments = is_classic_mode();
1272
  }
1273

    
1274
  // The same parameter may occur multiple times in the parameters_ list.
1275
  // If it does, and if it is not copied into the context object, it must
1276
  // receive the highest parameter index for that parameter; thus iteration
1277
  // order is relevant!
1278
  for (int i = params_.length() - 1; i >= 0; --i) {
1279
    Variable* var = params_[i];
1280
    ASSERT(var->scope() == this);
1281
    if (uses_nonstrict_arguments) {
1282
      // Force context allocation of the parameter.
1283
      var->ForceContextAllocation();
1284
    }
1285

    
1286
    if (MustAllocate(var)) {
1287
      if (MustAllocateInContext(var)) {
1288
        ASSERT(var->IsUnallocated() || var->IsContextSlot());
1289
        if (var->IsUnallocated()) {
1290
          AllocateHeapSlot(var);
1291
        }
1292
      } else {
1293
        ASSERT(var->IsUnallocated() || var->IsParameter());
1294
        if (var->IsUnallocated()) {
1295
          var->AllocateTo(Variable::PARAMETER, i);
1296
        }
1297
      }
1298
    }
1299
  }
1300
}
1301

    
1302

    
1303
void Scope::AllocateNonParameterLocal(Variable* var) {
1304
  ASSERT(var->scope() == this);
1305
  ASSERT(!var->IsVariable(isolate_->factory()->result_string()) ||
1306
         !var->IsStackLocal());
1307
  if (var->IsUnallocated() && MustAllocate(var)) {
1308
    if (MustAllocateInContext(var)) {
1309
      AllocateHeapSlot(var);
1310
    } else {
1311
      AllocateStackSlot(var);
1312
    }
1313
  }
1314
}
1315

    
1316

    
1317
void Scope::AllocateNonParameterLocals() {
1318
  // All variables that have no rewrite yet are non-parameter locals.
1319
  for (int i = 0; i < temps_.length(); i++) {
1320
    AllocateNonParameterLocal(temps_[i]);
1321
  }
1322

    
1323
  for (int i = 0; i < internals_.length(); i++) {
1324
    AllocateNonParameterLocal(internals_[i]);
1325
  }
1326

    
1327
  ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
1328
  for (VariableMap::Entry* p = variables_.Start();
1329
       p != NULL;
1330
       p = variables_.Next(p)) {
1331
    Variable* var = reinterpret_cast<Variable*>(p->value);
1332
    vars.Add(VarAndOrder(var, p->order), zone());
1333
  }
1334
  vars.Sort(VarAndOrder::Compare);
1335
  int var_count = vars.length();
1336
  for (int i = 0; i < var_count; i++) {
1337
    AllocateNonParameterLocal(vars[i].var());
1338
  }
1339

    
1340
  // For now, function_ must be allocated at the very end.  If it gets
1341
  // allocated in the context, it must be the last slot in the context,
1342
  // because of the current ScopeInfo implementation (see
1343
  // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1344
  if (function_ != NULL) {
1345
    AllocateNonParameterLocal(function_->proxy()->var());
1346
  }
1347
}
1348

    
1349

    
1350
void Scope::AllocateVariablesRecursively() {
1351
  // Allocate variables for inner scopes.
1352
  for (int i = 0; i < inner_scopes_.length(); i++) {
1353
    inner_scopes_[i]->AllocateVariablesRecursively();
1354
  }
1355

    
1356
  // If scope is already resolved, we still need to allocate
1357
  // variables in inner scopes which might not had been resolved yet.
1358
  if (already_resolved()) return;
1359
  // The number of slots required for variables.
1360
  num_stack_slots_ = 0;
1361
  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1362

    
1363
  // Allocate variables for this scope.
1364
  // Parameters must be allocated first, if any.
1365
  if (is_function_scope()) AllocateParameterLocals();
1366
  AllocateNonParameterLocals();
1367

    
1368
  // Force allocation of a context for this scope if necessary. For a 'with'
1369
  // scope and for a function scope that makes an 'eval' call we need a context,
1370
  // even if no local variables were statically allocated in the scope.
1371
  // Likewise for modules.
1372
  bool must_have_context = is_with_scope() || is_module_scope() ||
1373
      (is_function_scope() && calls_eval());
1374

    
1375
  // If we didn't allocate any locals in the local context, then we only
1376
  // need the minimal number of slots if we must have a context.
1377
  if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
1378
    num_heap_slots_ = 0;
1379
  }
1380

    
1381
  // Allocation done.
1382
  ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1383
}
1384

    
1385

    
1386
void Scope::AllocateModulesRecursively(Scope* host_scope) {
1387
  if (already_resolved()) return;
1388
  if (is_module_scope()) {
1389
    ASSERT(interface_->IsFrozen());
1390
    Handle<String> name = isolate_->factory()->InternalizeOneByteString(
1391
        STATIC_ASCII_VECTOR(".module"));
1392
    ASSERT(module_var_ == NULL);
1393
    module_var_ = host_scope->NewInternal(name);
1394
    ++host_scope->num_modules_;
1395
  }
1396

    
1397
  for (int i = 0; i < inner_scopes_.length(); i++) {
1398
    Scope* inner_scope = inner_scopes_.at(i);
1399
    inner_scope->AllocateModulesRecursively(host_scope);
1400
  }
1401
}
1402

    
1403

    
1404
int Scope::StackLocalCount() const {
1405
  return num_stack_slots() -
1406
      (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1407
}
1408

    
1409

    
1410
int Scope::ContextLocalCount() const {
1411
  if (num_heap_slots() == 0) return 0;
1412
  return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1413
      (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1414
}
1415

    
1416
} }  // namespace v8::internal