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