scopeinfo.cc 28.7 KB
Newer Older
1
// Copyright 2011 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include "src/scopeinfo.h"
6

7
#include <stdlib.h>
8

9
#include "src/bootstrapper.h"
10
#include "src/scopes.h"
11

12 13
namespace v8 {
namespace internal {
14 15


16 17
Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
                                    Scope* scope) {
18
  // Collect stack and context locals.
19 20
  ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
  ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
21
  ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
22 23 24
  ZoneList<Variable*> strong_mode_free_variables(0, zone);

  scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
25
                                      &context_globals,
26
                                      &strong_mode_free_variables);
27 28
  const int stack_local_count = stack_locals.length();
  const int context_local_count = context_locals.length();
29
  const int context_global_count = context_globals.length();
30 31
  const int strong_mode_free_variable_count =
      strong_mode_free_variables.length();
32
  // Make sure we allocate the correct amount.
33 34
  DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
  DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
35

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  // Determine use and location of the "this" binding if it is present.
  VariableAllocationInfo receiver_info;
  if (scope->has_this_declaration()) {
    Variable* var = scope->receiver();
    if (!var->is_used()) {
      receiver_info = UNUSED;
    } else if (var->IsContextSlot()) {
      receiver_info = CONTEXT;
    } else {
      DCHECK(var->IsParameter());
      receiver_info = STACK;
    }
  } else {
    receiver_info = NONE;
  }

52
  // Determine use and location of the function variable if it is present.
53
  VariableAllocationInfo function_name_info;
54 55
  VariableMode function_variable_mode;
  if (scope->is_function_scope() && scope->function() != NULL) {
56
    Variable* var = scope->function()->proxy()->var();
57 58 59 60 61
    if (!var->is_used()) {
      function_name_info = UNUSED;
    } else if (var->IsContextSlot()) {
      function_name_info = CONTEXT;
    } else {
62
      DCHECK(var->IsStackLocal());
63
      function_name_info = STACK;
64
    }
65
    function_variable_mode = var->mode();
66
  } else {
67 68
    function_name_info = NONE;
    function_variable_mode = VAR;
69
  }
70
  DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE);
71

72
  const bool has_function_name = function_name_info != NONE;
73
  const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
74
  const int parameter_count = scope->num_parameters();
75 76
  const int length = kVariablePartIndex + parameter_count +
                     (1 + stack_local_count) + 2 * context_local_count +
77
                     2 * context_global_count +
78
                     3 * strong_mode_free_variable_count +
79
                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
80

81
  Factory* factory = isolate->factory();
82
  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
83

84 85 86
  bool has_simple_parameters =
      scope->is_function_scope() && scope->has_simple_parameters();

87
  // Encode the flags.
88
  int flags = ScopeTypeField::encode(scope->scope_type()) |
89
              CallsEvalField::encode(scope->calls_eval()) |
90
              LanguageModeField::encode(scope->language_mode()) |
91
              DeclarationScopeField::encode(scope->is_declaration_scope()) |
92
              ReceiverVariableField::encode(receiver_info) |
93 94 95
              FunctionVariableField::encode(function_name_info) |
              FunctionVariableMode::encode(function_variable_mode) |
              AsmModuleField::encode(scope->asm_module()) |
96
              AsmFunctionField::encode(scope->asm_function()) |
97
              HasSimpleParametersField::encode(has_simple_parameters) |
98
              FunctionKindField::encode(scope->function_kind());
99 100 101 102
  scope_info->SetFlags(flags);
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetStackLocalCount(stack_local_count);
  scope_info->SetContextLocalCount(context_local_count);
103
  scope_info->SetContextGlobalCount(context_global_count);
104
  scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
105 106 107

  int index = kVariablePartIndex;
  // Add parameters.
108
  DCHECK(index == scope_info->ParameterEntriesIndex());
109 110
  for (int i = 0; i < parameter_count; ++i) {
    scope_info->set(index++, *scope->parameter(i)->name());
111 112
  }

113 114 115
  // Add stack locals' names. We are assuming that the stack locals'
  // slots are allocated in increasing order, so we can simply add
  // them to the ScopeInfo object.
