Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: src/scopeinfo.cc

Issue 1481613002: Create ast/ and parsing/ subdirectories and move appropriate files (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/scopeinfo.h ('k') | src/scopes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/scopeinfo.h"
6
7 #include <stdlib.h>
8
9 #include "src/bootstrapper.h"
10 #include "src/scopes.h"
11
12 namespace v8 {
13 namespace internal {
14
15
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 // Determine use and location of the function variable if it is present.
53 VariableAllocationInfo function_name_info;
54 VariableMode function_variable_mode;
55 if (scope->is_function_scope() && scope->function() != NULL) {
56 Variable* var = scope->function()->proxy()->var();
57 if (!var->is_used()) {
58 function_name_info = UNUSED;
59 } else if (var->IsContextSlot()) {
60 function_name_info = CONTEXT;
61 } else {
62 DCHECK(var->IsStackLocal());
63 function_name_info = STACK;
64 }
65 function_variable_mode = var->mode();
66 } else {
67 function_name_info = NONE;
68 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 const int length = kVariablePartIndex + parameter_count +
76 (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 bool has_simple_parameters =
85 scope->is_function_scope() && scope->has_simple_parameters();
86
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 FunctionVariableField::encode(function_name_info) |
94 FunctionVariableMode::encode(function_variable_mode) |
95 AsmModuleField::encode(scope->asm_module()) |
96 AsmFunctionField::encode(scope->asm_function()) |
97 HasSimpleParametersField::encode(has_simple_parameters) |
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 has_simple_parameters = 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 DeclarationScopeField::encode(true) |
248 ReceiverVariableField::encode(receiver_info) |
249 FunctionVariableField::encode(function_name_info) |
250 FunctionVariableMode::encode(function_variable_mode) |
251 AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
252 HasSimpleParametersField::encode(has_simple_parameters) |
253 FunctionKindField::encode(FunctionKind::kNormalFunction);
254 scope_info->SetFlags(flags);
255 scope_info->SetParameterCount(parameter_count);
256 scope_info->SetStackLocalCount(stack_local_count);
257 scope_info->SetContextLocalCount(context_local_count);
258 scope_info->SetContextGlobalCount(context_global_count);
259 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
260
261 int index = kVariablePartIndex;
262 const int first_slot_index = 0;
263 DCHECK(index == scope_info->StackLocalFirstSlotIndex());
264 scope_info->set(index++, Smi::FromInt(first_slot_index));
265 DCHECK(index == scope_info->StackLocalEntriesIndex());
266
267 // Here we add info for context-allocated "this".
268 DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
269 scope_info->set(index++, *isolate->factory()->this_string());
270 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
271 const uint32_t value = ContextLocalMode::encode(CONST) |
272 ContextLocalInitFlag::encode(kCreatedInitialized) |
273 ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
274 scope_info->set(index++, Smi::FromInt(value));
275
276 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
277 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
278
279 // And here we record that this scopeinfo binds a receiver.
280 DCHECK(index == scope_info->ReceiverEntryIndex());
281 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
282 scope_info->set(index++, Smi::FromInt(receiver_index));
283
284 DCHECK(index == scope_info->FunctionNameEntryIndex());
285
286 DCHECK_EQ(index, scope_info->length());
287 DCHECK_EQ(scope_info->ParameterCount(), 0);
288 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
289
290 return scope_info;
291 }
292
293
294 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
295 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 bool ScopeInfo::CallsEval() {
306 return length() > 0 && CallsEvalField::decode(Flags());
307 }
308
309
310 LanguageMode ScopeInfo::language_mode() {
311 return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
312 }
313
314
315 bool ScopeInfo::is_declaration_scope() {
316 return DeclarationScopeField::decode(Flags());
317 }
318
319
320 int ScopeInfo::LocalCount() {
321 return StackLocalCount() + ContextLocalCount();
322 }
323
324
325 int ScopeInfo::StackSlotCount() {
326 if (length() > 0) {
327 bool function_name_stack_slot =
328 FunctionVariableField::decode(Flags()) == STACK;
329 return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
330 }
331 return 0;
332 }
333
334
335 int ScopeInfo::ContextLength() {
336 if (length() > 0) {
337 int context_locals = ContextLocalCount();
338 int context_globals = ContextGlobalCount();
339 bool function_name_context_slot =
340 FunctionVariableField::decode(Flags()) == CONTEXT;
341 bool has_context = context_locals > 0 || context_globals > 0 ||
342 function_name_context_slot ||
343 scope_type() == WITH_SCOPE ||
344 (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
345 is_declaration_scope()) ||
346 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
347 scope_type() == MODULE_SCOPE;
348
349 if (has_context) {
350 return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals +
351 (function_name_context_slot ? 1 : 0);
352 }
353 }
354 return 0;
355 }
356
357
358 bool ScopeInfo::HasReceiver() {
359 if (length() > 0) {
360 return NONE != ReceiverVariableField::decode(Flags());
361 } else {
362 return false;
363 }
364 }
365
366
367 bool ScopeInfo::HasAllocatedReceiver() {
368 if (length() > 0) {
369 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
370 return allocation == STACK || allocation == CONTEXT;
371 } else {
372 return false;
373 }
374 }
375
376
377 bool ScopeInfo::HasFunctionName() {
378 if (length() > 0) {
379 return NONE != FunctionVariableField::decode(Flags());
380 } else {
381 return false;
382 }
383 }
384
385
386 bool ScopeInfo::HasHeapAllocatedLocals() {
387 if (length() > 0) {
388 return ContextLocalCount() > 0;
389 } else {
390 return false;
391 }
392 }
393
394
395 bool ScopeInfo::HasContext() {
396 return ContextLength() > 0;
397 }
398
399
400 String* ScopeInfo::FunctionName() {
401 DCHECK(HasFunctionName());
402 return String::cast(get(FunctionNameEntryIndex()));
403 }
404
405
406 String* ScopeInfo::ParameterName(int var) {
407 DCHECK(0 <= var && var < ParameterCount());
408 int info_index = ParameterEntriesIndex() + var;
409 return String::cast(get(info_index));
410 }
411
412
413 String* ScopeInfo::LocalName(int var) {
414 DCHECK(0 <= var && var < LocalCount());
415 DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
416 ContextLocalNameEntriesIndex());
417 int info_index = StackLocalEntriesIndex() + var;
418 return String::cast(get(info_index));
419 }
420
421
422 String* ScopeInfo::StackLocalName(int var) {
423 DCHECK(0 <= var && var < StackLocalCount());
424 int info_index = StackLocalEntriesIndex() + var;
425 return String::cast(get(info_index));
426 }
427
428
429 int ScopeInfo::StackLocalIndex(int var) {
430 DCHECK(0 <= var && var < StackLocalCount());
431 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
432 return first_slot_index + var;
433 }
434
435
436 String* ScopeInfo::ContextLocalName(int var) {
437 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
438 int info_index = ContextLocalNameEntriesIndex() + var;
439 return String::cast(get(info_index));
440 }
441
442
443 VariableMode ScopeInfo::ContextLocalMode(int var) {
444 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
445 int info_index = ContextLocalInfoEntriesIndex() + var;
446 int value = Smi::cast(get(info_index))->value();
447 return ContextLocalMode::decode(value);
448 }
449
450
451 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
452 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
453 int info_index = ContextLocalInfoEntriesIndex() + var;
454 int value = Smi::cast(get(info_index))->value();
455 return ContextLocalInitFlag::decode(value);
456 }
457
458
459 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
460 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
461 int info_index = ContextLocalInfoEntriesIndex() + var;
462 int value = Smi::cast(get(info_index))->value();
463 return ContextLocalMaybeAssignedFlag::decode(value);
464 }
465
466
467 bool ScopeInfo::LocalIsSynthetic(int var) {
468 DCHECK(0 <= var && var < LocalCount());
469 // There's currently no flag stored on the ScopeInfo to indicate that a
470 // variable is a compiler-introduced temporary. However, to avoid conflict
471 // with user declarations, the current temporaries like .generator_object and
472 // .result start with a dot, so we can use that as a flag. It's a hack!
473 Handle<String> name(LocalName(var));
474 return (name->length() > 0 && name->Get(0) == '.') ||
475 name->Equals(*GetIsolate()->factory()->this_string());
476 }
477
478
479 String* ScopeInfo::StrongModeFreeVariableName(int var) {
480 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
481 int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
482 return String::cast(get(info_index));
483 }
484
485
486 int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
487 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
488 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
489 int32_t value = 0;
490 bool ok = get(info_index)->ToInt32(&value);
491 USE(ok);
492 DCHECK(ok);
493 return value;
494 }
495
496
497 int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
498 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
499 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
500 int32_t value = 0;
501 bool ok = get(info_index)->ToInt32(&value);
502 USE(ok);
503 DCHECK(ok);
504 return value;
505 }
506
507
508 int ScopeInfo::StackSlotIndex(String* name) {
509 DCHECK(name->IsInternalizedString());
510 if (length() > 0) {
511 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
512 int start = StackLocalEntriesIndex();
513 int end = StackLocalEntriesIndex() + StackLocalCount();
514 for (int i = start; i < end; ++i) {
515 if (name == get(i)) {
516 return i - start + first_slot_index;
517 }
518 }
519 }
520 return -1;
521 }
522
523
524 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
525 Handle<String> name, VariableMode* mode,
526 InitializationFlag* init_flag,
527 MaybeAssignedFlag* maybe_assigned_flag) {
528 DCHECK(name->IsInternalizedString());
529 DCHECK(mode != NULL);
530 DCHECK(init_flag != NULL);
531 if (scope_info->length() > 0) {
532 ContextSlotCache* context_slot_cache =
533 scope_info->GetIsolate()->context_slot_cache();
534 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
535 maybe_assigned_flag);
536 if (result != ContextSlotCache::kNotFound) {
537 DCHECK(result < scope_info->ContextLength());
538 return result;
539 }
540
541 int start = scope_info->ContextLocalNameEntriesIndex();
542 int end = scope_info->ContextLocalNameEntriesIndex() +
543 scope_info->ContextLocalCount();
544 for (int i = start; i < end; ++i) {
545 if (*name == scope_info->get(i)) {
546 int var = i - start;
547 *mode = scope_info->ContextLocalMode(var);
548 *init_flag = scope_info->ContextLocalInitFlag(var);
549 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
550 result = Context::MIN_CONTEXT_SLOTS + var;
551
552 context_slot_cache->Update(scope_info, name, *mode, *init_flag,
553 *maybe_assigned_flag, result);
554 DCHECK(result < scope_info->ContextLength());
555 return result;
556 }
557 }
558 // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
559 context_slot_cache->Update(scope_info, name, TEMPORARY,
560 kNeedsInitialization, kNotAssigned, -1);
561 }
562 return -1;
563 }
564
565
566 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info,
567 Handle<String> name, VariableMode* mode,
568 InitializationFlag* init_flag,
569 MaybeAssignedFlag* maybe_assigned_flag) {
570 DCHECK(name->IsInternalizedString());
571 DCHECK(mode != NULL);
572 DCHECK(init_flag != NULL);
573 if (scope_info->length() > 0) {
574 // This is to ensure that ContextLocalMode() and co. queries would work.
575 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
576 scope_info->ContextLocalNameEntriesIndex() +
577 scope_info->ContextLocalCount());
578 int base = scope_info->ContextLocalNameEntriesIndex();
579 int start = scope_info->ContextGlobalNameEntriesIndex();
580 int end = scope_info->ContextGlobalNameEntriesIndex() +
581 scope_info->ContextGlobalCount();
582 for (int i = start; i < end; ++i) {
583 if (*name == scope_info->get(i)) {
584 int var = i - base;
585 *mode = scope_info->ContextLocalMode(var);
586 *init_flag = scope_info->ContextLocalInitFlag(var);
587 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
588 int result = Context::MIN_CONTEXT_SLOTS + var;
589 DCHECK(result < scope_info->ContextLength());
590 return result;
591 }
592 }
593 }
594 return -1;
595 }
596
597
598 String* ScopeInfo::ContextSlotName(int slot_index) {
599 int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
600 DCHECK_LE(0, var);
601 DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount());
602 return ContextLocalName(var);
603 }
604
605
606 int ScopeInfo::ParameterIndex(String* name) {
607 DCHECK(name->IsInternalizedString());
608 if (length() > 0) {
609 // We must read parameters from the end since for
610 // multiply declared parameters the value of the
611 // last declaration of that parameter is used
612 // inside a function (and thus we need to look
613 // at the last index). Was bug# 1110337.
614 int start = ParameterEntriesIndex();
615 int end = ParameterEntriesIndex() + ParameterCount();
616 for (int i = end - 1; i >= start; --i) {
617 if (name == get(i)) {
618 return i - start;
619 }
620 }
621 }
622 return -1;
623 }
624
625
626 int ScopeInfo::ReceiverContextSlotIndex() {
627 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
628 return Smi::cast(get(ReceiverEntryIndex()))->value();
629 return -1;
630 }
631
632
633 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
634 DCHECK(name->IsInternalizedString());
635 DCHECK(mode != NULL);
636 if (length() > 0) {
637 if (FunctionVariableField::decode(Flags()) == CONTEXT &&
638 FunctionName() == name) {
639 *mode = FunctionVariableMode::decode(Flags());
640 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
641 }
642 }
643 return -1;
644 }
645
646
647 FunctionKind ScopeInfo::function_kind() {
648 return FunctionKindField::decode(Flags());
649 }
650
651
652 int ScopeInfo::ParameterEntriesIndex() {
653 DCHECK(length() > 0);
654 return kVariablePartIndex;
655 }
656
657
658 int ScopeInfo::StackLocalFirstSlotIndex() {
659 return ParameterEntriesIndex() + ParameterCount();
660 }
661
662
663 int ScopeInfo::StackLocalEntriesIndex() {
664 return StackLocalFirstSlotIndex() + 1;
665 }
666
667
668 int ScopeInfo::ContextLocalNameEntriesIndex() {
669 return StackLocalEntriesIndex() + StackLocalCount();
670 }
671
672
673 int ScopeInfo::ContextGlobalNameEntriesIndex() {
674 return ContextLocalNameEntriesIndex() + ContextLocalCount();
675 }
676
677
678 int ScopeInfo::ContextLocalInfoEntriesIndex() {
679 return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
680 }
681
682
683 int ScopeInfo::ContextGlobalInfoEntriesIndex() {
684 return ContextLocalInfoEntriesIndex() + ContextLocalCount();
685 }
686
687
688 int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
689 return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
690 }
691
692
693 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
694 return StrongModeFreeVariableNameEntriesIndex() +
695 StrongModeFreeVariableCount();
696 }
697
698
699 int ScopeInfo::ReceiverEntryIndex() {
700 return StrongModeFreeVariablePositionEntriesIndex() +
701 2 * StrongModeFreeVariableCount();
702 }
703
704
705 int ScopeInfo::FunctionNameEntryIndex() {
706 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0);
707 }
708
709
710 int ContextSlotCache::Hash(Object* data, String* name) {
711 // Uses only lower 32 bits if pointers are larger.
712 uintptr_t addr_hash =
713 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
714 return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
715 }
716
717
718 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
719 InitializationFlag* init_flag,
720 MaybeAssignedFlag* maybe_assigned_flag) {
721 int index = Hash(data, name);
722 Key& key = keys_[index];
723 if ((key.data == data) && key.name->Equals(name)) {
724 Value result(values_[index]);
725 if (mode != NULL) *mode = result.mode();
726 if (init_flag != NULL) *init_flag = result.initialization_flag();
727 if (maybe_assigned_flag != NULL)
728 *maybe_assigned_flag = result.maybe_assigned_flag();
729 return result.index() + kNotFound;
730 }
731 return kNotFound;
732 }
733
734
735 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
736 VariableMode mode, InitializationFlag init_flag,
737 MaybeAssignedFlag maybe_assigned_flag,
738 int slot_index) {
739 DisallowHeapAllocation no_gc;
740 Handle<String> internalized_name;
741 DCHECK(slot_index > kNotFound);
742 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
743 ToHandle(&internalized_name)) {
744 int index = Hash(*data, *internalized_name);
745 Key& key = keys_[index];
746 key.data = *data;
747 key.name = *internalized_name;
748 // Please note value only takes a uint as index.
749 values_[index] = Value(mode, init_flag, maybe_assigned_flag,
750 slot_index - kNotFound).raw();
751 #ifdef DEBUG
752 ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
753 #endif
754 }
755 }
756
757
758 void ContextSlotCache::Clear() {
759 for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
760 }
761
762
763 #ifdef DEBUG
764
765 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
766 VariableMode mode,
767 InitializationFlag init_flag,
768 MaybeAssignedFlag maybe_assigned_flag,
769 int slot_index) {
770 DisallowHeapAllocation no_gc;
771 Handle<String> internalized_name;
772 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
773 ToHandle(&internalized_name)) {
774 int index = Hash(*data, *name);
775 Key& key = keys_[index];
776 DCHECK(key.data == *data);
777 DCHECK(key.name->Equals(*name));
778 Value result(values_[index]);
779 DCHECK(result.mode() == mode);
780 DCHECK(result.initialization_flag() == init_flag);
781 DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
782 DCHECK(result.index() + kNotFound == slot_index);
783 }
784 }
785
786
787 static void PrintList(const char* list_name,
788 int nof_internal_slots,
789 int start,
790 int end,
791 ScopeInfo* scope_info) {
792 if (start < end) {
793 PrintF("\n // %s\n", list_name);
794 if (nof_internal_slots > 0) {
795 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
796 }
797 for (int i = nof_internal_slots; start < end; ++i, ++start) {
798 PrintF(" %2d ", i);
799 String::cast(scope_info->get(start))->ShortPrint();
800 PrintF("\n");
801 }
802 }
803 }
804
805
806 void ScopeInfo::Print() {
807 PrintF("ScopeInfo ");
808 if (HasFunctionName()) {
809 FunctionName()->ShortPrint();
810 } else {
811 PrintF("/* no function name */");
812 }
813 PrintF("{");
814
815 if (length() > 0) {
816 PrintList("parameters", 0, ParameterEntriesIndex(),
817 ParameterEntriesIndex() + ParameterCount(), this);
818 PrintList("stack slots", 0, StackLocalEntriesIndex(),
819 StackLocalEntriesIndex() + StackLocalCount(), this);
820 PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
821 ContextLocalNameEntriesIndex(),
822 ContextLocalNameEntriesIndex() + ContextLocalCount(), this);
823 }
824
825 PrintF("}\n");
826 }
827 #endif // DEBUG
828
829
830 //---------------------------------------------------------------------------
831 // ModuleInfo.
832
833 Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate,
834 ModuleDescriptor* descriptor,
835 Scope* scope) {
836 Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length());
837 info->set_host_index(descriptor->Index());
838 int i = 0;
839 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
840 it.Advance(), ++i) {
841 Variable* var = scope->LookupLocal(it.local_name());
842 info->set_name(i, *(it.export_name()->string()));
843 info->set_mode(i, var->mode());
844 DCHECK(var->index() >= 0);
845 info->set_index(i, var->index());
846 }
847 DCHECK(i == info->length());
848 return info;
849 }
850
851 } // namespace internal
852 } // namespace v8
OLDNEW
« no previous file with comments | « src/scopeinfo.h ('k') | src/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698