OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/scopeinfo.h" | 9 #include "src/scopeinfo.h" |
10 #include "src/scopes.h" | 10 #include "src/scopes.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 const int stack_local_count = stack_locals.length(); | 25 const int stack_local_count = stack_locals.length(); |
26 const int context_local_count = context_locals.length(); | 26 const int context_local_count = context_locals.length(); |
27 const int strong_mode_free_variable_count = | 27 const int strong_mode_free_variable_count = |
28 strong_mode_free_variables.length(); | 28 strong_mode_free_variables.length(); |
29 // Make sure we allocate the correct amount. | 29 // Make sure we allocate the correct amount. |
30 DCHECK(scope->ContextLocalCount() == context_local_count); | 30 DCHECK(scope->ContextLocalCount() == context_local_count); |
31 | 31 |
32 bool simple_parameter_list = | 32 bool simple_parameter_list = |
33 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; | 33 scope->is_function_scope() ? scope->is_simple_parameter_list() : true; |
34 | 34 |
| 35 // Determine use and location of the "this" binding if it is present. |
| 36 VariableAllocationInfo receiver_info; |
| 37 if (scope->has_this_declaration()) { |
| 38 Variable* var = scope->receiver(); |
| 39 if (!var->is_used()) { |
| 40 receiver_info = UNUSED; |
| 41 } else if (var->IsContextSlot()) { |
| 42 receiver_info = CONTEXT; |
| 43 } else { |
| 44 DCHECK(var->IsParameter()); |
| 45 receiver_info = STACK; |
| 46 } |
| 47 } else { |
| 48 receiver_info = NONE; |
| 49 } |
| 50 |
35 // Determine use and location of the function variable if it is present. | 51 // Determine use and location of the function variable if it is present. |
36 FunctionVariableInfo function_name_info; | 52 VariableAllocationInfo function_name_info; |
37 VariableMode function_variable_mode; | 53 VariableMode function_variable_mode; |
38 if (scope->is_function_scope() && scope->function() != NULL) { | 54 if (scope->is_function_scope() && scope->function() != NULL) { |
39 Variable* var = scope->function()->proxy()->var(); | 55 Variable* var = scope->function()->proxy()->var(); |
40 if (!var->is_used()) { | 56 if (!var->is_used()) { |
41 function_name_info = UNUSED; | 57 function_name_info = UNUSED; |
42 } else if (var->IsContextSlot()) { | 58 } else if (var->IsContextSlot()) { |
43 function_name_info = CONTEXT; | 59 function_name_info = CONTEXT; |
44 } else { | 60 } else { |
45 DCHECK(var->IsStackLocal()); | 61 DCHECK(var->IsStackLocal()); |
46 function_name_info = STACK; | 62 function_name_info = STACK; |
47 } | 63 } |
48 function_variable_mode = var->mode(); | 64 function_variable_mode = var->mode(); |
49 } else { | 65 } else { |
50 function_name_info = NONE; | 66 function_name_info = NONE; |
51 function_variable_mode = VAR; | 67 function_variable_mode = VAR; |
52 } | 68 } |
53 | 69 |
54 const bool has_function_name = function_name_info != NONE; | 70 const bool has_function_name = function_name_info != NONE; |
| 71 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; |
55 const int parameter_count = scope->num_parameters(); | 72 const int parameter_count = scope->num_parameters(); |
56 const int length = kVariablePartIndex + parameter_count + | 73 const int length = kVariablePartIndex + parameter_count + |
57 (1 + stack_local_count) + 2 * context_local_count + | 74 (1 + stack_local_count) + 2 * context_local_count + |
58 3 * strong_mode_free_variable_count + | 75 3 * strong_mode_free_variable_count + |
59 (has_function_name ? 2 : 0); | 76 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); |
60 | 77 |
61 Factory* factory = isolate->factory(); | 78 Factory* factory = isolate->factory(); |
62 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 79 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
63 | 80 |
64 // Encode the flags. | 81 // Encode the flags. |
65 int flags = ScopeTypeField::encode(scope->scope_type()) | | 82 int flags = ScopeTypeField::encode(scope->scope_type()) | |
66 CallsEvalField::encode(scope->calls_eval()) | | 83 CallsEvalField::encode(scope->calls_eval()) | |
67 LanguageModeField::encode(scope->language_mode()) | | 84 LanguageModeField::encode(scope->language_mode()) | |
| 85 ReceiverVariableField::encode(receiver_info) | |
68 FunctionVariableField::encode(function_name_info) | | 86 FunctionVariableField::encode(function_name_info) | |
69 FunctionVariableMode::encode(function_variable_mode) | | 87 FunctionVariableMode::encode(function_variable_mode) | |
70 AsmModuleField::encode(scope->asm_module()) | | 88 AsmModuleField::encode(scope->asm_module()) | |
71 AsmFunctionField::encode(scope->asm_function()) | | 89 AsmFunctionField::encode(scope->asm_function()) | |
72 IsSimpleParameterListField::encode(simple_parameter_list) | | 90 IsSimpleParameterListField::encode(simple_parameter_list) | |
73 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | | 91 BlockScopeIsClassScopeField::encode(scope->is_class_scope()) | |
74 FunctionKindField::encode(scope->function_kind()); | 92 FunctionKindField::encode(scope->function_kind()); |
75 scope_info->SetFlags(flags); | 93 scope_info->SetFlags(flags); |
76 scope_info->SetParameterCount(parameter_count); | 94 scope_info->SetParameterCount(parameter_count); |
77 scope_info->SetStackLocalCount(stack_local_count); | 95 scope_info->SetStackLocalCount(stack_local_count); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 Handle<Object> start_position = factory->NewNumberFromInt( | 157 Handle<Object> start_position = factory->NewNumberFromInt( |
140 static_cast<int32_t>(strong_mode_free_variables[i] | 158 static_cast<int32_t>(strong_mode_free_variables[i] |
141 ->strong_mode_reference_start_position())); | 159 ->strong_mode_reference_start_position())); |
142 scope_info->set(index++, *start_position); | 160 scope_info->set(index++, *start_position); |
143 Handle<Object> end_position = factory->NewNumberFromInt( | 161 Handle<Object> end_position = factory->NewNumberFromInt( |
144 static_cast<int32_t>(strong_mode_free_variables[i] | 162 static_cast<int32_t>(strong_mode_free_variables[i] |
145 ->strong_mode_reference_end_position())); | 163 ->strong_mode_reference_end_position())); |
146 scope_info->set(index++, *end_position); | 164 scope_info->set(index++, *end_position); |
147 } | 165 } |
148 | 166 |
| 167 // If the receiver is allocated, add its index. |
| 168 DCHECK(index == scope_info->ReceiverEntryIndex()); |
| 169 if (has_receiver) { |
| 170 int var_index = scope->receiver()->index(); |
| 171 scope_info->set(index++, Smi::FromInt(var_index)); |
| 172 // ?? DCHECK(receiver_info != CONTEXT || var_index == |
| 173 // scope_info->ContextLength() - 1); |
| 174 } |
| 175 |
149 // If present, add the function variable name and its index. | 176 // If present, add the function variable name and its index. |
150 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 177 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
151 if (has_function_name) { | 178 if (has_function_name) { |
152 int var_index = scope->function()->proxy()->var()->index(); | 179 int var_index = scope->function()->proxy()->var()->index(); |
153 scope_info->set(index++, *scope->function()->proxy()->name()); | 180 scope_info->set(index++, *scope->function()->proxy()->name()); |
154 scope_info->set(index++, Smi::FromInt(var_index)); | 181 scope_info->set(index++, Smi::FromInt(var_index)); |
155 DCHECK(function_name_info != CONTEXT || | 182 DCHECK(function_name_info != CONTEXT || |
156 var_index == scope_info->ContextLength() - 1); | 183 var_index == scope_info->ContextLength() - 1); |
157 } | 184 } |
158 | 185 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 scope_type() == MODULE_SCOPE; | 240 scope_type() == MODULE_SCOPE; |
214 if (has_context) { | 241 if (has_context) { |
215 return Context::MIN_CONTEXT_SLOTS + context_locals + | 242 return Context::MIN_CONTEXT_SLOTS + context_locals + |
216 (function_name_context_slot ? 1 : 0); | 243 (function_name_context_slot ? 1 : 0); |
217 } | 244 } |
218 } | 245 } |
219 return 0; | 246 return 0; |
220 } | 247 } |
221 | 248 |
222 | 249 |
| 250 bool ScopeInfo::HasReceiver() { |
| 251 if (length() > 0) { |
| 252 return NONE != ReceiverVariableField::decode(Flags()); |
| 253 } else { |
| 254 return false; |
| 255 } |
| 256 } |
| 257 |
| 258 |
| 259 bool ScopeInfo::HasAllocatedReceiver() { |
| 260 if (length() > 0) { |
| 261 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags()); |
| 262 return allocation == STACK || allocation == CONTEXT; |
| 263 } else { |
| 264 return false; |
| 265 } |
| 266 } |
| 267 |
| 268 |
223 bool ScopeInfo::HasFunctionName() { | 269 bool ScopeInfo::HasFunctionName() { |
224 if (length() > 0) { | 270 if (length() > 0) { |
225 return NONE != FunctionVariableField::decode(Flags()); | 271 return NONE != FunctionVariableField::decode(Flags()); |
226 } else { | 272 } else { |
227 return false; | 273 return false; |
228 } | 274 } |
229 } | 275 } |
230 | 276 |
231 | 277 |
232 bool ScopeInfo::HasHeapAllocatedLocals() { | 278 bool ScopeInfo::HasHeapAllocatedLocals() { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 } | 356 } |
311 | 357 |
312 | 358 |
313 bool ScopeInfo::LocalIsSynthetic(int var) { | 359 bool ScopeInfo::LocalIsSynthetic(int var) { |
314 DCHECK(0 <= var && var < LocalCount()); | 360 DCHECK(0 <= var && var < LocalCount()); |
315 // There's currently no flag stored on the ScopeInfo to indicate that a | 361 // There's currently no flag stored on the ScopeInfo to indicate that a |
316 // variable is a compiler-introduced temporary. However, to avoid conflict | 362 // variable is a compiler-introduced temporary. However, to avoid conflict |
317 // with user declarations, the current temporaries like .generator_object and | 363 // with user declarations, the current temporaries like .generator_object and |
318 // .result start with a dot, so we can use that as a flag. It's a hack! | 364 // .result start with a dot, so we can use that as a flag. It's a hack! |
319 Handle<String> name(LocalName(var)); | 365 Handle<String> name(LocalName(var)); |
320 return name->length() > 0 && name->Get(0) == '.'; | 366 return (name->length() > 0 && name->Get(0) == '.') || |
| 367 name->Equals(*GetIsolate()->factory()->this_string()); |
321 } | 368 } |
322 | 369 |
323 | 370 |
324 String* ScopeInfo::StrongModeFreeVariableName(int var) { | 371 String* ScopeInfo::StrongModeFreeVariableName(int var) { |
325 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); | 372 DCHECK(0 <= var && var < StrongModeFreeVariableCount()); |
326 int info_index = StrongModeFreeVariableNameEntriesIndex() + var; | 373 int info_index = StrongModeFreeVariableNameEntriesIndex() + var; |
327 return String::cast(get(info_index)); | 374 return String::cast(get(info_index)); |
328 } | 375 } |
329 | 376 |
330 | 377 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 for (int i = end - 1; i >= start; --i) { | 467 for (int i = end - 1; i >= start; --i) { |
421 if (name == get(i)) { | 468 if (name == get(i)) { |
422 return i - start; | 469 return i - start; |
423 } | 470 } |
424 } | 471 } |
425 } | 472 } |
426 return -1; | 473 return -1; |
427 } | 474 } |
428 | 475 |
429 | 476 |
| 477 int ScopeInfo::ReceiverContextSlotIndex() { |
| 478 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) |
| 479 return Smi::cast(get(ReceiverEntryIndex()))->value(); |
| 480 return -1; |
| 481 } |
| 482 |
| 483 |
430 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { | 484 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { |
431 DCHECK(name->IsInternalizedString()); | 485 DCHECK(name->IsInternalizedString()); |
432 DCHECK(mode != NULL); | 486 DCHECK(mode != NULL); |
433 if (length() > 0) { | 487 if (length() > 0) { |
434 if (FunctionVariableField::decode(Flags()) == CONTEXT && | 488 if (FunctionVariableField::decode(Flags()) == CONTEXT && |
435 FunctionName() == name) { | 489 FunctionName() == name) { |
436 *mode = FunctionVariableMode::decode(Flags()); | 490 *mode = FunctionVariableMode::decode(Flags()); |
437 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); | 491 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); |
438 } | 492 } |
439 } | 493 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); | 561 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); |
508 } | 562 } |
509 | 563 |
510 | 564 |
511 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() { | 565 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() { |
512 return StrongModeFreeVariableNameEntriesIndex() + | 566 return StrongModeFreeVariableNameEntriesIndex() + |
513 StrongModeFreeVariableCount(); | 567 StrongModeFreeVariableCount(); |
514 } | 568 } |
515 | 569 |
516 | 570 |
| 571 int ScopeInfo::ReceiverEntryIndex() { |
| 572 return StrongModeFreeVariablePositionEntriesIndex() + |
| 573 2 * StrongModeFreeVariableCount(); |
| 574 } |
| 575 |
| 576 |
517 int ScopeInfo::FunctionNameEntryIndex() { | 577 int ScopeInfo::FunctionNameEntryIndex() { |
518 return StrongModeFreeVariablePositionEntriesIndex() + | 578 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0); |
519 2 * StrongModeFreeVariableCount(); | |
520 } | 579 } |
521 | 580 |
522 | 581 |
523 int ContextSlotCache::Hash(Object* data, String* name) { | 582 int ContextSlotCache::Hash(Object* data, String* name) { |
524 // Uses only lower 32 bits if pointers are larger. | 583 // Uses only lower 32 bits if pointers are larger. |
525 uintptr_t addr_hash = | 584 uintptr_t addr_hash = |
526 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; | 585 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; |
527 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); | 586 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); |
528 } | 587 } |
529 | 588 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 info->set_name(i, *(it.export_name()->string())); | 718 info->set_name(i, *(it.export_name()->string())); |
660 info->set_mode(i, var->mode()); | 719 info->set_mode(i, var->mode()); |
661 DCHECK(var->index() >= 0); | 720 DCHECK(var->index() >= 0); |
662 info->set_index(i, var->index()); | 721 info->set_index(i, var->index()); |
663 } | 722 } |
664 DCHECK(i == info->length()); | 723 DCHECK(i == info->length()); |
665 return info; | 724 return info; |
666 } | 725 } |
667 | 726 |
668 } } // namespace v8::internal | 727 } } // namespace v8::internal |
OLD | NEW |