116 117 118 119 120 121 122 123
  int first_slot_index;
  if (stack_local_count > 0) {
    first_slot_index = stack_locals[0]->index();
  } else {
    first_slot_index = 0;
  }
  DCHECK(index == scope_info->StackLocalFirstSlotIndex());
  scope_info->set(index++, Smi::FromInt(first_slot_index));
124
  DCHECK(index == scope_info->StackLocalEntriesIndex());
125
  for (int i = 0; i < stack_local_count; ++i) {
126
    DCHECK(stack_locals[i]->index() == first_slot_index + i);
127 128
    scope_info->set(index++, *stack_locals[i]->name());
  }
129

130 131 132 133 134 135
  // Due to usage analysis, context-allocated locals are not necessarily in
  // increasing order: Some of them may be parameters which are allocated before
  // the non-parameter locals. When the non-parameter locals are sorted
  // according to usage, the allocated slot indices may not be in increasing
  // order with the variable list anymore. Thus, we first need to sort them by
  // context slot index before adding them to the ScopeInfo object.
136
  context_locals.Sort(&Variable::CompareIndex);
137 138

  // Add context locals' names.
139
  DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
140 141 142
  for (int i = 0; i < context_local_count; ++i) {
    scope_info->set(index++, *context_locals[i]->name());
  }
143

144 145 146 147 148 149
  // Add context globals' names.
  DCHECK(index == scope_info->ContextGlobalNameEntriesIndex());
  for (int i = 0; i < context_global_count; ++i) {
    scope_info->set(index++, *context_globals[i]->name());
  }

150
  // Add context locals' info.
151
  DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
152
  for (int i = 0; i < context_local_count; ++i) {
153
    Variable* var = context_locals[i];
154 155 156 157
    uint32_t value =
        ContextLocalMode::encode(var->mode()) |
        ContextLocalInitFlag::encode(var->initialization_flag()) |
        ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
158
    scope_info->set(index++, Smi::FromInt(value));
159
  }
160

161 162 163 164 165 166 167 168 169 170 171 172
  // Add context globals' info.
  DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
  for (int i = 0; i < context_global_count; ++i) {
    Variable* var = context_globals[i];
    // TODO(ishell): do we need this kind of info for globals here?
    uint32_t value =
        ContextLocalMode::encode(var->mode()) |
        ContextLocalInitFlag::encode(var->initialization_flag()) |
        ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
    scope_info->set(index++, Smi::FromInt(value));
  }

173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
  for (int i = 0; i < strong_mode_free_variable_count; ++i) {
    scope_info->set(index++, *strong_mode_free_variables[i]->name());
  }

  DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
  for (int i = 0; i < strong_mode_free_variable_count; ++i) {
    // Unfortunately, the source code positions are stored as int even though
    // int32_t would be enough (given the maximum source code length).
    Handle<Object> start_position = factory->NewNumberFromInt(
        static_cast<int32_t>(strong_mode_free_variables[i]
                                 ->strong_mode_reference_start_position()));
    scope_info->set(index++, *start_position);
    Handle<Object> end_position = factory->NewNumberFromInt(
        static_cast<int32_t>(strong_mode_free_variables[i]
                                 ->strong_mode_reference_end_position()));
    scope_info->set(index++, *end_position);
  }

192 193 194 195 196 197 198 199 200
  // If the receiver is allocated, add its index.
  DCHECK(index == scope_info->ReceiverEntryIndex());
  if (has_receiver) {
    int var_index = scope->receiver()->index();
    scope_info->set(index++, Smi::FromInt(var_index));
    // ?? DCHECK(receiver_info != CONTEXT || var_index ==
    // scope_info->ContextLength() - 1);
  }

201
  // If present, add the function variable name and its index.
202
  DCHECK(index == scope_info->FunctionNameEntryIndex());
203
  if (has_function_name) {
204 205
    int var_index = scope->function()->proxy()->var()->index();
    scope_info->set(index++, *scope->function()->proxy()->name());
206
    scope_info->set(index++, Smi::FromInt(var_index));
207
    DCHECK(function_name_info != CONTEXT ||
208 209
           var_index == scope_info->ContextLength() - 1);
  }
