| 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/ast/context-slot-cache.h" | 7 #include "src/ast/context-slot-cache.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 | 13 |
| 14 | 14 |
| 15 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, | 15 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
| 16 Scope* scope) { | 16 Scope* scope) { |
| 17 // Collect variables. | 17 // Collect variables. |
| 18 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone); | 18 ZoneList<Variable*>* locals = scope->locals(); |
| 19 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone); | 19 int stack_local_count = 0; |
| 20 ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone); | 20 int context_local_count = 0; |
| 21 scope->CollectVariables(&stack_locals, &context_locals, &context_globals); | 21 // Stack allocated block scope variables are allocated in the parent |
| 22 const int stack_local_count = stack_locals.length(); | 22 // declaration scope, but are recorded in the block scope's scope info. First |
| 23 const int context_local_count = context_locals.length(); | 23 // slot index indicates at which offset a particular scope starts in the |
| 24 const int context_global_count = context_globals.length(); | 24 // parent declaration scope. |
| 25 int first_slot_index = 0; |
| 26 for (int i = 0; i < locals->length(); i++) { |
| 27 Variable* var = locals->at(i); |
| 28 if (var->IsStackLocal()) { |
| 29 if (stack_local_count == 0) first_slot_index = var->index(); |
| 30 stack_local_count++; |
| 31 } else if (var->IsContextSlot()) { |
| 32 context_local_count++; |
| 33 } |
| 34 } |
| 35 |
| 25 // Make sure we allocate the correct amount. | 36 // Make sure we allocate the correct amount. |
| 26 DCHECK_EQ(scope->ContextLocalCount(), context_local_count); | 37 DCHECK_EQ(scope->ContextLocalCount(), context_local_count); |
| 27 DCHECK_EQ(scope->ContextGlobalCount(), context_global_count); | |
| 28 | 38 |
| 29 // Determine use and location of the "this" binding if it is present. | 39 // Determine use and location of the "this" binding if it is present. |
| 30 VariableAllocationInfo receiver_info; | 40 VariableAllocationInfo receiver_info; |
| 31 if (scope->is_declaration_scope() && | 41 if (scope->is_declaration_scope() && |
| 32 scope->AsDeclarationScope()->has_this_declaration()) { | 42 scope->AsDeclarationScope()->has_this_declaration()) { |
| 33 Variable* var = scope->AsDeclarationScope()->receiver(); | 43 Variable* var = scope->AsDeclarationScope()->receiver(); |
| 34 if (!var->is_used()) { | 44 if (!var->is_used()) { |
| 35 receiver_info = UNUSED; | 45 receiver_info = UNUSED; |
| 36 } else if (var->IsContextSlot()) { | 46 } else if (var->IsContextSlot()) { |
| 37 receiver_info = CONTEXT; | 47 receiver_info = CONTEXT; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 59 function_name_info = CONTEXT; | 69 function_name_info = CONTEXT; |
| 60 } else { | 70 } else { |
| 61 DCHECK(var->IsStackLocal()); | 71 DCHECK(var->IsStackLocal()); |
| 62 function_name_info = STACK; | 72 function_name_info = STACK; |
| 63 } | 73 } |
| 64 function_variable_mode = var->mode(); | 74 function_variable_mode = var->mode(); |
| 65 } else { | 75 } else { |
| 66 function_name_info = NONE; | 76 function_name_info = NONE; |
| 67 function_variable_mode = VAR; | 77 function_variable_mode = VAR; |
| 68 } | 78 } |
| 69 DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE); | |
| 70 | 79 |
| 71 const bool has_function_name = function_name_info != NONE; | 80 const bool has_function_name = function_name_info != NONE; |
| 72 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; | 81 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; |
| 73 const int parameter_count = scope->num_parameters(); | 82 const int parameter_count = scope->num_parameters(); |
| 74 const int length = kVariablePartIndex + parameter_count + | 83 const int length = kVariablePartIndex + parameter_count + |
| 75 (1 + stack_local_count) + 2 * context_local_count + | 84 (1 + stack_local_count) + 2 * context_local_count + |
| 76 2 * context_global_count + | |
| 77 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); | 85 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); |
| 78 | 86 |
| 79 Factory* factory = isolate->factory(); | 87 Factory* factory = isolate->factory(); |
| 80 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 88 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
| 81 | 89 |
| 82 bool has_simple_parameters = false; | 90 bool has_simple_parameters = false; |
| 83 bool asm_module = false; | 91 bool asm_module = false; |
| 84 bool asm_function = false; | 92 bool asm_function = false; |
| 85 FunctionKind function_kind = kNormalFunction; | 93 FunctionKind function_kind = kNormalFunction; |
| 86 if (scope->is_function_scope()) { | 94 if (scope->is_function_scope()) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 101 FunctionVariableField::encode(function_name_info) | | 109 FunctionVariableField::encode(function_name_info) | |
| 102 FunctionVariableMode::encode(function_variable_mode) | | 110 FunctionVariableMode::encode(function_variable_mode) | |
| 103 AsmModuleField::encode(asm_module) | | 111 AsmModuleField::encode(asm_module) | |
| 104 AsmFunctionField::encode(asm_function) | | 112 AsmFunctionField::encode(asm_function) | |
| 105 HasSimpleParametersField::encode(has_simple_parameters) | | 113 HasSimpleParametersField::encode(has_simple_parameters) | |
| 106 FunctionKindField::encode(function_kind); | 114 FunctionKindField::encode(function_kind); |
| 107 scope_info->SetFlags(flags); | 115 scope_info->SetFlags(flags); |
| 108 scope_info->SetParameterCount(parameter_count); | 116 scope_info->SetParameterCount(parameter_count); |
| 109 scope_info->SetStackLocalCount(stack_local_count); | 117 scope_info->SetStackLocalCount(stack_local_count); |
| 110 scope_info->SetContextLocalCount(context_local_count); | 118 scope_info->SetContextLocalCount(context_local_count); |
| 111 scope_info->SetContextGlobalCount(context_global_count); | |
| 112 | 119 |
| 113 int index = kVariablePartIndex; | 120 int index = kVariablePartIndex; |
| 114 // Add parameters. | 121 // Add parameters. |
| 115 DCHECK_EQ(index, scope_info->ParameterEntriesIndex()); | 122 DCHECK_EQ(index, scope_info->ParameterEntriesIndex()); |
| 116 if (scope->is_declaration_scope()) { | 123 if (scope->is_declaration_scope()) { |
| 117 for (int i = 0; i < parameter_count; ++i) { | 124 for (int i = 0; i < parameter_count; ++i) { |
| 118 scope_info->set(index++, | 125 scope_info->set(index++, |
| 119 *scope->AsDeclarationScope()->parameter(i)->name()); | 126 *scope->AsDeclarationScope()->parameter(i)->name()); |
| 120 } | 127 } |
| 121 } | 128 } |
| 122 | 129 |
| 123 // Add stack locals' names. We are assuming that the stack locals' | 130 // Add stack locals' names, context locals' names and info. We are assuming |
| 124 // slots are allocated in increasing order, so we can simply add | 131 // that the stack locals' slots are allocated in increasing order, so we can |
| 125 // them to the ScopeInfo object. | 132 // simply add them to the ScopeInfo object. Context locals are added using |
| 126 int first_slot_index; | 133 // their index. |
| 127 if (stack_local_count > 0) { | |
| 128 first_slot_index = stack_locals[0]->index(); | |
| 129 } else { | |
| 130 first_slot_index = 0; | |
| 131 } | |
| 132 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); | 134 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); |
| 133 scope_info->set(index++, Smi::FromInt(first_slot_index)); | 135 scope_info->set(index++, Smi::FromInt(first_slot_index)); |
| 134 DCHECK_EQ(index, scope_info->StackLocalEntriesIndex()); | 136 DCHECK_EQ(index, scope_info->StackLocalEntriesIndex()); |
| 135 for (int i = 0; i < stack_local_count; ++i) { | 137 |
| 136 DCHECK(stack_locals[i]->index() == first_slot_index + i); | 138 int stack_local_base = index; |
| 137 scope_info->set(index++, *stack_locals[i]->name()); | 139 int context_local_base = stack_local_base + stack_local_count; |
| 140 int context_local_info_base = context_local_base + context_local_count; |
| 141 |
| 142 for (int i = 0; i < locals->length(); ++i) { |
| 143 Variable* var = locals->at(i); |
| 144 if (var->IsStackLocal()) { |
| 145 int local_index = var->index() - first_slot_index; |
| 146 DCHECK_LE(0, local_index); |
| 147 DCHECK_LT(local_index, stack_local_count); |
| 148 scope_info->set(stack_local_base + local_index, *var->name()); |
| 149 } else if (var->IsContextSlot()) { |
| 150 // Due to duplicate parameters, context locals aren't guaranteed to come |
| 151 // in order. |
| 152 int local_index = var->index() - Context::MIN_CONTEXT_SLOTS; |
| 153 DCHECK_LE(0, local_index); |
| 154 DCHECK_LT(local_index, context_local_count); |
| 155 uint32_t info = VariableModeField::encode(var->mode()) | |
| 156 InitFlagField::encode(var->initialization_flag()) | |
| 157 MaybeAssignedFlagField::encode(var->maybe_assigned()); |
| 158 scope_info->set(context_local_base + local_index, *var->name()); |
| 159 scope_info->set(context_local_info_base + local_index, |
| 160 Smi::FromInt(info)); |
| 161 } |
| 138 } | 162 } |
| 139 | 163 |
| 140 // Add context locals' names and info. Info lies beyond context globals' | 164 index += stack_local_count + 2 * context_local_count; |
| 141 // names. | |
| 142 // Make sure to store them in the order that they appear in the context. | |
| 143 DCHECK_EQ(index, scope_info->ContextLocalNameEntriesIndex()); | |
| 144 int info_index = index + context_local_count + context_global_count; | |
| 145 DCHECK_EQ(info_index, scope_info->ContextLocalInfoEntriesIndex()); | |
| 146 for (int i = 0; i < context_local_count; ++i) { | |
| 147 Variable* var = context_locals[i]; | |
| 148 int context_index = var->index() - Context::MIN_CONTEXT_SLOTS; | |
| 149 uint32_t info = VariableModeField::encode(var->mode()) | | |
| 150 InitFlagField::encode(var->initialization_flag()) | | |
| 151 MaybeAssignedFlagField::encode(var->maybe_assigned()); | |
| 152 scope_info->set(index + context_index, *var->name()); | |
| 153 scope_info->set(info_index + context_index, Smi::FromInt(info)); | |
| 154 } | |
| 155 | |
| 156 index += context_local_count; | |
| 157 | |
| 158 // Add context globals' names and info. Info lies beyond context locals' info. | |
| 159 DCHECK_EQ(index, scope_info->ContextGlobalNameEntriesIndex()); | |
| 160 info_index = index + context_global_count + context_local_count; | |
| 161 DCHECK_EQ(info_index, scope_info->ContextGlobalInfoEntriesIndex()); | |
| 162 for (int i = 0; i < context_global_count; ++i) { | |
| 163 Variable* var = context_globals[i]; | |
| 164 scope_info->set(index + i, *var->name()); | |
| 165 // TODO(ishell): do we need this kind of info for globals here? | |
| 166 uint32_t info = VariableModeField::encode(var->mode()) | | |
| 167 InitFlagField::encode(var->initialization_flag()) | | |
| 168 MaybeAssignedFlagField::encode(var->maybe_assigned()); | |
| 169 scope_info->set(info_index + i, Smi::FromInt(info)); | |
| 170 } | |
| 171 | |
| 172 index += context_local_count + 2 * context_global_count; | |
| 173 | 165 |
| 174 // If the receiver is allocated, add its index. | 166 // If the receiver is allocated, add its index. |
| 175 DCHECK(index == scope_info->ReceiverEntryIndex()); | 167 DCHECK_EQ(index, scope_info->ReceiverEntryIndex()); |
| 176 if (has_receiver) { | 168 if (has_receiver) { |
| 177 int var_index = scope->AsDeclarationScope()->receiver()->index(); | 169 int var_index = scope->AsDeclarationScope()->receiver()->index(); |
| 178 scope_info->set(index++, Smi::FromInt(var_index)); | 170 scope_info->set(index++, Smi::FromInt(var_index)); |
| 179 // ?? DCHECK(receiver_info != CONTEXT || var_index == | 171 // ?? DCHECK(receiver_info != CONTEXT || var_index == |
| 180 // scope_info->ContextLength() - 1); | 172 // scope_info->ContextLength() - 1); |
| 181 } | 173 } |
| 182 | 174 |
| 183 // If present, add the function variable name and its index. | 175 // If present, add the function variable name and its index. |
| 184 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 176 DCHECK_EQ(index, scope_info->FunctionNameEntryIndex()); |
| 185 if (has_function_name) { | 177 if (has_function_name) { |
| 186 int var_index = scope->AsDeclarationScope()->function_var()->index(); | 178 int var_index = scope->AsDeclarationScope()->function_var()->index(); |
| 187 scope_info->set(index++, | 179 scope_info->set(index++, |
| 188 *scope->AsDeclarationScope()->function_var()->name()); | 180 *scope->AsDeclarationScope()->function_var()->name()); |
| 189 scope_info->set(index++, Smi::FromInt(var_index)); | 181 scope_info->set(index++, Smi::FromInt(var_index)); |
| 190 DCHECK(function_name_info != CONTEXT || | 182 DCHECK(function_name_info != CONTEXT || |
| 191 var_index == scope_info->ContextLength() - 1); | 183 var_index == scope_info->ContextLength() - 1); |
| 192 } | 184 } |
| 193 | 185 |
| 194 DCHECK(index == scope_info->length()); | 186 DCHECK_EQ(index, scope_info->length()); |
| 195 DCHECK(scope->num_parameters() == scope_info->ParameterCount()); | 187 DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount()); |
| 196 DCHECK(scope->num_heap_slots() == scope_info->ContextLength()); | 188 DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength()); |
| 197 return scope_info; | 189 return scope_info; |
| 198 } | 190 } |
| 199 | 191 |
| 200 | 192 |
| 201 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { | 193 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { |
| 202 DCHECK(isolate->bootstrapper()->IsActive()); | 194 DCHECK(isolate->bootstrapper()->IsActive()); |
| 203 | 195 |
| 204 const int stack_local_count = 0; | 196 const int stack_local_count = 0; |
| 205 const int context_local_count = 1; | 197 const int context_local_count = 1; |
| 206 const int context_global_count = 0; | |
| 207 const bool has_simple_parameters = true; | 198 const bool has_simple_parameters = true; |
| 208 const VariableAllocationInfo receiver_info = CONTEXT; | 199 const VariableAllocationInfo receiver_info = CONTEXT; |
| 209 const VariableAllocationInfo function_name_info = NONE; | 200 const VariableAllocationInfo function_name_info = NONE; |
| 210 const VariableMode function_variable_mode = VAR; | 201 const VariableMode function_variable_mode = VAR; |
| 211 const bool has_function_name = false; | 202 const bool has_function_name = false; |
| 212 const bool has_receiver = true; | 203 const bool has_receiver = true; |
| 213 const int parameter_count = 0; | 204 const int parameter_count = 0; |
| 214 const int length = kVariablePartIndex + parameter_count + | 205 const int length = kVariablePartIndex + parameter_count + |
| 215 (1 + stack_local_count) + 2 * context_local_count + | 206 (1 + stack_local_count) + 2 * context_local_count + |
| 216 2 * context_global_count + | |
| 217 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); | 207 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); |
| 218 | 208 |
| 219 Factory* factory = isolate->factory(); | 209 Factory* factory = isolate->factory(); |
| 220 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); | 210 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
| 221 | 211 |
| 222 // Encode the flags. | 212 // Encode the flags. |
| 223 int flags = ScopeTypeField::encode(SCRIPT_SCOPE) | | 213 int flags = ScopeTypeField::encode(SCRIPT_SCOPE) | |
| 224 CallsEvalField::encode(false) | | 214 CallsEvalField::encode(false) | |
| 225 LanguageModeField::encode(SLOPPY) | | 215 LanguageModeField::encode(SLOPPY) | |
| 226 DeclarationScopeField::encode(true) | | 216 DeclarationScopeField::encode(true) | |
| 227 ReceiverVariableField::encode(receiver_info) | | 217 ReceiverVariableField::encode(receiver_info) | |
| 228 FunctionVariableField::encode(function_name_info) | | 218 FunctionVariableField::encode(function_name_info) | |
| 229 FunctionVariableMode::encode(function_variable_mode) | | 219 FunctionVariableMode::encode(function_variable_mode) | |
| 230 AsmModuleField::encode(false) | AsmFunctionField::encode(false) | | 220 AsmModuleField::encode(false) | AsmFunctionField::encode(false) | |
| 231 HasSimpleParametersField::encode(has_simple_parameters) | | 221 HasSimpleParametersField::encode(has_simple_parameters) | |
| 232 FunctionKindField::encode(FunctionKind::kNormalFunction); | 222 FunctionKindField::encode(FunctionKind::kNormalFunction); |
| 233 scope_info->SetFlags(flags); | 223 scope_info->SetFlags(flags); |
| 234 scope_info->SetParameterCount(parameter_count); | 224 scope_info->SetParameterCount(parameter_count); |
| 235 scope_info->SetStackLocalCount(stack_local_count); | 225 scope_info->SetStackLocalCount(stack_local_count); |
| 236 scope_info->SetContextLocalCount(context_local_count); | 226 scope_info->SetContextLocalCount(context_local_count); |
| 237 scope_info->SetContextGlobalCount(context_global_count); | |
| 238 | 227 |
| 239 int index = kVariablePartIndex; | 228 int index = kVariablePartIndex; |
| 240 const int first_slot_index = 0; | 229 const int first_slot_index = 0; |
| 241 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); | 230 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); |
| 242 scope_info->set(index++, Smi::FromInt(first_slot_index)); | 231 scope_info->set(index++, Smi::FromInt(first_slot_index)); |
| 243 DCHECK(index == scope_info->StackLocalEntriesIndex()); | 232 DCHECK_EQ(index, scope_info->StackLocalEntriesIndex()); |
| 244 | 233 |
| 245 // Here we add info for context-allocated "this". | 234 // Here we add info for context-allocated "this". |
| 246 DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); | 235 DCHECK_EQ(index, scope_info->ContextLocalNameEntriesIndex()); |
| 247 scope_info->set(index++, *isolate->factory()->this_string()); | 236 scope_info->set(index++, *isolate->factory()->this_string()); |
| 248 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); | 237 DCHECK_EQ(index, scope_info->ContextLocalInfoEntriesIndex()); |
| 249 const uint32_t value = VariableModeField::encode(CONST) | | 238 const uint32_t value = VariableModeField::encode(CONST) | |
| 250 InitFlagField::encode(kCreatedInitialized) | | 239 InitFlagField::encode(kCreatedInitialized) | |
| 251 MaybeAssignedFlagField::encode(kNotAssigned); | 240 MaybeAssignedFlagField::encode(kNotAssigned); |
| 252 scope_info->set(index++, Smi::FromInt(value)); | 241 scope_info->set(index++, Smi::FromInt(value)); |
| 253 | 242 |
| 254 // And here we record that this scopeinfo binds a receiver. | 243 // And here we record that this scopeinfo binds a receiver. |
| 255 DCHECK(index == scope_info->ReceiverEntryIndex()); | 244 DCHECK_EQ(index, scope_info->ReceiverEntryIndex()); |
| 256 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; | 245 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; |
| 257 scope_info->set(index++, Smi::FromInt(receiver_index)); | 246 scope_info->set(index++, Smi::FromInt(receiver_index)); |
| 258 | 247 |
| 259 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 248 DCHECK_EQ(index, scope_info->FunctionNameEntryIndex()); |
| 260 | 249 |
| 261 DCHECK_EQ(index, scope_info->length()); | 250 DCHECK_EQ(index, scope_info->length()); |
| 262 DCHECK_EQ(scope_info->ParameterCount(), 0); | 251 DCHECK_EQ(scope_info->ParameterCount(), 0); |
| 263 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1); | 252 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1); |
| 264 | 253 |
| 265 return scope_info; | 254 return scope_info; |
| 266 } | 255 } |
| 267 | 256 |
| 268 | 257 |
| 269 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { | 258 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { |
| 270 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); | 259 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); |
| 271 } | 260 } |
| 272 | 261 |
| 273 | 262 |
| 274 ScopeType ScopeInfo::scope_type() { | 263 ScopeType ScopeInfo::scope_type() { |
| 275 DCHECK(length() > 0); | 264 DCHECK_LT(0, length()); |
| 276 return ScopeTypeField::decode(Flags()); | 265 return ScopeTypeField::decode(Flags()); |
| 277 } | 266 } |
| 278 | 267 |
| 279 | 268 |
| 280 bool ScopeInfo::CallsEval() { | 269 bool ScopeInfo::CallsEval() { |
| 281 return length() > 0 && CallsEvalField::decode(Flags()); | 270 return length() > 0 && CallsEvalField::decode(Flags()); |
| 282 } | 271 } |
| 283 | 272 |
| 284 | 273 |
| 285 LanguageMode ScopeInfo::language_mode() { | 274 LanguageMode ScopeInfo::language_mode() { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 303 FunctionVariableField::decode(Flags()) == STACK; | 292 FunctionVariableField::decode(Flags()) == STACK; |
| 304 return StackLocalCount() + (function_name_stack_slot ? 1 : 0); | 293 return StackLocalCount() + (function_name_stack_slot ? 1 : 0); |
| 305 } | 294 } |
| 306 return 0; | 295 return 0; |
| 307 } | 296 } |
| 308 | 297 |
| 309 | 298 |
| 310 int ScopeInfo::ContextLength() { | 299 int ScopeInfo::ContextLength() { |
| 311 if (length() > 0) { | 300 if (length() > 0) { |
| 312 int context_locals = ContextLocalCount(); | 301 int context_locals = ContextLocalCount(); |
| 313 int context_globals = ContextGlobalCount(); | |
| 314 bool function_name_context_slot = | 302 bool function_name_context_slot = |
| 315 FunctionVariableField::decode(Flags()) == CONTEXT; | 303 FunctionVariableField::decode(Flags()) == CONTEXT; |
| 316 bool has_context = context_locals > 0 || context_globals > 0 || | 304 bool has_context = context_locals > 0 || function_name_context_slot || |
| 317 function_name_context_slot || | |
| 318 scope_type() == WITH_SCOPE || | 305 scope_type() == WITH_SCOPE || |
| 319 (scope_type() == BLOCK_SCOPE && CallsSloppyEval() && | 306 (scope_type() == BLOCK_SCOPE && CallsSloppyEval() && |
| 320 is_declaration_scope()) || | 307 is_declaration_scope()) || |
| 321 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) || | 308 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) || |
| 322 scope_type() == MODULE_SCOPE; | 309 scope_type() == MODULE_SCOPE; |
| 323 | 310 |
| 324 if (has_context) { | 311 if (has_context) { |
| 325 return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals + | 312 return Context::MIN_CONTEXT_SLOTS + context_locals + |
| 326 (function_name_context_slot ? 1 : 0); | 313 (function_name_context_slot ? 1 : 0); |
| 327 } | 314 } |
| 328 } | 315 } |
| 329 return 0; | 316 return 0; |
| 330 } | 317 } |
| 331 | 318 |
| 332 | 319 |
| 333 bool ScopeInfo::HasReceiver() { | 320 bool ScopeInfo::HasReceiver() { |
| 334 if (length() > 0) { | 321 if (length() > 0) { |
| 335 return NONE != ReceiverVariableField::decode(Flags()); | 322 return NONE != ReceiverVariableField::decode(Flags()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 } | 362 } |
| 376 | 363 |
| 377 | 364 |
| 378 String* ScopeInfo::FunctionName() { | 365 String* ScopeInfo::FunctionName() { |
| 379 DCHECK(HasFunctionName()); | 366 DCHECK(HasFunctionName()); |
| 380 return String::cast(get(FunctionNameEntryIndex())); | 367 return String::cast(get(FunctionNameEntryIndex())); |
| 381 } | 368 } |
| 382 | 369 |
| 383 | 370 |
| 384 String* ScopeInfo::ParameterName(int var) { | 371 String* ScopeInfo::ParameterName(int var) { |
| 385 DCHECK(0 <= var && var < ParameterCount()); | 372 DCHECK_LE(0, var); |
| 373 DCHECK_LT(var, ParameterCount()); |
| 386 int info_index = ParameterEntriesIndex() + var; | 374 int info_index = ParameterEntriesIndex() + var; |
| 387 return String::cast(get(info_index)); | 375 return String::cast(get(info_index)); |
| 388 } | 376 } |
| 389 | 377 |
| 390 | 378 |
| 391 String* ScopeInfo::LocalName(int var) { | 379 String* ScopeInfo::LocalName(int var) { |
| 392 DCHECK(0 <= var && var < LocalCount()); | 380 DCHECK_LE(0, var); |
| 381 DCHECK_LT(var, LocalCount()); |
| 393 DCHECK(StackLocalEntriesIndex() + StackLocalCount() == | 382 DCHECK(StackLocalEntriesIndex() + StackLocalCount() == |
| 394 ContextLocalNameEntriesIndex()); | 383 ContextLocalNameEntriesIndex()); |
| 395 int info_index = StackLocalEntriesIndex() + var; | 384 int info_index = StackLocalEntriesIndex() + var; |
| 396 return String::cast(get(info_index)); | 385 return String::cast(get(info_index)); |
| 397 } | 386 } |
| 398 | 387 |
| 399 | 388 |
| 400 String* ScopeInfo::StackLocalName(int var) { | 389 String* ScopeInfo::StackLocalName(int var) { |
| 401 DCHECK(0 <= var && var < StackLocalCount()); | 390 DCHECK_LE(0, var); |
| 391 DCHECK_LT(var, StackLocalCount()); |
| 402 int info_index = StackLocalEntriesIndex() + var; | 392 int info_index = StackLocalEntriesIndex() + var; |
| 403 return String::cast(get(info_index)); | 393 return String::cast(get(info_index)); |
| 404 } | 394 } |
| 405 | 395 |
| 406 | 396 |
| 407 int ScopeInfo::StackLocalIndex(int var) { | 397 int ScopeInfo::StackLocalIndex(int var) { |
| 408 DCHECK(0 <= var && var < StackLocalCount()); | 398 DCHECK_LE(0, var); |
| 399 DCHECK_LT(var, StackLocalCount()); |
| 409 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); | 400 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); |
| 410 return first_slot_index + var; | 401 return first_slot_index + var; |
| 411 } | 402 } |
| 412 | 403 |
| 413 | 404 |
| 414 String* ScopeInfo::ContextLocalName(int var) { | 405 String* ScopeInfo::ContextLocalName(int var) { |
| 415 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 406 DCHECK_LE(0, var); |
| 407 DCHECK_LT(var, ContextLocalCount()); |
| 416 int info_index = ContextLocalNameEntriesIndex() + var; | 408 int info_index = ContextLocalNameEntriesIndex() + var; |
| 417 return String::cast(get(info_index)); | 409 return String::cast(get(info_index)); |
| 418 } | 410 } |
| 419 | 411 |
| 420 | 412 |
| 421 VariableMode ScopeInfo::ContextLocalMode(int var) { | 413 VariableMode ScopeInfo::ContextLocalMode(int var) { |
| 422 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 414 DCHECK_LE(0, var); |
| 415 DCHECK_LT(var, ContextLocalCount()); |
| 423 int info_index = ContextLocalInfoEntriesIndex() + var; | 416 int info_index = ContextLocalInfoEntriesIndex() + var; |
| 424 int value = Smi::cast(get(info_index))->value(); | 417 int value = Smi::cast(get(info_index))->value(); |
| 425 return VariableModeField::decode(value); | 418 return VariableModeField::decode(value); |
| 426 } | 419 } |
| 427 | 420 |
| 428 | 421 |
| 429 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { | 422 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { |
| 430 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 423 DCHECK_LE(0, var); |
| 424 DCHECK_LT(var, ContextLocalCount()); |
| 431 int info_index = ContextLocalInfoEntriesIndex() + var; | 425 int info_index = ContextLocalInfoEntriesIndex() + var; |
| 432 int value = Smi::cast(get(info_index))->value(); | 426 int value = Smi::cast(get(info_index))->value(); |
| 433 return InitFlagField::decode(value); | 427 return InitFlagField::decode(value); |
| 434 } | 428 } |
| 435 | 429 |
| 436 | 430 |
| 437 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { | 431 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { |
| 438 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 432 DCHECK_LE(0, var); |
| 433 DCHECK_LT(var, ContextLocalCount()); |
| 439 int info_index = ContextLocalInfoEntriesIndex() + var; | 434 int info_index = ContextLocalInfoEntriesIndex() + var; |
| 440 int value = Smi::cast(get(info_index))->value(); | 435 int value = Smi::cast(get(info_index))->value(); |
| 441 return MaybeAssignedFlagField::decode(value); | 436 return MaybeAssignedFlagField::decode(value); |
| 442 } | 437 } |
| 443 | 438 |
| 444 bool ScopeInfo::VariableIsSynthetic(String* name) { | 439 bool ScopeInfo::VariableIsSynthetic(String* name) { |
| 445 // There's currently no flag stored on the ScopeInfo to indicate that a | 440 // There's currently no flag stored on the ScopeInfo to indicate that a |
| 446 // variable is a compiler-introduced temporary. However, to avoid conflict | 441 // variable is a compiler-introduced temporary. However, to avoid conflict |
| 447 // with user declarations, the current temporaries like .generator_object and | 442 // with user declarations, the current temporaries like .generator_object and |
| 448 // .result start with a dot, so we can use that as a flag. It's a hack! | 443 // .result start with a dot, so we can use that as a flag. It's a hack! |
| (...skipping 26 matching lines...) Expand all Loading... |
| 475 DCHECK_NOT_NULL(mode); | 470 DCHECK_NOT_NULL(mode); |
| 476 DCHECK_NOT_NULL(init_flag); | 471 DCHECK_NOT_NULL(init_flag); |
| 477 DCHECK_NOT_NULL(maybe_assigned_flag); | 472 DCHECK_NOT_NULL(maybe_assigned_flag); |
| 478 | 473 |
| 479 if (scope_info->length() > 0) { | 474 if (scope_info->length() > 0) { |
| 480 ContextSlotCache* context_slot_cache = | 475 ContextSlotCache* context_slot_cache = |
| 481 scope_info->GetIsolate()->context_slot_cache(); | 476 scope_info->GetIsolate()->context_slot_cache(); |
| 482 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, | 477 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, |
| 483 maybe_assigned_flag); | 478 maybe_assigned_flag); |
| 484 if (result != ContextSlotCache::kNotFound) { | 479 if (result != ContextSlotCache::kNotFound) { |
| 485 DCHECK(result < scope_info->ContextLength()); | 480 DCHECK_LT(result, scope_info->ContextLength()); |
| 486 return result; | 481 return result; |
| 487 } | 482 } |
| 488 | 483 |
| 489 int start = scope_info->ContextLocalNameEntriesIndex(); | 484 int start = scope_info->ContextLocalNameEntriesIndex(); |
| 490 int end = start + scope_info->ContextLocalCount(); | 485 int end = start + scope_info->ContextLocalCount(); |
| 491 for (int i = start; i < end; ++i) { | 486 for (int i = start; i < end; ++i) { |
| 492 if (*name == scope_info->get(i)) { | 487 if (*name == scope_info->get(i)) { |
| 493 int var = i - start; | 488 int var = i - start; |
| 494 *mode = scope_info->ContextLocalMode(var); | 489 *mode = scope_info->ContextLocalMode(var); |
| 495 *init_flag = scope_info->ContextLocalInitFlag(var); | 490 *init_flag = scope_info->ContextLocalInitFlag(var); |
| 496 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); | 491 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); |
| 497 result = Context::MIN_CONTEXT_SLOTS + var; | 492 result = Context::MIN_CONTEXT_SLOTS + var; |
| 498 | 493 |
| 499 context_slot_cache->Update(scope_info, name, *mode, *init_flag, | 494 context_slot_cache->Update(scope_info, name, *mode, *init_flag, |
| 500 *maybe_assigned_flag, result); | 495 *maybe_assigned_flag, result); |
| 501 DCHECK(result < scope_info->ContextLength()); | 496 DCHECK_LT(result, scope_info->ContextLength()); |
| 502 return result; | 497 return result; |
| 503 } | 498 } |
| 504 } | 499 } |
| 505 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. | 500 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. |
| 506 context_slot_cache->Update(scope_info, name, TEMPORARY, | 501 context_slot_cache->Update(scope_info, name, TEMPORARY, |
| 507 kNeedsInitialization, kNotAssigned, -1); | 502 kNeedsInitialization, kNotAssigned, -1); |
| 508 } | 503 } |
| 509 | 504 |
| 510 return -1; | 505 return -1; |
| 511 } | 506 } |
| 512 | 507 |
| 513 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info, | |
| 514 Handle<String> name, VariableMode* mode, | |
| 515 InitializationFlag* init_flag, | |
| 516 MaybeAssignedFlag* maybe_assigned_flag) { | |
| 517 DCHECK(name->IsInternalizedString()); | |
| 518 DCHECK_NOT_NULL(mode); | |
| 519 DCHECK_NOT_NULL(init_flag); | |
| 520 DCHECK_NOT_NULL(maybe_assigned_flag); | |
| 521 if (scope_info->length() > 0) { | |
| 522 // This is to ensure that ContextLocalMode() and co. queries would work. | |
| 523 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(), | |
| 524 scope_info->ContextLocalNameEntriesIndex() + | |
| 525 scope_info->ContextLocalCount()); | |
| 526 int base = scope_info->ContextLocalNameEntriesIndex(); | |
| 527 int start = scope_info->ContextGlobalNameEntriesIndex(); | |
| 528 int end = start + scope_info->ContextGlobalCount(); | |
| 529 for (int i = start; i < end; ++i) { | |
| 530 if (*name == scope_info->get(i)) { | |
| 531 int var = i - base; | |
| 532 *mode = scope_info->ContextLocalMode(var); | |
| 533 *init_flag = scope_info->ContextLocalInitFlag(var); | |
| 534 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); | |
| 535 int result = Context::MIN_CONTEXT_SLOTS + var; | |
| 536 DCHECK(result < scope_info->ContextLength()); | |
| 537 return result; | |
| 538 } | |
| 539 } | |
| 540 } | |
| 541 return -1; | |
| 542 } | |
| 543 | |
| 544 | |
| 545 String* ScopeInfo::ContextSlotName(int slot_index) { | 508 String* ScopeInfo::ContextSlotName(int slot_index) { |
| 546 int const var = slot_index - Context::MIN_CONTEXT_SLOTS; | 509 int const var = slot_index - Context::MIN_CONTEXT_SLOTS; |
| 547 DCHECK_LE(0, var); | 510 DCHECK_LE(0, var); |
| 548 DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount()); | 511 DCHECK_LT(var, ContextLocalCount()); |
| 549 return ContextLocalName(var); | 512 return ContextLocalName(var); |
| 550 } | 513 } |
| 551 | 514 |
| 552 | 515 |
| 553 int ScopeInfo::ParameterIndex(String* name) { | 516 int ScopeInfo::ParameterIndex(String* name) { |
| 554 DCHECK(name->IsInternalizedString()); | 517 DCHECK(name->IsInternalizedString()); |
| 555 if (length() > 0) { | 518 if (length() > 0) { |
| 556 // We must read parameters from the end since for | 519 // We must read parameters from the end since for |
| 557 // multiply declared parameters the value of the | 520 // multiply declared parameters the value of the |
| 558 // last declaration of that parameter is used | 521 // last declaration of that parameter is used |
| (...skipping 13 matching lines...) Expand all Loading... |
| 572 | 535 |
| 573 int ScopeInfo::ReceiverContextSlotIndex() { | 536 int ScopeInfo::ReceiverContextSlotIndex() { |
| 574 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) | 537 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) |
| 575 return Smi::cast(get(ReceiverEntryIndex()))->value(); | 538 return Smi::cast(get(ReceiverEntryIndex()))->value(); |
| 576 return -1; | 539 return -1; |
| 577 } | 540 } |
| 578 | 541 |
| 579 | 542 |
| 580 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { | 543 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { |
| 581 DCHECK(name->IsInternalizedString()); | 544 DCHECK(name->IsInternalizedString()); |
| 582 DCHECK(mode != NULL); | 545 DCHECK_NOT_NULL(mode); |
| 583 if (length() > 0) { | 546 if (length() > 0) { |
| 584 if (FunctionVariableField::decode(Flags()) == CONTEXT && | 547 if (FunctionVariableField::decode(Flags()) == CONTEXT && |
| 585 FunctionName() == name) { | 548 FunctionName() == name) { |
| 586 *mode = FunctionVariableMode::decode(Flags()); | 549 *mode = FunctionVariableMode::decode(Flags()); |
| 587 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); | 550 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); |
| 588 } | 551 } |
| 589 } | 552 } |
| 590 return -1; | 553 return -1; |
| 591 } | 554 } |
| 592 | 555 |
| 593 | 556 |
| 594 FunctionKind ScopeInfo::function_kind() { | 557 FunctionKind ScopeInfo::function_kind() { |
| 595 return FunctionKindField::decode(Flags()); | 558 return FunctionKindField::decode(Flags()); |
| 596 } | 559 } |
| 597 | 560 |
| 598 | 561 |
| 599 int ScopeInfo::ParameterEntriesIndex() { | 562 int ScopeInfo::ParameterEntriesIndex() { |
| 600 DCHECK(length() > 0); | 563 DCHECK_LT(0, length()); |
| 601 return kVariablePartIndex; | 564 return kVariablePartIndex; |
| 602 } | 565 } |
| 603 | 566 |
| 604 | 567 |
| 605 int ScopeInfo::StackLocalFirstSlotIndex() { | 568 int ScopeInfo::StackLocalFirstSlotIndex() { |
| 606 return ParameterEntriesIndex() + ParameterCount(); | 569 return ParameterEntriesIndex() + ParameterCount(); |
| 607 } | 570 } |
| 608 | 571 |
| 609 | 572 |
| 610 int ScopeInfo::StackLocalEntriesIndex() { | 573 int ScopeInfo::StackLocalEntriesIndex() { |
| 611 return StackLocalFirstSlotIndex() + 1; | 574 return StackLocalFirstSlotIndex() + 1; |
| 612 } | 575 } |
| 613 | 576 |
| 614 | 577 |
| 615 int ScopeInfo::ContextLocalNameEntriesIndex() { | 578 int ScopeInfo::ContextLocalNameEntriesIndex() { |
| 616 return StackLocalEntriesIndex() + StackLocalCount(); | 579 return StackLocalEntriesIndex() + StackLocalCount(); |
| 617 } | 580 } |
| 618 | 581 |
| 619 | 582 |
| 620 int ScopeInfo::ContextGlobalNameEntriesIndex() { | 583 int ScopeInfo::ContextLocalInfoEntriesIndex() { |
| 621 return ContextLocalNameEntriesIndex() + ContextLocalCount(); | 584 return ContextLocalNameEntriesIndex() + ContextLocalCount(); |
| 622 } | 585 } |
| 623 | 586 |
| 624 | 587 |
| 625 int ScopeInfo::ContextLocalInfoEntriesIndex() { | 588 int ScopeInfo::ReceiverEntryIndex() { |
| 626 return ContextGlobalNameEntriesIndex() + ContextGlobalCount(); | |
| 627 } | |
| 628 | |
| 629 | |
| 630 int ScopeInfo::ContextGlobalInfoEntriesIndex() { | |
| 631 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); | 589 return ContextLocalInfoEntriesIndex() + ContextLocalCount(); |
| 632 } | 590 } |
| 633 | 591 |
| 634 | 592 |
| 635 int ScopeInfo::ReceiverEntryIndex() { | |
| 636 return ContextGlobalInfoEntriesIndex() + ContextGlobalCount(); | |
| 637 } | |
| 638 | |
| 639 | |
| 640 int ScopeInfo::FunctionNameEntryIndex() { | 593 int ScopeInfo::FunctionNameEntryIndex() { |
| 641 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0); | 594 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0); |
| 642 } | 595 } |
| 643 | 596 |
| 644 #ifdef DEBUG | 597 #ifdef DEBUG |
| 645 | 598 |
| 646 static void PrintList(const char* list_name, | 599 static void PrintList(const char* list_name, |
| 647 int nof_internal_slots, | 600 int nof_internal_slots, |
| 648 int start, | 601 int start, |
| 649 int end, | 602 int end, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 ContextLocalNameEntriesIndex() + ContextLocalCount(), this); | 634 ContextLocalNameEntriesIndex() + ContextLocalCount(), this); |
| 682 } | 635 } |
| 683 | 636 |
| 684 PrintF("}\n"); | 637 PrintF("}\n"); |
| 685 } | 638 } |
| 686 #endif // DEBUG | 639 #endif // DEBUG |
| 687 | 640 |
| 688 | 641 |
| 689 } // namespace internal | 642 } // namespace internal |
| 690 } // namespace v8 | 643 } // namespace v8 |
| OLD | NEW |