• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/ast/scopeinfo.h"
6 
7 #include <stdlib.h>
8 
9 #include "src/ast/scopes.h"
10 #include "src/bootstrapper.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 
Create(Isolate * isolate,Zone * zone,Scope * scope)16 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
17                                     Scope* scope) {
18   // Collect stack and context locals.
19   ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
20   ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
21   ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
22   ZoneList<Variable*> strong_mode_free_variables(0, zone);
23 
24   scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
25                                       &context_globals,
26                                       &strong_mode_free_variables);
27   const int stack_local_count = stack_locals.length();
28   const int context_local_count = context_locals.length();
29   const int context_global_count = context_globals.length();
30   const int strong_mode_free_variable_count =
31       strong_mode_free_variables.length();
32   // Make sure we allocate the correct amount.
33   DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
34   DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
35 
36   // Determine use and location of the "this" binding if it is present.
37   VariableAllocationInfo receiver_info;
38   if (scope->has_this_declaration()) {
39     Variable* var = scope->receiver();
40     if (!var->is_used()) {
41       receiver_info = UNUSED;
42     } else if (var->IsContextSlot()) {
43       receiver_info = CONTEXT;
44     } else {
45       DCHECK(var->IsParameter());
46       receiver_info = STACK;
47     }
48   } else {
49     receiver_info = NONE;
50   }
51 
52   bool has_new_target = scope->new_target_var() != nullptr;
53 
54   // Determine use and location of the function variable if it is present.
55   VariableAllocationInfo function_name_info;
56   VariableMode function_variable_mode;
57   if (scope->is_function_scope() && scope->function() != NULL) {
58     Variable* var = scope->function()->proxy()->var();
59     if (!var->is_used()) {
60       function_name_info = UNUSED;
61     } else if (var->IsContextSlot()) {
62       function_name_info = CONTEXT;
63     } else {
64       DCHECK(var->IsStackLocal());
65       function_name_info = STACK;
66     }
67     function_variable_mode = var->mode();
68   } else {
69     function_name_info = NONE;
70     function_variable_mode = VAR;
71   }
72   DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE);
73 
74   const bool has_function_name = function_name_info != NONE;
75   const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
76   const int parameter_count = scope->num_parameters();
77   const int length = kVariablePartIndex + parameter_count +
78                      (1 + stack_local_count) + 2 * context_local_count +
79                      2 * context_global_count +
80                      3 * strong_mode_free_variable_count +
81                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
82 
83   Factory* factory = isolate->factory();
84   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
85 
86   bool has_simple_parameters =
87       scope->is_function_scope() && scope->has_simple_parameters();
88 
89   // Encode the flags.
90   int flags = ScopeTypeField::encode(scope->scope_type()) |
91               CallsEvalField::encode(scope->calls_eval()) |
92               LanguageModeField::encode(scope->language_mode()) |
93               DeclarationScopeField::encode(scope->is_declaration_scope()) |
94               ReceiverVariableField::encode(receiver_info) |
95               HasNewTargetField::encode(has_new_target) |
96               FunctionVariableField::encode(function_name_info) |
97               FunctionVariableMode::encode(function_variable_mode) |
98               AsmModuleField::encode(scope->asm_module()) |
99               AsmFunctionField::encode(scope->asm_function()) |
100               HasSimpleParametersField::encode(has_simple_parameters) |
101               FunctionKindField::encode(scope->function_kind());
102   scope_info->SetFlags(flags);
103   scope_info->SetParameterCount(parameter_count);
104   scope_info->SetStackLocalCount(stack_local_count);
105   scope_info->SetContextLocalCount(context_local_count);
106   scope_info->SetContextGlobalCount(context_global_count);
107   scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
108 
109   int index = kVariablePartIndex;
110   // Add parameters.
111   DCHECK(index == scope_info->ParameterEntriesIndex());
112   for (int i = 0; i < parameter_count; ++i) {
113     scope_info->set(index++, *scope->parameter(i)->name());
114   }
115 
116   // Add stack locals' names. We are assuming that the stack locals'
117   // slots are allocated in increasing order, so we can simply add
118   // them to the ScopeInfo object.
119   int first_slot_index;
120   if (stack_local_count > 0) {
121     first_slot_index = stack_locals[0]->index();
122   } else {
123     first_slot_index = 0;
124   }
125   DCHECK(index == scope_info->StackLocalFirstSlotIndex());
126   scope_info->set(index++, Smi::FromInt(first_slot_index));
127   DCHECK(index == scope_info->StackLocalEntriesIndex());
128   for (int i = 0; i < stack_local_count; ++i) {
129     DCHECK(stack_locals[i]->index() == first_slot_index + i);
130     scope_info->set(index++, *stack_locals[i]->name());
131   }
132 
133   // Due to usage analysis, context-allocated locals are not necessarily in
134   // increasing order: Some of them may be parameters which are allocated before
135   // the non-parameter locals. When the non-parameter locals are sorted
136   // according to usage, the allocated slot indices may not be in increasing
137   // order with the variable list anymore. Thus, we first need to sort them by
138   // context slot index before adding them to the ScopeInfo object.
139   context_locals.Sort(&Variable::CompareIndex);
140 
141   // Add context locals' names.
142   DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
143   for (int i = 0; i < context_local_count; ++i) {
144     scope_info->set(index++, *context_locals[i]->name());
145   }
146 
147   // Add context globals' names.
148   DCHECK(index == scope_info->ContextGlobalNameEntriesIndex());
149   for (int i = 0; i < context_global_count; ++i) {
150     scope_info->set(index++, *context_globals[i]->name());
151   }
152 
153   // Add context locals' info.
154   DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
155   for (int i = 0; i < context_local_count; ++i) {
156     Variable* var = context_locals[i];
157     uint32_t value =
158         ContextLocalMode::encode(var->mode()) |
159         ContextLocalInitFlag::encode(var->initialization_flag()) |
160         ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
161     scope_info->set(index++, Smi::FromInt(value));
162   }
163 
164   // Add context globals' info.
165   DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
166   for (int i = 0; i < context_global_count; ++i) {
167     Variable* var = context_globals[i];
168     // TODO(ishell): do we need this kind of info for globals here?
169     uint32_t value =
170         ContextLocalMode::encode(var->mode()) |
171         ContextLocalInitFlag::encode(var->initialization_flag()) |
172         ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
173     scope_info->set(index++, Smi::FromInt(value));
174   }
175 
176   DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
177   for (int i = 0; i < strong_mode_free_variable_count; ++i) {
178     scope_info->set(index++, *strong_mode_free_variables[i]->name());
179   }
180 
181   DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
182   for (int i = 0; i < strong_mode_free_variable_count; ++i) {
183     // Unfortunately, the source code positions are stored as int even though
184     // int32_t would be enough (given the maximum source code length).
185     Handle<Object> start_position = factory->NewNumberFromInt(
186         static_cast<int32_t>(strong_mode_free_variables[i]
187                                  ->strong_mode_reference_start_position()));
188     scope_info->set(index++, *start_position);
189     Handle<Object> end_position = factory->NewNumberFromInt(
190         static_cast<int32_t>(strong_mode_free_variables[i]
191                                  ->strong_mode_reference_end_position()));
192     scope_info->set(index++, *end_position);
193   }
194 
195   // If the receiver is allocated, add its index.
196   DCHECK(index == scope_info->ReceiverEntryIndex());
197   if (has_receiver) {
198     int var_index = scope->receiver()->index();
199     scope_info->set(index++, Smi::FromInt(var_index));
200     // ?? DCHECK(receiver_info != CONTEXT || var_index ==
201     // scope_info->ContextLength() - 1);
202   }
203 
204   // If present, add the function variable name and its index.
205   DCHECK(index == scope_info->FunctionNameEntryIndex());
206   if (has_function_name) {
207     int var_index = scope->function()->proxy()->var()->index();
208     scope_info->set(index++, *scope->function()->proxy()->name());
209     scope_info->set(index++, Smi::FromInt(var_index));
210     DCHECK(function_name_info != CONTEXT ||
211            var_index == scope_info->ContextLength() - 1);
212   }
213 
214   DCHECK(index == scope_info->length());
215   DCHECK(scope->num_parameters() == scope_info->ParameterCount());
216   DCHECK(scope->num_heap_slots() == scope_info->ContextLength() ||
217          (scope->num_heap_slots() == kVariablePartIndex &&
218           scope_info->ContextLength() == 0));
219   return scope_info;
220 }
221 
222 
CreateGlobalThisBinding(Isolate * isolate)223 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
224   DCHECK(isolate->bootstrapper()->IsActive());
225 
226   const int stack_local_count = 0;
227   const int context_local_count = 1;
228   const int context_global_count = 0;
229   const int strong_mode_free_variable_count = 0;
230   const bool has_simple_parameters = true;
231   const VariableAllocationInfo receiver_info = CONTEXT;
232   const VariableAllocationInfo function_name_info = NONE;
233   const VariableMode function_variable_mode = VAR;
234   const bool has_function_name = false;
235   const bool has_receiver = true;
236   const int parameter_count = 0;
237   const int length = kVariablePartIndex + parameter_count +
238                      (1 + stack_local_count) + 2 * context_local_count +
239                      2 * context_global_count +
240                      3 * strong_mode_free_variable_count +
241                      (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
242 
243   Factory* factory = isolate->factory();
244   Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
245 
246   // Encode the flags.
247   int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
248               CallsEvalField::encode(false) |
249               LanguageModeField::encode(SLOPPY) |
250               DeclarationScopeField::encode(true) |
251               ReceiverVariableField::encode(receiver_info) |
252               FunctionVariableField::encode(function_name_info) |
253               FunctionVariableMode::encode(function_variable_mode) |
254               AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
255               HasSimpleParametersField::encode(has_simple_parameters) |
256               FunctionKindField::encode(FunctionKind::kNormalFunction);
257   scope_info->SetFlags(flags);
258   scope_info->SetParameterCount(parameter_count);
259   scope_info->SetStackLocalCount(stack_local_count);
260   scope_info->SetContextLocalCount(context_local_count);
261   scope_info->SetContextGlobalCount(context_global_count);
262   scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
263 
264   int index = kVariablePartIndex;
265   const int first_slot_index = 0;
266   DCHECK(index == scope_info->StackLocalFirstSlotIndex());
267   scope_info->set(index++, Smi::FromInt(first_slot_index));
268   DCHECK(index == scope_info->StackLocalEntriesIndex());
269 
270   // Here we add info for context-allocated "this".
271   DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
272   scope_info->set(index++, *isolate->factory()->this_string());
273   DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
274   const uint32_t value = ContextLocalMode::encode(CONST) |
275                          ContextLocalInitFlag::encode(kCreatedInitialized) |
276                          ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
277   scope_info->set(index++, Smi::FromInt(value));
278 
279   DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
280   DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
281 
282   // And here we record that this scopeinfo binds a receiver.
283   DCHECK(index == scope_info->ReceiverEntryIndex());
284   const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
285   scope_info->set(index++, Smi::FromInt(receiver_index));
286 
287   DCHECK(index == scope_info->FunctionNameEntryIndex());
288 
289   DCHECK_EQ(index, scope_info->length());
290   DCHECK_EQ(scope_info->ParameterCount(), 0);
291   DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
292 
293   return scope_info;
294 }
295 
296 
Empty(Isolate * isolate)297 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
298   return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
299 }
300 
301 
scope_type()302 ScopeType ScopeInfo::scope_type() {
303   DCHECK(length() > 0);
304   return ScopeTypeField::decode(Flags());
305 }
306 
307 
CallsEval()308 bool ScopeInfo::CallsEval() {
309   return length() > 0 && CallsEvalField::decode(Flags());
310 }
311 
312 
language_mode()313 LanguageMode ScopeInfo::language_mode() {
314   return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
315 }
316 
317 
is_declaration_scope()318 bool ScopeInfo::is_declaration_scope() {
319   return DeclarationScopeField::decode(Flags());
320 }
321 
322 
LocalCount()323 int ScopeInfo::LocalCount() {
324   return StackLocalCount() + ContextLocalCount();
325 }
326 
327 
StackSlotCount()328 int ScopeInfo::StackSlotCount() {
329   if (length() > 0) {
330     bool function_name_stack_slot =
331         FunctionVariableField::decode(Flags()) == STACK;
332     return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
333   }
334   return 0;
335 }
336 
337 
ContextLength()338 int ScopeInfo::ContextLength() {
339   if (length() > 0) {
340     int context_locals = ContextLocalCount();
341     int context_globals = ContextGlobalCount();
342     bool function_name_context_slot =
343         FunctionVariableField::decode(Flags()) == CONTEXT;
344     bool has_context = context_locals > 0 || context_globals > 0 ||
345                        function_name_context_slot ||
346                        scope_type() == WITH_SCOPE ||
347                        (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
348                            is_declaration_scope()) ||
349                        (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
350                        scope_type() == MODULE_SCOPE;
351 
352     if (has_context) {
353       return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals +
354              (function_name_context_slot ? 1 : 0);
355     }
356   }
357   return 0;
358 }
359 
360 
HasReceiver()361 bool ScopeInfo::HasReceiver() {
362   if (length() > 0) {
363     return NONE != ReceiverVariableField::decode(Flags());
364   } else {
365     return false;
366   }
367 }
368 
369 
HasAllocatedReceiver()370 bool ScopeInfo::HasAllocatedReceiver() {
371   if (length() > 0) {
372     VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
373     return allocation == STACK || allocation == CONTEXT;
374   } else {
375     return false;
376   }
377 }
378 
379 
HasNewTarget()380 bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
381 
382 
HasFunctionName()383 bool ScopeInfo::HasFunctionName() {
384   if (length() > 0) {
385     return NONE != FunctionVariableField::decode(Flags());
386   } else {
387     return false;
388   }
389 }
390 
391 
HasHeapAllocatedLocals()392 bool ScopeInfo::HasHeapAllocatedLocals() {
393   if (length() > 0) {
394     return ContextLocalCount() > 0;
395   } else {
396     return false;
397   }
398 }
399 
400 
HasContext()401 bool ScopeInfo::HasContext() {
402   return ContextLength() > 0;
403 }
404 
405 
FunctionName()406 String* ScopeInfo::FunctionName() {
407   DCHECK(HasFunctionName());
408   return String::cast(get(FunctionNameEntryIndex()));
409 }
410 
411 
ParameterName(int var)412 String* ScopeInfo::ParameterName(int var) {
413   DCHECK(0 <= var && var < ParameterCount());
414   int info_index = ParameterEntriesIndex() + var;
415   return String::cast(get(info_index));
416 }
417 
418 
LocalName(int var)419 String* ScopeInfo::LocalName(int var) {
420   DCHECK(0 <= var && var < LocalCount());
421   DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
422          ContextLocalNameEntriesIndex());
423   int info_index = StackLocalEntriesIndex() + var;
424   return String::cast(get(info_index));
425 }
426 
427 
StackLocalName(int var)428 String* ScopeInfo::StackLocalName(int var) {
429   DCHECK(0 <= var && var < StackLocalCount());
430   int info_index = StackLocalEntriesIndex() + var;
431   return String::cast(get(info_index));
432 }
433 
434 
StackLocalIndex(int var)435 int ScopeInfo::StackLocalIndex(int var) {
436   DCHECK(0 <= var && var < StackLocalCount());
437   int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
438   return first_slot_index + var;
439 }
440 
441 
ContextLocalName(int var)442 String* ScopeInfo::ContextLocalName(int var) {
443   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
444   int info_index = ContextLocalNameEntriesIndex() + var;
445   return String::cast(get(info_index));
446 }
447 
448 
ContextLocalMode(int var)449 VariableMode ScopeInfo::ContextLocalMode(int var) {
450   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
451   int info_index = ContextLocalInfoEntriesIndex() + var;
452   int value = Smi::cast(get(info_index))->value();
453   return ContextLocalMode::decode(value);
454 }
455 
456 
ContextLocalInitFlag(int var)457 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
458   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
459   int info_index = ContextLocalInfoEntriesIndex() + var;
460   int value = Smi::cast(get(info_index))->value();
461   return ContextLocalInitFlag::decode(value);
462 }
463 
464 
ContextLocalMaybeAssignedFlag(int var)465 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
466   DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
467   int info_index = ContextLocalInfoEntriesIndex() + var;
468   int value = Smi::cast(get(info_index))->value();
469   return ContextLocalMaybeAssignedFlag::decode(value);
470 }
471 
472 
LocalIsSynthetic(int var)473 bool ScopeInfo::LocalIsSynthetic(int var) {
474   DCHECK(0 <= var && var < LocalCount());
475   // There's currently no flag stored on the ScopeInfo to indicate that a
476   // variable is a compiler-introduced temporary. However, to avoid conflict
477   // with user declarations, the current temporaries like .generator_object and
478   // .result start with a dot, so we can use that as a flag. It's a hack!
479   Handle<String> name(LocalName(var));
480   return (name->length() > 0 && name->Get(0) == '.') ||
481          name->Equals(*GetIsolate()->factory()->this_string());
482 }
483 
484 
StrongModeFreeVariableName(int var)485 String* ScopeInfo::StrongModeFreeVariableName(int var) {
486   DCHECK(0 <= var && var < StrongModeFreeVariableCount());
487   int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
488   return String::cast(get(info_index));
489 }
490 
491 
StrongModeFreeVariableStartPosition(int var)492 int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
493   DCHECK(0 <= var && var < StrongModeFreeVariableCount());
494   int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
495   int32_t value = 0;
496   bool ok = get(info_index)->ToInt32(&value);
497   USE(ok);
498   DCHECK(ok);
499   return value;
500 }
501 
502 
StrongModeFreeVariableEndPosition(int var)503 int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
504   DCHECK(0 <= var && var < StrongModeFreeVariableCount());
505   int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
506   int32_t value = 0;
507   bool ok = get(info_index)->ToInt32(&value);
508   USE(ok);
509   DCHECK(ok);
510   return value;
511 }
512 
513 
StackSlotIndex(String * name)514 int ScopeInfo::StackSlotIndex(String* name) {
515   DCHECK(name->IsInternalizedString());
516   if (length() > 0) {
517     int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
518     int start = StackLocalEntriesIndex();
519     int end = StackLocalEntriesIndex() + StackLocalCount();
520     for (int i = start; i < end; ++i) {
521       if (name == get(i)) {
522         return i - start + first_slot_index;
523       }
524     }
525   }
526   return -1;
527 }
528 
529 
ContextSlotIndex(Handle<ScopeInfo> scope_info,Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)530 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
531                                 Handle<String> name, VariableMode* mode,
532                                 InitializationFlag* init_flag,
533                                 MaybeAssignedFlag* maybe_assigned_flag) {
534   DCHECK(name->IsInternalizedString());
535   DCHECK(mode != NULL);
536   DCHECK(init_flag != NULL);
537   if (scope_info->length() > 0) {
538     ContextSlotCache* context_slot_cache =
539         scope_info->GetIsolate()->context_slot_cache();
540     int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
541                                             maybe_assigned_flag);
542     if (result != ContextSlotCache::kNotFound) {
543       DCHECK(result < scope_info->ContextLength());
544       return result;
545     }
546 
547     int start = scope_info->ContextLocalNameEntriesIndex();
548     int end = scope_info->ContextLocalNameEntriesIndex() +
549               scope_info->ContextLocalCount();
550     for (int i = start; i < end; ++i) {
551       if (*name == scope_info->get(i)) {
552         int var = i - start;
553         *mode = scope_info->ContextLocalMode(var);
554         *init_flag = scope_info->ContextLocalInitFlag(var);
555         *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
556         result = Context::MIN_CONTEXT_SLOTS + var;
557 
558         context_slot_cache->Update(scope_info, name, *mode, *init_flag,
559                                    *maybe_assigned_flag, result);
560         DCHECK(result < scope_info->ContextLength());
561         return result;
562       }
563     }
564     // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
565     context_slot_cache->Update(scope_info, name, TEMPORARY,
566                                kNeedsInitialization, kNotAssigned, -1);
567   }
568   return -1;
569 }
570 
571 
ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info,Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)572 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info,
573                                       Handle<String> name, VariableMode* mode,
574                                       InitializationFlag* init_flag,
575                                       MaybeAssignedFlag* maybe_assigned_flag) {
576   DCHECK(name->IsInternalizedString());
577   DCHECK(mode != NULL);
578   DCHECK(init_flag != NULL);
579   if (scope_info->length() > 0) {
580     // This is to ensure that ContextLocalMode() and co. queries would work.
581     DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
582               scope_info->ContextLocalNameEntriesIndex() +
583                   scope_info->ContextLocalCount());
584     int base = scope_info->ContextLocalNameEntriesIndex();
585     int start = scope_info->ContextGlobalNameEntriesIndex();
586     int end = scope_info->ContextGlobalNameEntriesIndex() +
587               scope_info->ContextGlobalCount();
588     for (int i = start; i < end; ++i) {
589       if (*name == scope_info->get(i)) {
590         int var = i - base;
591         *mode = scope_info->ContextLocalMode(var);
592         *init_flag = scope_info->ContextLocalInitFlag(var);
593         *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
594         int result = Context::MIN_CONTEXT_SLOTS + var;
595         DCHECK(result < scope_info->ContextLength());
596         return result;
597       }
598     }
599   }
600   return -1;
601 }
602 
603 
ContextSlotName(int slot_index)604 String* ScopeInfo::ContextSlotName(int slot_index) {
605   int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
606   DCHECK_LE(0, var);
607   DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount());
608   return ContextLocalName(var);
609 }
610 
611 
ParameterIndex(String * name)612 int ScopeInfo::ParameterIndex(String* name) {
613   DCHECK(name->IsInternalizedString());
614   if (length() > 0) {
615     // We must read parameters from the end since for
616     // multiply declared parameters the value of the
617     // last declaration of that parameter is used
618     // inside a function (and thus we need to look
619     // at the last index). Was bug# 1110337.
620     int start = ParameterEntriesIndex();
621     int end = ParameterEntriesIndex() + ParameterCount();
622     for (int i = end - 1; i >= start; --i) {
623       if (name == get(i)) {
624         return i - start;
625       }
626     }
627   }
628   return -1;
629 }
630 
631 
ReceiverContextSlotIndex()632 int ScopeInfo::ReceiverContextSlotIndex() {
633   if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
634     return Smi::cast(get(ReceiverEntryIndex()))->value();
635   return -1;
636 }
637 
638 
FunctionContextSlotIndex(String * name,VariableMode * mode)639 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
640   DCHECK(name->IsInternalizedString());
641   DCHECK(mode != NULL);
642   if (length() > 0) {
643     if (FunctionVariableField::decode(Flags()) == CONTEXT &&
644         FunctionName() == name) {
645       *mode = FunctionVariableMode::decode(Flags());
646       return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
647     }
648   }
649   return -1;
650 }
651 
652 
function_kind()653 FunctionKind ScopeInfo::function_kind() {
654   return FunctionKindField::decode(Flags());
655 }
656 
657 
ParameterEntriesIndex()658 int ScopeInfo::ParameterEntriesIndex() {
659   DCHECK(length() > 0);
660   return kVariablePartIndex;
661 }
662 
663 
StackLocalFirstSlotIndex()664 int ScopeInfo::StackLocalFirstSlotIndex() {
665   return ParameterEntriesIndex() + ParameterCount();
666 }
667 
668 
StackLocalEntriesIndex()669 int ScopeInfo::StackLocalEntriesIndex() {
670   return StackLocalFirstSlotIndex() + 1;
671 }
672 
673 
ContextLocalNameEntriesIndex()674 int ScopeInfo::ContextLocalNameEntriesIndex() {
675   return StackLocalEntriesIndex() + StackLocalCount();
676 }
677 
678 
ContextGlobalNameEntriesIndex()679 int ScopeInfo::ContextGlobalNameEntriesIndex() {
680   return ContextLocalNameEntriesIndex() + ContextLocalCount();
681 }
682 
683 
ContextLocalInfoEntriesIndex()684 int ScopeInfo::ContextLocalInfoEntriesIndex() {
685   return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
686 }
687 
688 
ContextGlobalInfoEntriesIndex()689 int ScopeInfo::ContextGlobalInfoEntriesIndex() {
690   return ContextLocalInfoEntriesIndex() + ContextLocalCount();
691 }
692 
693 
StrongModeFreeVariableNameEntriesIndex()694 int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
695   return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
696 }
697 
698 
StrongModeFreeVariablePositionEntriesIndex()699 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
700   return StrongModeFreeVariableNameEntriesIndex() +
701          StrongModeFreeVariableCount();
702 }
703 
704 
ReceiverEntryIndex()705 int ScopeInfo::ReceiverEntryIndex() {
706   return StrongModeFreeVariablePositionEntriesIndex() +
707          2 * StrongModeFreeVariableCount();
708 }
709 
710 
FunctionNameEntryIndex()711 int ScopeInfo::FunctionNameEntryIndex() {
712   return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0);
713 }
714 
715 
Hash(Object * data,String * name)716 int ContextSlotCache::Hash(Object* data, String* name) {
717   // Uses only lower 32 bits if pointers are larger.
718   uintptr_t addr_hash =
719       static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
720   return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
721 }
722 
723 
Lookup(Object * data,String * name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)724 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
725                              InitializationFlag* init_flag,
726                              MaybeAssignedFlag* maybe_assigned_flag) {
727   int index = Hash(data, name);
728   Key& key = keys_[index];
729   if ((key.data == data) && key.name->Equals(name)) {
730     Value result(values_[index]);
731     if (mode != NULL) *mode = result.mode();
732     if (init_flag != NULL) *init_flag = result.initialization_flag();
733     if (maybe_assigned_flag != NULL)
734       *maybe_assigned_flag = result.maybe_assigned_flag();
735     return result.index() + kNotFound;
736   }
737   return kNotFound;
738 }
739 
740 
Update(Handle<Object> data,Handle<String> name,VariableMode mode,InitializationFlag init_flag,MaybeAssignedFlag maybe_assigned_flag,int slot_index)741 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
742                               VariableMode mode, InitializationFlag init_flag,
743                               MaybeAssignedFlag maybe_assigned_flag,
744                               int slot_index) {
745   DisallowHeapAllocation no_gc;
746   Handle<String> internalized_name;
747   DCHECK(slot_index > kNotFound);
748   if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
749       ToHandle(&internalized_name)) {
750     int index = Hash(*data, *internalized_name);
751     Key& key = keys_[index];
752     key.data = *data;
753     key.name = *internalized_name;
754     // Please note value only takes a uint as index.
755     values_[index] = Value(mode, init_flag, maybe_assigned_flag,
756                            slot_index - kNotFound).raw();
757 #ifdef DEBUG
758     ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
759 #endif
760   }
761 }
762 
763 
Clear()764 void ContextSlotCache::Clear() {
765   for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
766 }
767 
768 
769 #ifdef DEBUG
770 
ValidateEntry(Handle<Object> data,Handle<String> name,VariableMode mode,InitializationFlag init_flag,MaybeAssignedFlag maybe_assigned_flag,int slot_index)771 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
772                                      VariableMode mode,
773                                      InitializationFlag init_flag,
774                                      MaybeAssignedFlag maybe_assigned_flag,
775                                      int slot_index) {
776   DisallowHeapAllocation no_gc;
777   Handle<String> internalized_name;
778   if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
779       ToHandle(&internalized_name)) {
780     int index = Hash(*data, *name);
781     Key& key = keys_[index];
782     DCHECK(key.data == *data);
783     DCHECK(key.name->Equals(*name));
784     Value result(values_[index]);
785     DCHECK(result.mode() == mode);
786     DCHECK(result.initialization_flag() == init_flag);
787     DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
788     DCHECK(result.index() + kNotFound == slot_index);
789   }
790 }
791 
792 
PrintList(const char * list_name,int nof_internal_slots,int start,int end,ScopeInfo * scope_info)793 static void PrintList(const char* list_name,
794                       int nof_internal_slots,
795                       int start,
796                       int end,
797                       ScopeInfo* scope_info) {
798   if (start < end) {
799     PrintF("\n  // %s\n", list_name);
800     if (nof_internal_slots > 0) {
801       PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
802     }
803     for (int i = nof_internal_slots; start < end; ++i, ++start) {
804       PrintF("  %2d ", i);
805       String::cast(scope_info->get(start))->ShortPrint();
806       PrintF("\n");
807     }
808   }
809 }
810 
811 
Print()812 void ScopeInfo::Print() {
813   PrintF("ScopeInfo ");
814   if (HasFunctionName()) {
815     FunctionName()->ShortPrint();
816   } else {
817     PrintF("/* no function name */");
818   }
819   PrintF("{");
820 
821   if (length() > 0) {
822     PrintList("parameters", 0, ParameterEntriesIndex(),
823               ParameterEntriesIndex() + ParameterCount(), this);
824     PrintList("stack slots", 0, StackLocalEntriesIndex(),
825               StackLocalEntriesIndex() + StackLocalCount(), this);
826     PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
827               ContextLocalNameEntriesIndex(),
828               ContextLocalNameEntriesIndex() + ContextLocalCount(), this);
829   }
830 
831   PrintF("}\n");
832 }
833 #endif  // DEBUG
834 
835 
836 //---------------------------------------------------------------------------
837 // ModuleInfo.
838 
Create(Isolate * isolate,ModuleDescriptor * descriptor,Scope * scope)839 Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate,
840                                       ModuleDescriptor* descriptor,
841                                       Scope* scope) {
842   Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length());
843   info->set_host_index(descriptor->Index());
844   int i = 0;
845   for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
846        it.Advance(), ++i) {
847     Variable* var = scope->LookupLocal(it.local_name());
848     info->set_name(i, *(it.export_name()->string()));
849     info->set_mode(i, var->mode());
850     DCHECK(var->index() >= 0);
851     info->set_index(i, var->index());
852   }
853   DCHECK(i == info->length());
854   return info;
855 }
856 
857 }  // namespace internal
858 }  // namespace v8
859