210

211 212 213
  DCHECK(index == scope_info->length());
  DCHECK(scope->num_parameters() == scope_info->ParameterCount());
  DCHECK(scope->num_heap_slots() == scope_info->ContextLength() ||
214 215
         (scope->num_heap_slots() == kVariablePartIndex &&
          scope_info->ContextLength() == 0));
216
  return scope_info;
217 218 219
}


220 221 222 223 224
Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
  DCHECK(isolate->bootstrapper()->IsActive());

  const int stack_local_count = 0;
  const int context_local_count = 1;
225
  const int context_global_count = 0;
226
  const int strong_mode_free_variable_count = 0;
227
  const bool has_simple_parameters = true;
228 229 230 231 232 233 234 235
  const VariableAllocationInfo receiver_info = CONTEXT;
  const VariableAllocationInfo function_name_info = NONE;
  const VariableMode function_variable_mode = VAR;
  const bool has_function_name = false;
  const bool has_receiver = true;
  const int parameter_count = 0;
  const int length = kVariablePartIndex + parameter_count +
                     (1 + stack_local_count) + 2 * context_local_count +
236
                     2 * context_global_count +
237 238 239 240 241 242 243 244 245 246
                     3 * strong_mode_free_variable_count +
                     (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);

  Factory* factory = isolate->factory();
  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);

  // Encode the flags.
  int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
              CallsEvalField::encode(false) |
              LanguageModeField::encode(SLOPPY) |
247
              DeclarationScopeField::encode(true) |
248 249 250 251
              ReceiverVariableField::encode(receiver_info) |
              FunctionVariableField::encode(function_name_info) |
              FunctionVariableMode::encode(function_variable_mode) |
              AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
252
              HasSimpleParametersField::encode(has_simple_parameters) |
253 254 255 256 257
              FunctionKindField::encode(FunctionKind::kNormalFunction);
  scope_info->SetFlags(flags);
  scope_info->SetParameterCount(parameter_count);
  scope_info->SetStackLocalCount(stack_local_count);
  scope_info->SetContextLocalCount(context_local_count);
258
  scope_info->SetContextGlobalCount(context_global_count);
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);

  int index = kVariablePartIndex;
  const int first_slot_index = 0;
  DCHECK(index == scope_info->StackLocalFirstSlotIndex());
  scope_info->set(index++, Smi::FromInt(first_slot_index));
  DCHECK(index == scope_info->StackLocalEntriesIndex());

  // Here we add info for context-allocated "this".
  DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
  scope_info->set(index++, *isolate->factory()->this_string());
  DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
  const uint32_t value = ContextLocalMode::encode(CONST) |
                         ContextLocalInitFlag::encode(kCreatedInitialized) |
                         ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
  scope_info->set(index++, Smi::FromInt(value));

  DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
  DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());

  // And here we record that this scopeinfo binds a receiver.
  DCHECK(index == scope_info->ReceiverEntryIndex());
  const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
  scope_info->set(index++, Smi::FromInt(receiver_index));

  DCHECK(index == scope_info->FunctionNameEntryIndex());

  DCHECK_EQ(index, scope_info->length());
  DCHECK_EQ(scope_info->ParameterCount(), 0);
  DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);

  return scope_info;
}


294 295
ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
  return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
296 297 298
}


299
ScopeType ScopeInfo::scope_type() {
300
  DCHECK(length() > 0);
301
  return ScopeTypeField::decode(Flags());
302 303 304
}


305 306
bool ScopeInfo::CallsEval() {
  return length() > 0 && CallsEvalField::decode(Flags());
307 308 309
}


310 311
LanguageMode ScopeInfo::language_mode() {
  return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
312 313 314
}


315 316 317 318 319
bool ScopeInfo::is_declaration_scope() {
  return DeclarationScopeField::decode(Flags());
}


320 321
int ScopeInfo::LocalCount() {
  return StackLocalCount() + ContextLocalCount();
322 323 324
}


325 326 327 328 329 330 331
int ScopeInfo::StackSlotCount() {
  if (length() > 0) {
    bool function_name_stack_slot =
        FunctionVariableField::decode(Flags()) == STACK;
    return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
  }
  return 0;
332 333 334
}


