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

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: Rebased to include removal of stack height tracking and strict mode flag changes. 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) {
Kevin Millikin (Chromium) 2011/11/02 16:31:19 Now that you've removed the template parameter, I
Steven 2011/11/02 18:52:59 Done.
50 ScopeInfo<Allocator>::ScopeInfo(Scope* scope) 50 ZoneList<Variable*> variables(32); // 32 is a wild guess
Kevin Millikin (Chromium) 2011/11/02 16:31:19 Again, not your code, but the "wild guess" here se
Steven 2011/11/02 18:52:59 Will do this in a new CL. Here we are only interes
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 if (!var->is_used()) continue;
Kevin Millikin (Chromium) 2011/11/02 16:31:19 It's not clear how "CollectUsedVariables" can coll
Steven 2011/11/02 18:52:59 A bit flip because of faulty hardware :P Done. On
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 = VARIABLE_PART_INDEX
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->set_flags(flags);
117 scope_info->set_num_parameters(num_parameters);
118 scope_info->set_num_stack_locals(num_stack_locals);
119 scope_info->set_num_context_locals(num_context_locals);
120
121 int index = VARIABLE_PART_INDEX;
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->num_stack_locals() &&
102 UNREACHABLE(); 165 var_index == scope_info->NumberOfStackSlots() - 1));
103 break; 166 ASSERT(function_name_info != CONTEXT ||
167 var_index == scope_info->NumberOfContextSlots() - 1);
168 }
169
170 ASSERT(index == scope_info->length());
171 ASSERT(scope->num_parameters() == scope_info->num_parameters());
172 ASSERT(scope->num_stack_slots() == scope_info->NumberOfStackSlots());
173 ASSERT(scope->num_heap_slots() == scope_info->NumberOfContextSlots());
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() {
Kevin Millikin (Chromium) 2011/11/02 16:31:19 I like return length() > 0 && CallsEvalField::dec
Steven 2011/11/02 18:52:59 Done.
190 if (length() > 0) {
191 return CallsEvalField::decode(flags());
192 } else {
193 return false;
194 }
195 }
196
197
198 bool ScopeInfo::IsStrictMode() {
199 if (length() > 0) {
200 return StrictModeField::decode(flags());
201 } else {
202 return false;
203 }
204 }
205
206
207 int ScopeInfo::NumberOfLocals() {
208 return num_stack_locals() + num_context_locals();
209 }
210
211
212 int ScopeInfo::NumberOfStackSlots() {
213 if (length() > 0) {
214 bool function_name_stack_slot = STACK ==
Kevin Millikin (Chromium) 2011/11/02 16:31:19 Hmmm, I could see this requiring two tries to read
Steven 2011/11/02 18:52:59 Done.
215 FunctionVariableField::decode(flags());
216 return num_stack_locals() + (function_name_stack_slot ? 1 : 0);
217 }
218 return 0;
219 }
220
221
222 int ScopeInfo::NumberOfContextSlots() {
223 if (length() > 0) {
224 int context_locals = num_context_locals();
225 bool function_name_context_slot = CONTEXT ==
Kevin Millikin (Chromium) 2011/11/02 16:31:19 Same comment as just above.
Steven 2011/11/02 18:52:59 Done.
226 FunctionVariableField::decode(flags());
227 bool has_context = context_locals > 0 ||
228 function_name_context_slot ||
229 Type() == WITH_SCOPE ||
230 (Type() == FUNCTION_SCOPE && CallsEval());
231 if (has_context) {
232 return Context::MIN_CONTEXT_SLOTS + context_locals +
233 (function_name_context_slot ? 1 : 0);
234 }
235 }
236 return 0;
237 }
238
239
240 bool ScopeInfo::HasFunctionName() {
241 if (length() > 0) {
242 return NONE != FunctionVariableField::decode(flags());
243 } else {
244 return false;
245 }
246 }
247
248
249 bool ScopeInfo::HasHeapAllocatedLocals() {
250 if (length() > 0) {
251 return num_context_locals() > 0;
252 } else {
253 return false;
254 }
255 }
256
257
258 bool ScopeInfo::HasContext() {
259 if (length() > 0) {
260 return NumberOfContextSlots() > 0;
261 } else {
262 return false;
263 }
264 }
265
266
267 Handle<String> ScopeInfo::function_name() {
268 if (HasFunctionName()) {
269 return Handle<String>(String::cast(get(FunctionNameEntryIndex())));
270 } else {
271 return Handle<String>();
272 }
273 }
274
275
276 Handle<String> ScopeInfo::parameter_name(int var) {
277 ASSERT(0 <= var && var < num_parameters());
278 int info_index = ParameterEntriesIndex() + var;
279 return Handle<String>(String::cast(get(info_index)));
280 }
281
282
283 Handle<String> ScopeInfo::local_name(int var) {
284 ASSERT(0 <= var && var < NumberOfLocals());
285 ASSERT(StackLocalEntriesIndex() + num_stack_locals() ==
286 ContextLocalNameEntriesIndex());
287 int info_index = StackLocalEntriesIndex() + var;
288 return Handle<String>(String::cast(get(info_index)));
289 }
290
291
292 Handle<String> ScopeInfo::stack_local_name(int var) {
293 ASSERT(0 <= var && var < num_stack_locals());
294 int info_index = StackLocalEntriesIndex() + var;
295 return Handle<String>(String::cast(get(info_index)));
296 }
297
298
299 Handle<String> ScopeInfo::context_local_name(int var) {
300 ASSERT(0 <= var && var < num_context_locals());
301 int info_index = ContextLocalNameEntriesIndex() + var;
302 return Handle<String>(String::cast(get(info_index)));
303 }
304
305
306 VariableMode ScopeInfo::context_local_mode(int var) {
307 ASSERT(0 <= var && var < num_context_locals());
308 int info_index = ContextLocalModeEntriesIndex() + var;
309 return static_cast<VariableMode>(Smi::cast(get(info_index))->value());
310 }
311
312
313 int ScopeInfo::StackSlotIndex(String* name) {
314 ASSERT(name->IsSymbol());
315 if (length() > 0) {
316 int start = StackLocalEntriesIndex();
317 int end = StackLocalEntriesIndex() + num_stack_locals();
318 for (int i = start; i < end; ++i) {
319 if (name == get(i)) {
320 return i - start;
104 } 321 }
105 } 322 }
106 } 323 }
107 324 return -1;
108 // Add heap locals. 325 }
109 if (scope->num_heap_slots() > 0) { 326
110 // Add user-defined slots. 327
111 for (int i = 0; i < heap_locals.length(); i++) { 328 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()); 329 ASSERT(name->IsSymbol());
471 if (length() > 0) { 330 if (length() > 0) {
472 // Slots start after length entry. 331 ContextSlotCache* context_slot_cache = GetIsolate()->context_slot_cache();
473 Object** p0 = StackSlotEntriesAddr(); 332 int result = context_slot_cache->Lookup(this, name, mode);
474 int number_of_stack_slots; 333 if (result != ContextSlotCache::kNotFound) {
475 p0 = ReadInt(p0, &number_of_stack_slots); 334 ASSERT(result < NumberOfContextSlots());
476 Object** p = p0; 335 return result;
477 Object** end = p0 + number_of_stack_slots; 336 }
478 while (p != end) { 337
479 if (*p == name) return static_cast<int>(p - p0); 338 int start = ContextLocalNameEntriesIndex();
480 p++; 339 int end = ContextLocalNameEntriesIndex() + num_context_locals();
481 } 340 for (int i = start; i < end; ++i) {
482 } 341 if (name == get(i)) {
483 return -1; 342 int var = i - start;
484 } 343 VariableMode mode_value = context_local_mode(var);
485
486 int SerializedScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) {
487 ASSERT(name->IsSymbol());
488 Isolate* isolate = GetIsolate();
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; 344 if (mode != NULL) *mode = mode_value;
505 result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS; 345 result = Context::MIN_CONTEXT_SLOTS + var;
506 isolate->context_slot_cache()->Update(this, name, mode_value, result); 346 context_slot_cache->Update(this, name, mode_value, result);
347 ASSERT(result < NumberOfContextSlots());
507 return result; 348 return result;
508 } 349 }
509 p += 2; 350 }
510 } 351 context_slot_cache->Update(this, name, INTERNAL, -1);
511 } 352 }
512 isolate->context_slot_cache()->Update(this, name, INTERNAL, -1);
513 return -1; 353 return -1;
514 } 354 }
515 355
516 356
517 int SerializedScopeInfo::ParameterIndex(String* name) { 357 int ScopeInfo::ParameterIndex(String* name) {
518 ASSERT(name->IsSymbol()); 358 ASSERT(name->IsSymbol());
519 if (length() > 0) { 359 if (length() > 0) {
520 // We must read parameters from the end since for 360 // We must read parameters from the end since for
521 // multiply declared parameters the value of the 361 // multiply declared parameters the value of the
522 // last declaration of that parameter is used 362 // last declaration of that parameter is used
523 // inside a function (and thus we need to look 363 // inside a function (and thus we need to look
524 // at the last index). Was bug# 1110337. 364 // at the last index). Was bug# 1110337.
525 // 365 int start = ParameterEntriesIndex();
526 // Eventually, we should only register such parameters 366 int end = ParameterEntriesIndex() + num_parameters();
527 // once, with corresponding index. This requires a new 367 for (int i = end - 1; i >= start; --i) {
528 // implementation of the ScopeInfo code. See also other 368 if (name == get(i)) {
529 // comments in this file regarding this. 369 return i - start;
530 Object** p = ParameterEntriesAddr(); 370 }
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 } 371 }
538 } 372 }
539 return -1; 373 return -1;
540 } 374 }
541 375
542 376
543 int SerializedScopeInfo::FunctionContextSlotIndex(String* name, 377 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
544 VariableMode* mode) {
545 ASSERT(name->IsSymbol()); 378 ASSERT(name->IsSymbol());
546 if (length() > 0) { 379 if (length() > 0) {
547 Object** p = data_start(); 380 if (FunctionVariableField::decode(flags()) == CONTEXT &&
548 if (*p == name) { 381 *function_name() == name) {
549 p = ContextEntriesAddr(); 382 if (mode != NULL) *mode = FunctionVariableMode::decode(flags());
550 int number_of_context_slots; 383 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 } 384 }
563 } 385 }
564 return -1; 386 return -1;
565 } 387 }
566 388
567 389
390 int ScopeInfo::ParameterEntriesIndex() {
391 ASSERT(length() > 0);
392 return VARIABLE_PART_INDEX;
393 }
394
395
396 int ScopeInfo::StackLocalEntriesIndex() {
397 return ParameterEntriesIndex() + num_parameters();
398 }
399
400
401 int ScopeInfo::ContextLocalNameEntriesIndex() {
402 return StackLocalEntriesIndex() + num_stack_locals();
403 }
404
405
406 int ScopeInfo::ContextLocalModeEntriesIndex() {
407 return ContextLocalNameEntriesIndex() + num_context_locals();
408 }
409
410
411 int ScopeInfo::FunctionNameEntryIndex() {
412 return ContextLocalModeEntriesIndex() + num_context_locals();
413 }
414
415
568 int ContextSlotCache::Hash(Object* data, String* name) { 416 int ContextSlotCache::Hash(Object* data, String* name) {
569 // Uses only lower 32 bits if pointers are larger. 417 // Uses only lower 32 bits if pointers are larger.
570 uintptr_t addr_hash = 418 uintptr_t addr_hash =
571 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; 419 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
572 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); 420 return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
573 } 421 }
574 422
575 423
576 int ContextSlotCache::Lookup(Object* data, 424 int ContextSlotCache::Lookup(Object* data,
577 String* name, 425 String* name,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 Key& key = keys_[index]; 472 Key& key = keys_[index];
625 ASSERT(key.data == data); 473 ASSERT(key.data == data);
626 ASSERT(key.name->Equals(name)); 474 ASSERT(key.name->Equals(name));
627 Value result(values_[index]); 475 Value result(values_[index]);
628 ASSERT(result.mode() == mode); 476 ASSERT(result.mode() == mode);
629 ASSERT(result.index() + kNotFound == slot_index); 477 ASSERT(result.index() + kNotFound == slot_index);
630 } 478 }
631 } 479 }
632 480
633 481
634 template <class Allocator>
635 static void PrintList(const char* list_name, 482 static void PrintList(const char* list_name,
636 int nof_internal_slots, 483 int nof_internal_slots,
637 List<Handle<String>, Allocator>& list) { 484 int start,
638 if (list.length() > 0) { 485 int end,
486 ScopeInfo* scope_info) {
487 if (start < end) {
639 PrintF("\n // %s\n", list_name); 488 PrintF("\n // %s\n", list_name);
640 if (nof_internal_slots > 0) { 489 if (nof_internal_slots > 0) {
641 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1); 490 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
642 } 491 }
643 for (int i = 0; i < list.length(); i++) { 492 for (int i = nof_internal_slots; start < end; ++i, ++start) {
644 PrintF(" %2d ", i + nof_internal_slots); 493 PrintF(" %2d ", i);
645 list[i]->ShortPrint(); 494 String::cast(scope_info->get(start))->ShortPrint();
646 PrintF("\n"); 495 PrintF("\n");
647 } 496 }
648 } 497 }
649 } 498 }
650 499
651 500
652 template<class Allocator> 501 void ScopeInfo::Print() {
653 void ScopeInfo<Allocator>::Print() {
654 PrintF("ScopeInfo "); 502 PrintF("ScopeInfo ");
655 if (function_name_->length() > 0) 503 if (HasFunctionName()) {
656 function_name_->ShortPrint(); 504 function_name()->ShortPrint();
657 else 505 } else {
658 PrintF("/* no function name */"); 506 PrintF("/* no function name */");
507 }
659 PrintF("{"); 508 PrintF("{");
660 509
661 PrintList<Allocator>("parameters", 0, parameters_); 510 PrintList("parameters", 0,
662 PrintList<Allocator>("stack slots", 0, stack_slots_); 511 ParameterEntriesIndex(),
663 PrintList<Allocator>("context slots", Context::MIN_CONTEXT_SLOTS, 512 ParameterEntriesIndex() + num_parameters(),
664 context_slots_); 513 this);
514 PrintList("stack slots", 0,
515 StackLocalEntriesIndex(),
516 StackLocalEntriesIndex() + num_stack_locals(),
517 this);
518 PrintList("context slots",
519 Context::MIN_CONTEXT_SLOTS,
520 ContextLocalNameEntriesIndex(),
521 ContextLocalNameEntriesIndex() + num_context_locals(),
522 this);
665 523
666 PrintF("}\n"); 524 PrintF("}\n");
667 } 525 }
668 #endif // DEBUG 526 #endif // DEBUG
669 527
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 528 } } // namespace v8::internal
OLDNEW
« src/scopeinfo.h ('K') | « src/scopeinfo.h ('k') | src/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698