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

Side by Side Diff: src/scopeinfo.cc

Issue 8352039: Cleanup ScopeInfo and SerializedScopeInfo. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Converted ScopeInfo accessors to CamelCase. Created 9 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 28 matching lines...) Expand all
39 39
40 40
41 static int CompareLocal(Variable* const* v, Variable* const* w) { 41 static int CompareLocal(Variable* const* v, Variable* const* w) {
42 int x = (*v)->index(); 42 int x = (*v)->index();
43 int y = (*w)->index(); 43 int y = (*w)->index();
44 // Consider sorting them according to type as well? 44 // Consider sorting them according to type as well?
45 return x - y; 45 return x - y;
46 } 46 }
47 47
48 48
49 template<class Allocator> 49 Handle<ScopeInfo> ScopeInfo::Create(Scope* scope) {
50 ScopeInfo<Allocator>::ScopeInfo(Scope* scope) 50 ZoneList<Variable*> variables(32); // 32 is a wild guess
51 : function_name_(FACTORY->empty_symbol()), 51 ASSERT(variables.is_empty());
52 calls_eval_(scope->calls_eval()), 52 scope->CollectUsedVariables(&variables);
53 is_strict_mode_(scope->is_strict_mode()), 53
54 type_(scope->type()), 54 ZoneList<Variable*> stack_locals(scope->num_stack_slots());
55 parameters_(scope->num_parameters()), 55 ZoneList<Variable*> context_locals(scope->num_heap_slots());
56 stack_slots_(scope->num_stack_slots()), 56
57 context_slots_(scope->num_heap_slots()), 57 // Collect stack and context locals.
58 context_modes_(scope->num_heap_slots()) { 58 for (int i = 0; i < variables.length(); i++) {
59 Variable* var = variables[i];
60 ASSERT(var->is_used());
61 switch (var->location()) {
62 case Variable::UNALLOCATED:
63 case Variable::PARAMETER:
64 break;
65
66 case Variable::LOCAL:
67 stack_locals.Add(var);
68 break;
69
70 case Variable::CONTEXT:
71 context_locals.Add(var);
72 break;
73
74 case Variable::LOOKUP:
75 // We don't expect lookup variables in the locals list.
76 UNREACHABLE();
77 break;
78 }
79 }
80
81 // Determine use and location of the function variable if it is present.
82 FunctionVariableInfo function_name_info;
83 VariableMode function_variable_mode;
84 if (scope->is_function_scope() && scope->function() != NULL) {
85 Variable* var = scope->function()->var();
86 if (!var->is_used()) {
87 function_name_info = UNUSED;
88 } else if (var->IsContextSlot()) {
89 function_name_info = CONTEXT;
90 } else {
91 ASSERT(var->IsStackLocal());
92 function_name_info = STACK;
93 }
94 function_variable_mode = var->mode();
95 } else {
96 function_name_info = NONE;
97 function_variable_mode = VAR;
98 }
99
100 const bool has_function_name = function_name_info != NONE;
101 const int num_parameters = scope->num_parameters();
102 const int num_stack_locals = stack_locals.length();
103 const int num_context_locals = context_locals.length();
104 const int length = kVariablePartIndex
105 + num_parameters + num_stack_locals + 2 * num_context_locals
106 + (has_function_name ? 2 : 0);
107
108 Handle<ScopeInfo> scope_info = FACTORY->NewScopeInfo(length);
109
110 // Encode the flags.
111 int flags = TypeField::encode(scope->type()) |
112 CallsEvalField::encode(scope->calls_eval()) |
113 StrictModeField::encode(scope->is_strict_mode()) |
114 FunctionVariableField::encode(function_name_info) |
115 FunctionVariableMode::encode(function_variable_mode);
116 scope_info->SetFlags(flags);
117 scope_info->SetNumParameters(num_parameters);
118 scope_info->SetNumStackLocals(num_stack_locals);
119 scope_info->SetNumContextLocals(num_context_locals);
120
121 int index = kVariablePartIndex;
59 // Add parameters. 122 // Add parameters.
60 for (int i = 0; i < scope->num_parameters(); i++) { 123 ASSERT(index == scope_info->ParameterEntriesIndex());
61 ASSERT(parameters_.length() == i); 124 for (int i = 0; i < num_parameters; ++i) {
62 parameters_.Add(scope->parameter(i)->name()); 125 scope_info->set(index++, *scope->parameter(i)->name());
63 } 126 }
64 127
65 // Add stack locals and collect heap locals. 128 // Add stack locals' names. We are assuming that the stack locals'
66 // We are assuming that the locals' slots are allocated in 129 // slots are allocated in increasing order, so we can simply add
67 // increasing order, so we can simply add them to the 130 // them to the ScopeInfo object.
68 // ScopeInfo lists. However, due to usage analysis, this is 131 ASSERT(index == scope_info->StackLocalEntriesIndex());
69 // not true for context-allocated locals: Some of them 132 for (int i = 0; i < num_stack_locals; ++i) {
70 // may be parameters which are allocated before the 133 ASSERT(stack_locals[i]->index() == i);
71 // non-parameter locals. When the non-parameter locals are 134 scope_info->set(index++, *stack_locals[i]->name());
72 // sorted according to usage, the allocated slot indices may 135 }
73 // not be in increasing order with the variable list anymore. 136
74 // Thus, we first collect the context-allocated locals, and then 137 // Due to usage analysis, context-allocated locals are not necessarily in
75 // sort them by context slot index before adding them to the 138 // increasing order: Some of them may be parameters which are allocated before
76 // ScopeInfo list. 139 // the non-parameter locals. When the non-parameter locals are sorted
77 List<Variable*, Allocator> locals(32); // 32 is a wild guess 140 // according to usage, the allocated slot indices may not be in increasing
78 ASSERT(locals.is_empty()); 141 // order with the variable list anymore. Thus, we first need to sort them by
79 scope->CollectUsedVariables(&locals); 142 // context slot index before adding them to the ScopeInfo object.
80 locals.Sort(&CompareLocal); 143 context_locals.Sort(&CompareLocal);
81 144
82 List<Variable*, Allocator> heap_locals(locals.length()); 145 // Add context locals' names.
83 for (int i = 0; i < locals.length(); i++) { 146 ASSERT(index == scope_info->ContextLocalNameEntriesIndex());
84 Variable* var = locals[i]; 147 for (int i = 0; i < num_context_locals; ++i) {
85 if (var->is_used()) { 148 scope_info->set(index++, *context_locals[i]->name());
86 switch (var->location()) { 149 }
87 case Variable::UNALLOCATED: 150
88 case Variable::PARAMETER: 151 // Add context locals' modes.
89 break; 152 ASSERT(index == scope_info->ContextLocalModeEntriesIndex());
90 153 for (int i = 0; i < num_context_locals; ++i) {
91 case Variable::LOCAL: 154 scope_info->set(index++, Smi::FromInt(context_locals[i]->mode()));
92 ASSERT(stack_slots_.length() == var->index()); 155 }
93 stack_slots_.Add(var->name()); 156
94 break; 157 // If present, add the function variable name and its index.
95 158 ASSERT(index == scope_info->FunctionNameEntryIndex());
96 case Variable::CONTEXT: 159 if (has_function_name) {
97 heap_locals.Add(var); 160 int var_index = scope->function()->var()->index();
98 break; 161 scope_info->set(index++, *scope->function()->name());
99 162 scope_info->set(index++, Smi::FromInt(var_index));
100 case Variable::LOOKUP: 163 ASSERT(function_name_info != STACK ||
101 // We don't expect lookup variables in the locals list. 164 (var_index == scope_info->NumStackLocals() &&
102 UNREACHABLE(); 165 var_index == scope_info->NumberOfStackSlots() - 1));
103 break; 166 ASSERT(function_name_info != CONTEXT ||
167 var_index == scope_info->ContextLength() - 1);
168 }
169
170 ASSERT(index == scope_info->length());
171 ASSERT(scope->num_parameters() == scope_info->NumParameters());
172 ASSERT(scope->num_stack_slots() == scope_info->NumberOfStackSlots());
173 ASSERT(scope->num_heap_slots() == scope_info->ContextLength());
174 return scope_info;
175 }
176
177
178 ScopeInfo* ScopeInfo::Empty() {
179 return reinterpret_cast<ScopeInfo*>(HEAP->empty_fixed_array());
180 }
181
182
183 ScopeType ScopeInfo::Type() {
184 ASSERT(length() > 0);
185 return TypeField::decode(Flags());
186 }
187
188
189 bool ScopeInfo::CallsEval() {
190 return length() > 0 && CallsEvalField::decode(Flags());
191 }
192
193
194 bool ScopeInfo::IsStrictMode() {
195 return length() > 0 && StrictModeField::decode(Flags());
196 }
197
198
199 int ScopeInfo::NumberOfLocals() {
200 return NumStackLocals() + NumContextLocals();
201 }
202
203
204 int ScopeInfo::NumberOfStackSlots() {
205 if (length() > 0) {
206 bool function_name_stack_slot =
207 FunctionVariableField::decode(Flags()) == STACK;
208 return NumStackLocals() + (function_name_stack_slot ? 1 : 0);
209 }
210 return 0;
211 }
212
213
214 int ScopeInfo::ContextLength() {
215 if (length() > 0) {
216 int context_locals = NumContextLocals();
217 bool function_name_context_slot =
218 FunctionVariableField::decode(Flags()) == CONTEXT;
219 bool has_context = context_locals > 0 ||
220 function_name_context_slot ||
221 Type() == WITH_SCOPE ||
222 (Type() == FUNCTION_SCOPE && CallsEval());
223 if (has_context) {
224 return Context::MIN_CONTEXT_SLOTS + context_locals +
225 (function_name_context_slot ? 1 : 0);
226 }
227 }
228 return 0;
229 }
230
231
232 bool ScopeInfo::HasFunctionName() {
233 if (length() > 0) {
234 return NONE != FunctionVariableField::decode(Flags());
235 } else {
236 return false;
237 }
238 }
239
240
241 bool ScopeInfo::HasHeapAllocatedLocals() {
242 if (length() > 0) {
243 return NumContextLocals() > 0;
244 } else {
245 return false;
246 }
247 }
248
249
250 bool ScopeInfo::HasContext() {
251 if (length() > 0) {
252 return ContextLength() > 0;
253 } else {
254 return false;
255 }
256 }
257
258
259 String* ScopeInfo::FunctionName() {
260 ASSERT(HasFunctionName());
261 return String::cast(get(FunctionNameEntryIndex()));
262 }
263
264
265 String* ScopeInfo::ParameterName(int var) {
266 ASSERT(0 <= var && var < NumParameters());
267 int info_index = ParameterEntriesIndex() + var;
268 return String::cast(get(info_index));
269 }
270
271
272 String* ScopeInfo::LocalName(int var) {
273 ASSERT(0 <= var && var < NumberOfLocals());
274 ASSERT(StackLocalEntriesIndex() + NumStackLocals() ==
275 ContextLocalNameEntriesIndex());
276 int info_index = StackLocalEntriesIndex() + var;
277 return String::cast(get(info_index));
278 }
279
280
281 String* ScopeInfo::StackLocalName(int var) {
282 ASSERT(0 <= var && var < NumStackLocals());
283 int info_index = StackLocalEntriesIndex() + var;
284 return String::cast(get(info_index));
285 }
286
287
288 String* ScopeInfo::ContextLocalName(int var) {
289 ASSERT(0 <= var && var < NumContextLocals());
290 int info_index = ContextLocalNameEntriesIndex() + var;
291 return String::cast(get(info_index));
292 }
293
294
295 VariableMode ScopeInfo::ContextLocalMode(int var) {
296 ASSERT(0 <= var && var < NumContextLocals());
297 int info_index = ContextLocalModeEntriesIndex() + var;
298 return static_cast<VariableMode>(Smi::cast(get(info_index))->value());
299 }
300
301
302 int ScopeInfo::StackSlotIndex(String* name) {
303 ASSERT(name->IsSymbol());
304 if (length() > 0) {
305 int start = StackLocalEntriesIndex();
306 int end = StackLocalEntriesIndex() + NumStackLocals();
307 for (int i = start; i < end; ++i) {
308 if (name == get(i)) {
309 return i - start;
104 } 310 }
105 } 311 }
106 } 312 }
107 313 return -1;
108 // Add heap locals. 314 }
109 if (scope->num_heap_slots() > 0) { 315
110 // Add user-defined slots. 316
111 for (int i = 0; i < heap_locals.length(); i++) { 317 int ScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) {
112 ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
113 context_slots_.length());
114 ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
115 context_modes_.length());
116 context_slots_.Add(heap_locals[i]->name());
117 context_modes_.Add(heap_locals[i]->mode());
118 }
119
120 } else {
121 ASSERT(heap_locals.length() == 0);
122 }
123
124 // Add the function context slot, if present.
125 // For now, this must happen at the very end because of the
126 // ordering of the scope info slots and the respective slot indices.
127 if (scope->is_function_scope()) {
128 VariableProxy* proxy = scope->function();
129 if (proxy != NULL &&
130 proxy->var()->is_used() &&
131 proxy->var()->IsContextSlot()) {
132 function_name_ = proxy->name();
133 // Note that we must not find the function name in the context slot
134 // list - instead it must be handled separately in the
135 // Contexts::Lookup() function. Thus record an empty symbol here so we
136 // get the correct number of context slots.
137 ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
138 context_slots_.length());
139 ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
140 context_modes_.length());
141 context_slots_.Add(FACTORY->empty_symbol());
142 context_modes_.Add(proxy->var()->mode());
143 }
144 }
145 }
146
147
148 // Encoding format in a FixedArray object:
149 //
150 // - function name
151 //
152 // - calls eval boolean flag
153 //
154 // - is strict mode scope
155 //
156 // - scope type
157 //
158 // - number of variables in the context object (smi) (= function context
159 // slot index + 1)
160 // - list of pairs (name, Var mode) of context-allocated variables (starting
161 // with context slot 0)
162 //
163 // - number of parameters (smi)
164 // - list of parameter names (starting with parameter 0 first)
165 //
166 // - number of variables on the stack (smi)
167 // - list of names of stack-allocated variables (starting with stack slot 0)
168
169 // The ScopeInfo representation could be simplified and the ScopeInfo
170 // re-implemented (with almost the same interface). Here is a
171 // suggestion for the new format:
172 //
173 // - have a single list with all variable names (parameters, stack locals,
174 // context locals), followed by a list of non-Object* values containing
175 // the variables information (what kind, index, attributes)
176 // - searching the linear list of names is fast and yields an index into the
177 // list if the variable name is found
178 // - that list index is then used to find the variable information in the
179 // subsequent list
180 // - the list entries don't have to be in any particular order, so all the
181 // current sorting business can go away
182 // - the ScopeInfo lookup routines can be reduced to perhaps a single lookup
183 // which returns all information at once
184 // - when gathering the information from a Scope, we only need to iterate
185 // through the local variables (parameters and context info is already
186 // present)
187
188
189 template <class T>
190 static inline Object** ReadInt(Object** p, T* x) {
191 *x = static_cast<T>((reinterpret_cast<Smi*>(*p++))->value());
192 return p;
193 }
194
195
196 static inline Object** ReadBool(Object** p, bool* x) {
197 *x = (reinterpret_cast<Smi*>(*p++))->value() != 0;
198 return p;
199 }
200
201
202 template <class T>
203 static inline Object** ReadObject(Object** p, Handle<T>* s) {
204 *s = Handle<T>::cast(Handle<Object>(*p++));
205 return p;
206 }
207
208
209 template <class Allocator, class T>
210 static Object** ReadList(Object** p, List<Handle<T>, Allocator >* list) {
211 ASSERT(list->is_empty());
212 int n;
213 p = ReadInt(p, &n);
214 while (n-- > 0) {
215 Handle<T> s;
216 p = ReadObject(p, &s);
217 list->Add(s);
218 }
219 return p;
220 }
221
222
223 template <class Allocator>
224 static Object** ReadList(Object** p,
225 List<Handle<String>, Allocator>* list,
226 List<VariableMode, Allocator>* modes) {
227 ASSERT(list->is_empty());
228 int n;
229 p = ReadInt(p, &n);
230 while (n-- > 0) {
231 Handle<String> s;
232 int m;
233 p = ReadObject(p, &s);
234 p = ReadInt(p, &m);
235 list->Add(s);
236 modes->Add(static_cast<VariableMode>(m));
237 }
238 return p;
239 }
240
241
242 template<class Allocator>
243 ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
244 : function_name_(FACTORY->empty_symbol()),
245 parameters_(4),
246 stack_slots_(8),
247 context_slots_(8),
248 context_modes_(8) {
249 if (data->length() > 0) {
250 Object** p0 = data->data_start();
251 Object** p = p0;
252 p = ReadObject(p, &function_name_);
253 p = ReadBool(p, &calls_eval_);
254 p = ReadBool(p, &is_strict_mode_);
255 p = ReadInt(p, &type_);
256 p = ReadList<Allocator>(p, &context_slots_, &context_modes_);
257 p = ReadList<Allocator>(p, &parameters_);
258 p = ReadList<Allocator>(p, &stack_slots_);
259 ASSERT((p - p0) == FixedArray::cast(data)->length());
260 }
261 }
262
263
264 static inline Object** WriteInt(Object** p, int x) {
265 *p++ = Smi::FromInt(x);
266 return p;
267 }
268
269
270 static inline Object** WriteBool(Object** p, bool b) {
271 *p++ = Smi::FromInt(b ? 1 : 0);
272 return p;
273 }
274
275
276 template <class T>
277 static inline Object** WriteObject(Object** p, Handle<T> s) {
278 *p++ = *s;
279 return p;
280 }
281
282
283 template <class Allocator, class T>
284 static Object** WriteList(Object** p, List<Handle<T>, Allocator >* list) {
285 const int n = list->length();
286 p = WriteInt(p, n);
287 for (int i = 0; i < n; i++) {
288 p = WriteObject(p, list->at(i));
289 }
290 return p;
291 }
292
293
294 template <class Allocator>
295 static Object** WriteList(Object** p,
296 List<Handle<String>, Allocator>* list,
297 List<VariableMode, Allocator>* modes) {
298 const int n = list->length();
299 p = WriteInt(p, n);
300 for (int i = 0; i < n; i++) {
301 p = WriteObject(p, list->at(i));
302 p = WriteInt(p, modes->at(i));
303 }
304 return p;
305 }
306
307
308 template<class Allocator>
309 Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
310 // function name, calls eval, is_strict_mode, scope type,
311 // length for 3 tables:
312 const int extra_slots = 1 + 1 + 1 + 1 + 3;
313 int length = extra_slots +
314 context_slots_.length() * 2 +
315 parameters_.length() +
316 stack_slots_.length();
317
318 Handle<SerializedScopeInfo> data(
319 SerializedScopeInfo::cast(*FACTORY->NewSerializedScopeInfo(length)));
320 AssertNoAllocation nogc;
321
322 Object** p0 = data->data_start();
323 Object** p = p0;
324 p = WriteObject(p, function_name_);
325 p = WriteBool(p, calls_eval_);
326 p = WriteBool(p, is_strict_mode_);
327 p = WriteInt(p, type_);
328 p = WriteList(p, &context_slots_, &context_modes_);
329 p = WriteList(p, &parameters_);
330 p = WriteList(p, &stack_slots_);
331 ASSERT((p - p0) == length);
332
333 return data;
334 }
335
336
337 template<class Allocator>
338 Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
339 // A local variable can be allocated either on the stack or in the context.
340 // For variables allocated in the context they are always preceded by
341 // Context::MIN_CONTEXT_SLOTS of fixed allocated slots in the context.
342 if (i < number_of_stack_slots()) {
343 return stack_slot_name(i);
344 } else {
345 return context_slot_name(i - number_of_stack_slots() +
346 Context::MIN_CONTEXT_SLOTS);
347 }
348 }
349
350
351 template<class Allocator>
352 int ScopeInfo<Allocator>::NumberOfLocals() const {
353 int number_of_locals = number_of_stack_slots();
354 if (number_of_context_slots() > 0) {
355 ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS);
356 number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS;
357 }
358 return number_of_locals;
359 }
360
361
362 Handle<SerializedScopeInfo> SerializedScopeInfo::Create(Scope* scope) {
363 ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
364 return sinfo.Serialize();
365 }
366
367
368 SerializedScopeInfo* SerializedScopeInfo::Empty() {
369 return reinterpret_cast<SerializedScopeInfo*>(HEAP->empty_fixed_array());
370 }
371
372
373 Object** SerializedScopeInfo::ContextEntriesAddr() {
374 ASSERT(length() > 0);
375 // +4 for function name, calls eval, strict mode, scope type.
376 return data_start() + 4;
377 }
378
379
380 Object** SerializedScopeInfo::ParameterEntriesAddr() {
381 ASSERT(length() > 0);
382 Object** p = ContextEntriesAddr();
383 int number_of_context_slots;
384 p = ReadInt(p, &number_of_context_slots);
385 return p + number_of_context_slots*2; // *2 for pairs
386 }
387
388
389 Object** SerializedScopeInfo::StackSlotEntriesAddr() {
390 ASSERT(length() > 0);
391 Object** p = ParameterEntriesAddr();
392 int number_of_parameter_slots;
393 p = ReadInt(p, &number_of_parameter_slots);
394 return p + number_of_parameter_slots;
395 }
396
397
398 bool SerializedScopeInfo::CallsEval() {
399 if (length() > 0) {
400 Object** p = data_start() + 1; // +1 for function name.
401 bool calls_eval;
402 p = ReadBool(p, &calls_eval);
403 return calls_eval;
404 }
405 return false;
406 }
407
408
409 bool SerializedScopeInfo::IsStrictMode() {
410 if (length() > 0) {
411 Object** p = data_start() + 2; // +2 for function name, calls eval.
412 bool strict_mode;
413 p = ReadBool(p, &strict_mode);
414 return strict_mode;
415 }
416 return false;
417 }
418
419
420 ScopeType SerializedScopeInfo::Type() {
421 ASSERT(length() > 0);
422 // +3 for function name, calls eval, strict mode.
423 Object** p = data_start() + 3;
424 ScopeType type;
425 p = ReadInt(p, &type);
426 return type;
427 }
428
429
430 int SerializedScopeInfo::NumberOfStackSlots() {
431 if (length() > 0) {
432 Object** p = StackSlotEntriesAddr();
433 int number_of_stack_slots;
434 ReadInt(p, &number_of_stack_slots);
435 return number_of_stack_slots;
436 }
437 return 0;
438 }
439
440
441 int SerializedScopeInfo::NumberOfContextSlots() {
442 if (length() > 0) {
443 Object** p = ContextEntriesAddr();
444 int number_of_context_slots;
445 ReadInt(p, &number_of_context_slots);
446 return number_of_context_slots + Context::MIN_CONTEXT_SLOTS;
447 }
448 return 0;
449 }
450
451
452 bool SerializedScopeInfo::HasHeapAllocatedLocals() {
453 if (length() > 0) {
454 Object** p = ContextEntriesAddr();
455 int number_of_context_slots;
456 ReadInt(p, &number_of_context_slots);
457 return number_of_context_slots > 0;
458 }
459 return false;
460 }
461
462
463 bool SerializedScopeInfo::HasContext() {
464 return HasHeapAllocatedLocals() ||
465 Type() == WITH_SCOPE;
466 }
467
468
469 int SerializedScopeInfo::StackSlotIndex(String* name) {
470 ASSERT(name->IsSymbol()); 318 ASSERT(name->IsSymbol());
471 if (length() > 0) { 319 ASSERT(mode != NULL);
472 // Slots start after length entry. 320 if (length() > 0) {
473 Object** p0 = StackSlotEntriesAddr(); 321 ContextSlotCache* context_slot_cache = GetIsolate()->context_slot_cache();
474 int number_of_stack_slots; 322 int result = context_slot_cache->Lookup(this, name, mode);
475 p0 = ReadInt(p0, &number_of_stack_slots); 323 if (result != ContextSlotCache::kNotFound) {
476 Object** p = p0; 324 ASSERT(result < ContextLength());
477 Object** end = p0 + number_of_stack_slots; 325 return result;
478 while (p != end) { 326 }
479 if (*p == name) return static_cast<int>(p - p0); 327
480 p++; 328 int start = ContextLocalNameEntriesIndex();
481 } 329 int end = ContextLocalNameEntriesIndex() + NumContextLocals();
482 } 330 for (int i = start; i < end; ++i) {
483 return -1; 331 if (name == get(i)) {
484 } 332 int var = i - start;
485 333 *mode = ContextLocalMode(var);
486 int SerializedScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) { 334 result = Context::MIN_CONTEXT_SLOTS + var;
487 ASSERT(name->IsSymbol()); 335 context_slot_cache->Update(this, name, *mode, result);
488 Isolate* isolate = GetIsolate(); 336 ASSERT(result < ContextLength());
489 int result = isolate->context_slot_cache()->Lookup(this, name, mode);
490 if (result != ContextSlotCache::kNotFound) return result;
491 if (length() > 0) {
492 // Slots start after length entry.
493 Object** p0 = ContextEntriesAddr();
494 int number_of_context_slots;
495 p0 = ReadInt(p0, &number_of_context_slots);
496 Object** p = p0;
497 Object** end = p0 + number_of_context_slots * 2;
498 while (p != end) {
499 if (*p == name) {
500 ASSERT(((p - p0) & 1) == 0);
501 int v;
502 ReadInt(p + 1, &v);
503 VariableMode mode_value = static_cast<VariableMode>(v);
504 if (mode != NULL) *mode = mode_value;
505 result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
506 isolate->context_slot_cache()->Update(this, name, mode_value, result);
507 return result; 337 return result;
508 } 338 }
509 p += 2; 339 }
510 } 340 context_slot_cache->Update(this, name, INTERNAL, -1);
511 } 341 }
512 isolate->context_slot_cache()->Update(this, name, INTERNAL, -1);
513 return -1; 342 return -1;
514 } 343 }
515 344
516 345
517 int SerializedScopeInfo::ParameterIndex(String* name) { 346 int ScopeInfo::ParameterIndex(String* name) {
518 ASSERT(name->IsSymbol()); 347 ASSERT(name->IsSymbol());
519 if (length() > 0) { 348 if (length() > 0) {
520 // We must read parameters from the end since for 349 // We must read parameters from the end since for
521 // multiply declared parameters the value of the 350 // multiply declared parameters the value of the
522 // last declaration of that parameter is used 351 // last declaration of that parameter is used
523 // inside a function (and thus we need to look 352 // inside a function (and thus we need to look
524 // at the last index). Was bug# 1110337. 353 // at the last index). Was bug# 1110337.
525 // 354 int start = ParameterEntriesIndex();
526 // Eventually, we should only register such parameters 355 int end = ParameterEntriesIndex() + NumParameters();
527 // once, with corresponding index. This requires a new 356 for (int i = end - 1; i >= start; --i) {
528 // implementation of the ScopeInfo code. See also other 357 if (name == get(i)) {
529 // comments in this file regarding this. 358 return i - start;
530 Object** p = ParameterEntriesAddr(); 359 }
531 int number_of_parameter_slots;
532 Object** p0 = ReadInt(p, &number_of_parameter_slots);
533 p = p0 + number_of_parameter_slots;
534 while (p > p0) {
535 p--;
536 if (*p == name) return static_cast<int>(p - p0);
537 } 360 }
538 } 361 }
539 return -1; 362 return -1;
540 } 363 }
541 364
542 365
543 int SerializedScopeInfo::FunctionContextSlotIndex(String* name, 366 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
544 VariableMode* mode) {
545 ASSERT(name->IsSymbol()); 367 ASSERT(name->IsSymbol());
368 ASSERT(mode != NULL);
546 if (length() > 0) { 369 if (length() > 0) {
547 Object** p = data_start(); 370 if (FunctionVariableField::decode(Flags()) == CONTEXT &&
548 if (*p == name) { 371 FunctionName() == name) {
549 p = ContextEntriesAddr(); 372 *mode = FunctionVariableMode::decode(Flags());
550 int number_of_context_slots; 373 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
551 p = ReadInt(p, &number_of_context_slots);
552 ASSERT(number_of_context_slots != 0);
553 // The function context slot is the last entry.
554 if (mode != NULL) {
555 // Seek to context slot entry.
556 p += (number_of_context_slots - 1) * 2;
557 // Seek to mode.
558 ++p;
559 ReadInt(p, mode);
560 }
561 return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1;
562 } 374 }
563 } 375 }
564 return -1; 376 return -1;
565 } 377 }
566 378
567 379
380 int ScopeInfo::ParameterEntriesIndex() {
381 ASSERT(length() > 0);
382 return kVariablePartIndex;
383 }
384
385
386 int ScopeInfo::StackLocalEntriesIndex() {
387 return ParameterEntriesIndex() + NumParameters();
388 }
389
390
391 int ScopeInfo::ContextLocalNameEntriesIndex() {
392 return StackLocalEntriesIndex() + NumStackLocals();
393 }
394
395
396 int ScopeInfo::ContextLocalModeEntriesIndex() {
397 return ContextLocalNameEntriesIndex() + NumContextLocals();
398 }
399
400
401 int ScopeInfo::FunctionNameEntryIndex() {
402 return ContextLocalModeEntriesIndex() + NumContextLocals();
403 }
404
405
568 int ContextSlotCache::Hash(Object* data, String* name) { 406 int ContextSlotCache::Hash(Object* data, String* name) {
569 // Uses only lower 32 bits if pointers are larger. 407 // Uses only lower 32 bits if pointers are larger.
570 uintptr_t addr_hash = 408 uintptr_t addr_hash =
571 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; 409 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
572 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); 410 return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
573 } 411 }
574 412
575 413
576 int ContextSlotCache::Lookup(Object* data, 414 int ContextSlotCache::Lookup(Object* data,
577 String* name, 415 String* name,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 Key& key = keys_[index]; 462 Key& key = keys_[index];
625 ASSERT(key.data == data); 463 ASSERT(key.data == data);
626 ASSERT(key.name->Equals(name)); 464 ASSERT(key.name->Equals(name));
627 Value result(values_[index]); 465 Value result(values_[index]);
628 ASSERT(result.mode() == mode); 466 ASSERT(result.mode() == mode);
629 ASSERT(result.index() + kNotFound == slot_index); 467 ASSERT(result.index() + kNotFound == slot_index);
630 } 468 }
631 } 469 }
632 470
633 471
634 template <class Allocator>
635 static void PrintList(const char* list_name, 472 static void PrintList(const char* list_name,
636 int nof_internal_slots, 473 int nof_internal_slots,
637 List<Handle<String>, Allocator>& list) { 474 int start,
638 if (list.length() > 0) { 475 int end,
476 ScopeInfo* scope_info) {
477 if (start < end) {
639 PrintF("\n // %s\n", list_name); 478 PrintF("\n // %s\n", list_name);
640 if (nof_internal_slots > 0) { 479 if (nof_internal_slots > 0) {
641 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1); 480 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
642 } 481 }
643 for (int i = 0; i < list.length(); i++) { 482 for (int i = nof_internal_slots; start < end; ++i, ++start) {
644 PrintF(" %2d ", i + nof_internal_slots); 483 PrintF(" %2d ", i);
645 list[i]->ShortPrint(); 484 String::cast(scope_info->get(start))->ShortPrint();
646 PrintF("\n"); 485 PrintF("\n");
647 } 486 }
648 } 487 }
649 } 488 }
650 489
651 490
652 template<class Allocator> 491 void ScopeInfo::Print() {
653 void ScopeInfo<Allocator>::Print() {
654 PrintF("ScopeInfo "); 492 PrintF("ScopeInfo ");
655 if (function_name_->length() > 0) 493 if (HasFunctionName()) {
656 function_name_->ShortPrint(); 494 FunctionName()->ShortPrint();
657 else 495 } else {
658 PrintF("/* no function name */"); 496 PrintF("/* no function name */");
497 }
659 PrintF("{"); 498 PrintF("{");
660 499
661 PrintList<Allocator>("parameters", 0, parameters_); 500 PrintList("parameters", 0,
662 PrintList<Allocator>("stack slots", 0, stack_slots_); 501 ParameterEntriesIndex(),
663 PrintList<Allocator>("context slots", Context::MIN_CONTEXT_SLOTS, 502 ParameterEntriesIndex() + NumParameters(),
664 context_slots_); 503 this);
504 PrintList("stack slots", 0,
505 StackLocalEntriesIndex(),
506 StackLocalEntriesIndex() + NumStackLocals(),
507 this);
508 PrintList("context slots",
509 Context::MIN_CONTEXT_SLOTS,
510 ContextLocalNameEntriesIndex(),
511 ContextLocalNameEntriesIndex() + NumContextLocals(),
512 this);
665 513
666 PrintF("}\n"); 514 PrintF("}\n");
667 } 515 }
668 #endif // DEBUG 516 #endif // DEBUG
669 517
670
671 // Make sure the classes get instantiated by the template system.
672 template class ScopeInfo<FreeStoreAllocationPolicy>;
673 template class ScopeInfo<PreallocatedStorage>;
674 template class ScopeInfo<ZoneListAllocationPolicy>;
675
676 } } // namespace v8::internal 518 } } // namespace v8::internal
OLDNEW
« src/frames.cc ('K') | « src/scopeinfo.h ('k') | src/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698