335 336 337
int ScopeInfo::ContextLength() {
  if (length() > 0) {
    int context_locals = ContextLocalCount();
338
    int context_globals = ContextGlobalCount();
339 340
    bool function_name_context_slot =
        FunctionVariableField::decode(Flags()) == CONTEXT;
341 342
    bool has_context = context_locals > 0 || context_globals > 0 ||
                       function_name_context_slot ||
343
                       scope_type() == WITH_SCOPE ||
344 345
                       (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
                           is_declaration_scope()) ||
346 347
                       (scope_type() == ARROW_SCOPE && CallsSloppyEval()) ||
                       (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
348
                       scope_type() == MODULE_SCOPE;
349

350
    if (has_context) {
351
      return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals +
352
             (function_name_context_slot ? 1 : 0);
353
    }
354
  }
355
  return 0;
356 357 358
}


359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
bool ScopeInfo::HasReceiver() {
  if (length() > 0) {
    return NONE != ReceiverVariableField::decode(Flags());
  } else {
    return false;
  }
}


bool ScopeInfo::HasAllocatedReceiver() {
  if (length() > 0) {
    VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
    return allocation == STACK || allocation == CONTEXT;
  } else {
    return false;
  }
}


378 379 380
bool ScopeInfo::HasFunctionName() {
  if (length() > 0) {
    return NONE != FunctionVariableField::decode(Flags());
381
  } else {
382
    return false;
383
  }
384 385 386
}


387 388 389 390 391
bool ScopeInfo::HasHeapAllocatedLocals() {
  if (length() > 0) {
    return ContextLocalCount() > 0;
  } else {
    return false;
392 393 394 395
  }
}


396
bool ScopeInfo::HasContext() {
397
  return ContextLength() > 0;
398 399 400
}


401
String* ScopeInfo::FunctionName() {
402
  DCHECK(HasFunctionName());
403
  return String::cast(get(FunctionNameEntryIndex()));
404 405 406
}


407
String* ScopeInfo::ParameterName(int var) {
408
  DCHECK(0 <= var && var < ParameterCount());
409 410
  int info_index = ParameterEntriesIndex() + var;
  return String::cast(get(info_index));
411 412 413
}


414
String* ScopeInfo::LocalName(int var) {
415 416
  DCHECK(0 <= var && var < LocalCount());
  DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
417 418 419
         ContextLocalNameEntriesIndex());
  int info_index = StackLocalEntriesIndex() + var;
  return String::cast(get(info_index));
420 421 422
}


423
String* ScopeInfo::StackLocalName(int var) {
424
  DCHECK(0 <= var && var < StackLocalCount());
425 426
  int info_index = StackLocalEntriesIndex() + var;
  return String::cast(get(info_index));
427 428 429
}


430 431 432 433 434 435 436
int ScopeInfo::StackLocalIndex(int var) {
  DCHECK(0 <= var && var < StackLocalCount());
  int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
  return first_slot_index + var;
}


437
String* ScopeInfo::ContextLocalName(int var) {
438
  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
439 440
  int info_index = ContextLocalNameEntriesIndex() + var;
  return String::cast(get(info_index));
441 442 443
}


444
VariableMode ScopeInfo::ContextLocalMode(int var) {
445
  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
446 447 448 449 450 451 452
  int info_index = ContextLocalInfoEntriesIndex() + var;
  int value = Smi::cast(get(info_index))->value();
  return ContextLocalMode::decode(value);
}


InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
453
  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
454 455 456
  int info_index = ContextLocalInfoEntriesIndex() + var;
  int value = Smi::cast(get(info_index))->value();
  return ContextLocalInitFlag::decode(value);
457 458 459
}


460
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
461
  DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
462 463 464 465 466 467
  int info_index = ContextLocalInfoEntriesIndex() + var;
  int value = Smi::cast(get(info_index))->value();
  return ContextLocalMaybeAssignedFlag::decode(value);
}


468
bool ScopeInfo::LocalIsSynthetic(int var) {
469
  DCHECK(0 <= var && var < LocalCount());
470 471 472 473 474
  // There's currently no flag stored on the ScopeInfo to indicate that a
  // variable is a compiler-introduced temporary. However, to avoid conflict
  // with user declarations, the current temporaries like .generator_object and
  // .result start with a dot, so we can use that as a flag. It's a hack!
  Handle<String> name(LocalName(var));
475 476
  return (name->length() > 0 && name->Get(0) == '.') ||
         name->Equals(*GetIsolate()->factory()->this_string());
477 478 479
}


480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
String* ScopeInfo::StrongModeFreeVariableName(int var) {
  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
  int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
  return String::cast(get(info_index));
}


int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
  int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
  int32_t value = 0;
  bool ok = get(info_index)->ToInt32(&value);
  USE(ok);
  DCHECK(ok);
  return value;
}


int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
  DCHECK(0 <= var && var < StrongModeFreeVariableCount());
  int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
  int32_t value = 0;
  bool ok = get(info_index)->ToInt32(&value);
  USE(ok);
  DCHECK(ok);
  return value;
}


509
int ScopeInfo::StackSlotIndex(String* name) {
510
  DCHECK(name->IsInternalizedString());
511
  if (length() > 0) {
512
    int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
513 514 515 516
    int start = StackLocalEntriesIndex();
    int end = StackLocalEntriesIndex() + StackLocalCount();
    for (int i = start; i < end; ++i) {
      if (name == get(i)) {
517
        return i - start + first_slot_index;
518
      }
519 520 521 522 523
    }
  }
  return -1;
}

524

525
int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
526
                                Handle<String> name, VariableMode* mode,
527
                                VariableLocation* location,
528 529
                                InitializationFlag* init_flag,
                                MaybeAssignedFlag* maybe_assigned_flag) {
530 531
  DCHECK(name->IsInternalizedString());
  DCHECK(mode != NULL);
532
  DCHECK(location != NULL);
533
  DCHECK(init_flag != NULL);
534 535 536
  if (scope_info->length() > 0) {
    ContextSlotCache* context_slot_cache =
        scope_info->GetIsolate()->context_slot_cache();
537 538
    int result = context_slot_cache->Lookup(*scope_info, *name, mode, location,
                                            init_flag, maybe_assigned_flag);
539
    if (result != ContextSlotCache::kNotFound) {
540
      DCHECK(result < scope_info->ContextLength());
541 542 543
      return result;
    }

544 545 546
    DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
              scope_info->ContextLocalNameEntriesIndex() +
                  scope_info->ContextLocalCount());
547
    int start = scope_info->ContextLocalNameEntriesIndex();
548 549
    int end = scope_info->ContextGlobalNameEntriesIndex() +
              scope_info->ContextGlobalCount();
550
    for (int i = start; i < end; ++i) {
551
      if (*name == scope_info->get(i)) {
552
        int var = i - start;
553 554
        *mode = scope_info->ContextLocalMode(var);
        *init_flag = scope_info->ContextLocalInitFlag(var);
555
        *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
556 557 558 559 560 561 562 563

        if (var < scope_info->ContextLocalCount()) {
          *location = VariableLocation::CONTEXT;
          result = Context::MIN_CONTEXT_SLOTS + var;
        } else {
          var -= scope_info->ContextLocalCount();
          *location = VariableLocation::GLOBAL;
          result = Context::MIN_CONTEXT_SLOTS +
564
                   scope_info->ContextLocalCount() + var;
565 566 567 568
        }

        context_slot_cache->Update(scope_info, name, *mode, *location,
                                   *init_flag, *maybe_assigned_flag, result);
569
        DCHECK(result < scope_info->ContextLength());
570
        return result;
571 572
      }
    }
573 574
    // Cache as not found. Mode, location, init flag and maybe assigned flag
    // don't matter.
575
    context_slot_cache->Update(scope_info, name, TEMPORARY,
576
                               VariableLocation::CONTEXT, kNeedsInitialization,
577
                               kNotAssigned, -1);
578 579 580 581 582
  }
  return -1;
}


583
String* ScopeInfo::ContextSlotName(int slot_index) {
584
  int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
585
  DCHECK_LE(0, var);
586 587
  DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount());
  return ContextLocalName(var);
588 589 590
}


591
int ScopeInfo::ParameterIndex(String* name) {
592
  DCHECK(name->IsInternalizedString());
593
  if (length() > 0) {
594 595 596 597 598
    // We must read parameters from the end since for
    // multiply declared parameters the value of the
    // last declaration of that parameter is used
    // inside a function (and thus we need to look
    // at the last index). Was bug# 1110337.
599 600 601 602 603 604
    int start = ParameterEntriesIndex();
    int end = ParameterEntriesIndex() + ParameterCount();
    for (int i = end - 1; i >= start; --i) {
      if (name == get(i)) {
        return i - start;
      }
605 606 607 608 609 610
    }
  }
  return -1;
}


611 612 613 614 615 616 617
int ScopeInfo::ReceiverContextSlotIndex() {
  if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
    return Smi::cast(get(ReceiverEntryIndex()))->value();
  return -1;
}


618
int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
619 620
  DCHECK(name->IsInternalizedString());
  DCHECK(mode != NULL);
621
  if (length() > 0) {
622 623 624 625
    if (FunctionVariableField::decode(Flags()) == CONTEXT &&
        FunctionName() == name) {
      *mode = FunctionVariableMode::decode(Flags());
      return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
626 627 628 629 630 631
    }
  }
  return -1;
}


632 633 634 635 636
FunctionKind ScopeInfo::function_kind() {
  return FunctionKindField::decode(Flags());
}


637
int ScopeInfo::ParameterEntriesIndex() {
638
  DCHECK(length() > 0);
639 640 641 642
  return kVariablePartIndex;
}


643
int ScopeInfo::StackLocalFirstSlotIndex() {
644 645 646 647
  return ParameterEntriesIndex() + ParameterCount();
}


648 649 650 651 652
int ScopeInfo::StackLocalEntriesIndex() {
  return StackLocalFirstSlotIndex() + 1;
}


653 654 655 656 657
int ScopeInfo::ContextLocalNameEntriesIndex() {
  return StackLocalEntriesIndex() + StackLocalCount();
}


658
int ScopeInfo::ContextGlobalNameEntriesIndex() {
659 660 661 662
  return ContextLocalNameEntriesIndex() + ContextLocalCount();
}


663 664 665 666 667 668
int ScopeInfo::ContextLocalInfoEntriesIndex() {
  return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
}


int ScopeInfo::ContextGlobalInfoEntriesIndex() {
669
  return ContextLocalInfoEntriesIndex() + ContextLocalCount();
670 671 672
}


673 674 675 676 677
int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
  return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
}


678 679 680 681 682 683
int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
  return StrongModeFreeVariableNameEntriesIndex() +
         StrongModeFreeVariableCount();
}


684
int ScopeInfo::ReceiverEntryIndex() {
685 686 687 688 689
  return StrongModeFreeVariablePositionEntriesIndex() +
         2 * StrongModeFreeVariableCount();
}


690 691 692 693 694
int ScopeInfo::FunctionNameEntryIndex() {
  return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0);
}


695
int ContextSlotCache::Hash(Object* data, String* name) {
696 697
  // Uses only lower 32 bits if pointers are larger.
  uintptr_t addr_hash =
698
      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
699
  return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
700 701 702
}


703
int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
704
                             VariableLocation* location,
705 706
                             InitializationFlag* init_flag,
                             MaybeAssignedFlag* maybe_assigned_flag) {
707
  int index = Hash(data, name);
708
  Key& key = keys_[index];
709
  if ((key.data == data) && key.name->Equals(name)) {
710 711
    Value result(values_[index]);
    if (mode != NULL) *mode = result.mode();
712
    if (location != NULL) *location = result.location();
713
    if (init_flag != NULL) *init_flag = result.initialization_flag();
714 715
    if (maybe_assigned_flag != NULL)
      *maybe_assigned_flag = result.maybe_assigned_flag();
716 717 718 719 720 721
    return result.index() + kNotFound;
  }
  return kNotFound;
}


722
void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
723 724
                              VariableMode mode, VariableLocation location,
                              InitializationFlag init_flag,
725
                              MaybeAssignedFlag maybe_assigned_flag,
726
                              int slot_index) {
727
  DisallowHeapAllocation no_gc;
728
  Handle<String> internalized_name;
729
  DCHECK(slot_index > kNotFound);
730 731 732
  if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
      ToHandle(&internalized_name)) {
    int index = Hash(*data, *internalized_name);
733
    Key& key = keys_[index];
734
    key.data = *data;
735
    key.name = *internalized_name;
736
    // Please note value only takes a uint as index.
737
    values_[index] = Value(mode, location, init_flag, maybe_assigned_flag,
738
                           slot_index - kNotFound).raw();
739
#ifdef DEBUG
740 741
    ValidateEntry(data, name, mode, location, init_flag, maybe_assigned_flag,
                  slot_index);
742 743 744 745 746 747
#endif
  }
}


void ContextSlotCache::Clear() {
748
  for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
749 750 751
}


752
#ifdef DEBUG
753

754
void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
755
                                     VariableMode mode,
756
                                     VariableLocation location,
757
                                     InitializationFlag init_flag,
758
                                     MaybeAssignedFlag maybe_assigned_flag,
759
                                     int slot_index) {
760
  DisallowHeapAllocation no_gc;
761 762 763
  Handle<String> internalized_name;
  if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
      ToHandle(&internalized_name)) {
764
    int index = Hash(*data, *name);
765
    Key& key = keys_[index];
766 767
    DCHECK(key.data == *data);
    DCHECK(key.name->Equals(*name));
768
    Value result(values_[index]);
769
    DCHECK(result.mode() == mode);
770
    DCHECK(result.location() == location);
771 772 773
    DCHECK(result.initialization_flag() == init_flag);
    DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
    DCHECK(result.index() + kNotFound == slot_index);
774 775 776 777
  }
}


778 779
static void PrintList(const char* list_name,
                      int nof_internal_slots,
780 781 782 783
                      int start,
                      int end,
                      ScopeInfo* scope_info) {
  if (start < end) {
784 785 786 787
    PrintF("\n  // %s\n", list_name);
    if (nof_internal_slots > 0) {
      PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
    }
788 789 790
    for (int i = nof_internal_slots; start < end; ++i, ++start) {
      PrintF("  %2d ", i);
      String::cast(scope_info->get(start))->ShortPrint();
791 792 793 794 795 796
      PrintF("\n");
    }
  }
}


797
void ScopeInfo::Print() {
798
  PrintF("ScopeInfo ");
799 800 801
  if (HasFunctionName()) {
    FunctionName()->ShortPrint();
  } else {
802
    PrintF("/* no function name */");
803
  }
804 805
  PrintF("{");

806 807 808 809 810 811 812 813 814 815 816 817 818
  PrintList("parameters", 0,
            ParameterEntriesIndex(),
            ParameterEntriesIndex() + ParameterCount(),
            this);
  PrintList("stack slots", 0,
            StackLocalEntriesIndex(),
            StackLocalEntriesIndex() + StackLocalCount(),
            this);
  PrintList("context slots",
            Context::MIN_CONTEXT_SLOTS,
            ContextLocalNameEntriesIndex(),
            ContextLocalNameEntriesIndex() + ContextLocalCount(),
            this);
819 820 821 822 823

  PrintF("}\n");
}
#endif  // DEBUG

824 825 826 827

//---------------------------------------------------------------------------
// ModuleInfo.

828 829 830 831 832
Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate,
                                      ModuleDescriptor* descriptor,
                                      Scope* scope) {
  Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length());
  info->set_host_index(descriptor->Index());
833
  int i = 0;
834 835
  for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
       it.Advance(), ++i) {
836 837
    Variable* var = scope->LookupLocal(it.local_name());
    info->set_name(i, *(it.export_name()->string()));
838
    info->set_mode(i, var->mode());
839 840
    DCHECK(var->index() >= 0);
    info->set_index(i, var->index());
841
  }
842
  DCHECK(i == info->length());
843 844 845
  return info;
}

846 847
}  // namespace internal
}  // namespace v8