blob: 0f36234701c06e903cf07c6aa05e1f1133551b3d [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
30#include "v8.h"
31
32#include "scopeinfo.h"
33#include "scopes.h"
34
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000035#include "allocation-inl.h"
36
Steve Blocka7e24c12009-10-30 11:49:00 +000037namespace v8 {
38namespace internal {
39
40
Ben Murdoch3ef787d2012-04-12 10:51:47 +010041Handle<ScopeInfo> ScopeInfo::Create(Scope* scope) {
42 // Collect stack and context locals.
43 ZoneList<Variable*> stack_locals(scope->StackLocalCount());
44 ZoneList<Variable*> context_locals(scope->ContextLocalCount());
45 scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
46 const int stack_local_count = stack_locals.length();
47 const int context_local_count = context_locals.length();
48 // Make sure we allocate the correct amount.
49 ASSERT(scope->StackLocalCount() == stack_local_count);
50 ASSERT(scope->ContextLocalCount() == context_local_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000051
Ben Murdoch3ef787d2012-04-12 10:51:47 +010052 // Determine use and location of the function variable if it is present.
53 FunctionVariableInfo function_name_info;
54 VariableMode function_variable_mode;
55 if (scope->is_function_scope() && scope->function() != NULL) {
56 Variable* var = scope->function()->var();
57 if (!var->is_used()) {
58 function_name_info = UNUSED;
59 } else if (var->IsContextSlot()) {
60 function_name_info = CONTEXT;
61 } else {
62 ASSERT(var->IsStackLocal());
63 function_name_info = STACK;
64 }
65 function_variable_mode = var->mode();
66 } else {
67 function_name_info = NONE;
68 function_variable_mode = VAR;
69 }
Steve Blocka7e24c12009-10-30 11:49:00 +000070
Ben Murdoch3ef787d2012-04-12 10:51:47 +010071 const bool has_function_name = function_name_info != NONE;
72 const int parameter_count = scope->num_parameters();
73 const int length = kVariablePartIndex
74 + parameter_count + stack_local_count + 2 * context_local_count
75 + (has_function_name ? 2 : 0);
76
77 Handle<ScopeInfo> scope_info = FACTORY->NewScopeInfo(length);
78
79 // Encode the flags.
80 int flags = TypeField::encode(scope->type()) |
81 CallsEvalField::encode(scope->calls_eval()) |
82 LanguageModeField::encode(scope->language_mode()) |
83 FunctionVariableField::encode(function_name_info) |
84 FunctionVariableMode::encode(function_variable_mode);
85 scope_info->SetFlags(flags);
86 scope_info->SetParameterCount(parameter_count);
87 scope_info->SetStackLocalCount(stack_local_count);
88 scope_info->SetContextLocalCount(context_local_count);
89
90 int index = kVariablePartIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +000091 // Add parameters.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010092 ASSERT(index == scope_info->ParameterEntriesIndex());
93 for (int i = 0; i < parameter_count; ++i) {
94 scope_info->set(index++, *scope->parameter(i)->name());
Steve Blocka7e24c12009-10-30 11:49:00 +000095 }
96
Ben Murdoch3ef787d2012-04-12 10:51:47 +010097 // Add stack locals' names. We are assuming that the stack locals'
98 // slots are allocated in increasing order, so we can simply add
99 // them to the ScopeInfo object.
100 ASSERT(index == scope_info->StackLocalEntriesIndex());
101 for (int i = 0; i < stack_local_count; ++i) {
102 ASSERT(stack_locals[i]->index() == i);
103 scope_info->set(index++, *stack_locals[i]->name());
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100104 }
Ben Murdoch85b71792012-04-11 18:30:58 +0100105
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100106 // Due to usage analysis, context-allocated locals are not necessarily in
107 // increasing order: Some of them may be parameters which are allocated before
108 // the non-parameter locals. When the non-parameter locals are sorted
109 // according to usage, the allocated slot indices may not be in increasing
110 // order with the variable list anymore. Thus, we first need to sort them by
111 // context slot index before adding them to the ScopeInfo object.
112 context_locals.Sort(&Variable::CompareIndex);
Ben Murdoch85b71792012-04-11 18:30:58 +0100113
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100114 // Add context locals' names.
115 ASSERT(index == scope_info->ContextLocalNameEntriesIndex());
116 for (int i = 0; i < context_local_count; ++i) {
117 scope_info->set(index++, *context_locals[i]->name());
Ben Murdoch85b71792012-04-11 18:30:58 +0100118 }
119
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100120 // Add context locals' info.
121 ASSERT(index == scope_info->ContextLocalInfoEntriesIndex());
122 for (int i = 0; i < context_local_count; ++i) {
123 Variable* var = context_locals[i];
124 uint32_t value = ContextLocalMode::encode(var->mode()) |
125 ContextLocalInitFlag::encode(var->initialization_flag());
126 scope_info->set(index++, Smi::FromInt(value));
Ben Murdoch85b71792012-04-11 18:30:58 +0100127 }
Ben Murdoch85b71792012-04-11 18:30:58 +0100128
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100129 // If present, add the function variable name and its index.
130 ASSERT(index == scope_info->FunctionNameEntryIndex());
131 if (has_function_name) {
132 int var_index = scope->function()->var()->index();
133 scope_info->set(index++, *scope->function()->name());
134 scope_info->set(index++, Smi::FromInt(var_index));
135 ASSERT(function_name_info != STACK ||
136 (var_index == scope_info->StackLocalCount() &&
137 var_index == scope_info->StackSlotCount() - 1));
138 ASSERT(function_name_info != CONTEXT ||
139 var_index == scope_info->ContextLength() - 1);
Ben Murdoch85b71792012-04-11 18:30:58 +0100140 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100141
142 ASSERT(index == scope_info->length());
143 ASSERT(scope->num_parameters() == scope_info->ParameterCount());
144 ASSERT(scope->num_stack_slots() == scope_info->StackSlotCount());
145 ASSERT(scope->num_heap_slots() == scope_info->ContextLength());
146 return scope_info;
Ben Murdoch85b71792012-04-11 18:30:58 +0100147}
148
149
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100150ScopeInfo* ScopeInfo::Empty() {
151 return reinterpret_cast<ScopeInfo*>(HEAP->empty_fixed_array());
Ben Murdoch85b71792012-04-11 18:30:58 +0100152}
153
154
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100155ScopeType ScopeInfo::Type() {
Ben Murdoch85b71792012-04-11 18:30:58 +0100156 ASSERT(length() > 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100157 return TypeField::decode(Flags());
Ben Murdoch85b71792012-04-11 18:30:58 +0100158}
159
160
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100161bool ScopeInfo::CallsEval() {
162 return length() > 0 && CallsEvalField::decode(Flags());
Ben Murdoch85b71792012-04-11 18:30:58 +0100163}
164
165
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100166LanguageMode ScopeInfo::language_mode() {
167 return length() > 0 ? LanguageModeField::decode(Flags()) : CLASSIC_MODE;
Ben Murdoch85b71792012-04-11 18:30:58 +0100168}
169
170
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100171int ScopeInfo::LocalCount() {
172 return StackLocalCount() + ContextLocalCount();
173}
174
175
176int ScopeInfo::StackSlotCount() {
Ben Murdoch85b71792012-04-11 18:30:58 +0100177 if (length() > 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100178 bool function_name_stack_slot =
179 FunctionVariableField::decode(Flags()) == STACK;
180 return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
Ben Murdoch85b71792012-04-11 18:30:58 +0100181 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100182 return 0;
183}
184
185
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100186int ScopeInfo::ContextLength() {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100187 if (length() > 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100188 int context_locals = ContextLocalCount();
189 bool function_name_context_slot =
190 FunctionVariableField::decode(Flags()) == CONTEXT;
191 bool has_context = context_locals > 0 ||
192 function_name_context_slot ||
193 Type() == WITH_SCOPE ||
194 (Type() == FUNCTION_SCOPE && CallsEval());
195 if (has_context) {
196 return Context::MIN_CONTEXT_SLOTS + context_locals +
197 (function_name_context_slot ? 1 : 0);
198 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100199 }
Ben Murdoch85b71792012-04-11 18:30:58 +0100200 return 0;
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100201}
202
203
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100204bool ScopeInfo::HasFunctionName() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000205 if (length() > 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100206 return NONE != FunctionVariableField::decode(Flags());
207 } else {
208 return false;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000209 }
210}
211
212
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100213bool ScopeInfo::HasHeapAllocatedLocals() {
214 if (length() > 0) {
215 return ContextLocalCount() > 0;
216 } else {
217 return false;
218 }
219}
220
221
222bool ScopeInfo::HasContext() {
223 if (length() > 0) {
224 return ContextLength() > 0;
225 } else {
226 return false;
227 }
228}
229
230
231String* ScopeInfo::FunctionName() {
232 ASSERT(HasFunctionName());
233 return String::cast(get(FunctionNameEntryIndex()));
234}
235
236
237String* ScopeInfo::ParameterName(int var) {
238 ASSERT(0 <= var && var < ParameterCount());
239 int info_index = ParameterEntriesIndex() + var;
240 return String::cast(get(info_index));
241}
242
243
244String* ScopeInfo::LocalName(int var) {
245 ASSERT(0 <= var && var < LocalCount());
246 ASSERT(StackLocalEntriesIndex() + StackLocalCount() ==
247 ContextLocalNameEntriesIndex());
248 int info_index = StackLocalEntriesIndex() + var;
249 return String::cast(get(info_index));
250}
251
252
253String* ScopeInfo::StackLocalName(int var) {
254 ASSERT(0 <= var && var < StackLocalCount());
255 int info_index = StackLocalEntriesIndex() + var;
256 return String::cast(get(info_index));
257}
258
259
260String* ScopeInfo::ContextLocalName(int var) {
261 ASSERT(0 <= var && var < ContextLocalCount());
262 int info_index = ContextLocalNameEntriesIndex() + var;
263 return String::cast(get(info_index));
264}
265
266
267VariableMode ScopeInfo::ContextLocalMode(int var) {
268 ASSERT(0 <= var && var < ContextLocalCount());
269 int info_index = ContextLocalInfoEntriesIndex() + var;
270 int value = Smi::cast(get(info_index))->value();
271 return ContextLocalMode::decode(value);
272}
273
274
275InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
276 ASSERT(0 <= var && var < ContextLocalCount());
277 int info_index = ContextLocalInfoEntriesIndex() + var;
278 int value = Smi::cast(get(info_index))->value();
279 return ContextLocalInitFlag::decode(value);
280}
281
282
283int ScopeInfo::StackSlotIndex(String* name) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100284 ASSERT(name->IsSymbol());
285 if (length() > 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100286 int start = StackLocalEntriesIndex();
287 int end = StackLocalEntriesIndex() + StackLocalCount();
288 for (int i = start; i < end; ++i) {
289 if (name == get(i)) {
290 return i - start;
291 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100292 }
293 }
294 return -1;
295}
296
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100297
298int ScopeInfo::ContextSlotIndex(String* name,
299 VariableMode* mode,
300 InitializationFlag* init_flag) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100301 ASSERT(name->IsSymbol());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100302 ASSERT(mode != NULL);
303 ASSERT(init_flag != NULL);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100304 if (length() > 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100305 ContextSlotCache* context_slot_cache = GetIsolate()->context_slot_cache();
306 int result = context_slot_cache->Lookup(this, name, mode, init_flag);
307 if (result != ContextSlotCache::kNotFound) {
308 ASSERT(result < ContextLength());
309 return result;
310 }
311
312 int start = ContextLocalNameEntriesIndex();
313 int end = ContextLocalNameEntriesIndex() + ContextLocalCount();
314 for (int i = start; i < end; ++i) {
315 if (name == get(i)) {
316 int var = i - start;
317 *mode = ContextLocalMode(var);
318 *init_flag = ContextLocalInitFlag(var);
319 result = Context::MIN_CONTEXT_SLOTS + var;
320 context_slot_cache->Update(this, name, *mode, *init_flag, result);
321 ASSERT(result < ContextLength());
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100322 return result;
323 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100324 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100325 context_slot_cache->Update(this, name, INTERNAL, kNeedsInitialization, -1);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100326 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100327 return -1;
328}
329
330
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100331int ScopeInfo::ParameterIndex(String* name) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100332 ASSERT(name->IsSymbol());
333 if (length() > 0) {
334 // We must read parameters from the end since for
335 // multiply declared parameters the value of the
336 // last declaration of that parameter is used
337 // inside a function (and thus we need to look
338 // at the last index). Was bug# 1110337.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100339 int start = ParameterEntriesIndex();
340 int end = ParameterEntriesIndex() + ParameterCount();
341 for (int i = end - 1; i >= start; --i) {
342 if (name == get(i)) {
343 return i - start;
344 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100345 }
346 }
347 return -1;
348}
349
350
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100351int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100352 ASSERT(name->IsSymbol());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100353 ASSERT(mode != NULL);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100354 if (length() > 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100355 if (FunctionVariableField::decode(Flags()) == CONTEXT &&
356 FunctionName() == name) {
357 *mode = FunctionVariableMode::decode(Flags());
358 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100359 }
360 }
361 return -1;
362}
363
364
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100365int ScopeInfo::ParameterEntriesIndex() {
366 ASSERT(length() > 0);
367 return kVariablePartIndex;
368}
369
370
371int ScopeInfo::StackLocalEntriesIndex() {
372 return ParameterEntriesIndex() + ParameterCount();
373}
374
375
376int ScopeInfo::ContextLocalNameEntriesIndex() {
377 return StackLocalEntriesIndex() + StackLocalCount();
378}
379
380
381int ScopeInfo::ContextLocalInfoEntriesIndex() {
382 return ContextLocalNameEntriesIndex() + ContextLocalCount();
383}
384
385
386int ScopeInfo::FunctionNameEntryIndex() {
387 return ContextLocalInfoEntriesIndex() + ContextLocalCount();
388}
389
390
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100391int ContextSlotCache::Hash(Object* data, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 // Uses only lower 32 bits if pointers are larger.
393 uintptr_t addr_hash =
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100394 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
Andrei Popescu402d9372010-02-26 13:31:12 +0000395 return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
Steve Blocka7e24c12009-10-30 11:49:00 +0000396}
397
398
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100399int ContextSlotCache::Lookup(Object* data,
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 String* name,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100401 VariableMode* mode,
402 InitializationFlag* init_flag) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100403 int index = Hash(data, name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 Key& key = keys_[index];
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100405 if ((key.data == data) && key.name->Equals(name)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 Value result(values_[index]);
407 if (mode != NULL) *mode = result.mode();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100408 if (init_flag != NULL) *init_flag = result.initialization_flag();
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 return result.index() + kNotFound;
410 }
411 return kNotFound;
412}
413
414
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100415void ContextSlotCache::Update(Object* data,
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 String* name,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100417 VariableMode mode,
418 InitializationFlag init_flag,
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 int slot_index) {
420 String* symbol;
421 ASSERT(slot_index > kNotFound);
Steve Block44f0eee2011-05-26 01:26:41 +0100422 if (HEAP->LookupSymbolIfExists(name, &symbol)) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100423 int index = Hash(data, symbol);
Steve Blocka7e24c12009-10-30 11:49:00 +0000424 Key& key = keys_[index];
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100425 key.data = data;
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 key.name = symbol;
427 // Please note value only takes a uint as index.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100428 values_[index] = Value(mode, init_flag, slot_index - kNotFound).raw();
Steve Blocka7e24c12009-10-30 11:49:00 +0000429#ifdef DEBUG
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100430 ValidateEntry(data, name, mode, init_flag, slot_index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000431#endif
432 }
433}
434
435
436void ContextSlotCache::Clear() {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100437 for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000438}
439
440
Steve Blocka7e24c12009-10-30 11:49:00 +0000441#ifdef DEBUG
442
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100443void ContextSlotCache::ValidateEntry(Object* data,
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 String* name,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100445 VariableMode mode,
446 InitializationFlag init_flag,
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 int slot_index) {
448 String* symbol;
Steve Block44f0eee2011-05-26 01:26:41 +0100449 if (HEAP->LookupSymbolIfExists(name, &symbol)) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100450 int index = Hash(data, name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 Key& key = keys_[index];
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100452 ASSERT(key.data == data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 ASSERT(key.name->Equals(name));
454 Value result(values_[index]);
455 ASSERT(result.mode() == mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100456 ASSERT(result.initialization_flag() == init_flag);
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 ASSERT(result.index() + kNotFound == slot_index);
458 }
459}
460
461
Steve Blocka7e24c12009-10-30 11:49:00 +0000462static void PrintList(const char* list_name,
463 int nof_internal_slots,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100464 int start,
465 int end,
466 ScopeInfo* scope_info) {
467 if (start < end) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 PrintF("\n // %s\n", list_name);
469 if (nof_internal_slots > 0) {
470 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
471 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100472 for (int i = nof_internal_slots; start < end; ++i, ++start) {
473 PrintF(" %2d ", i);
474 String::cast(scope_info->get(start))->ShortPrint();
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 PrintF("\n");
476 }
477 }
478}
479
480
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100481void ScopeInfo::Print() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 PrintF("ScopeInfo ");
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100483 if (HasFunctionName()) {
484 FunctionName()->ShortPrint();
485 } else {
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 PrintF("/* no function name */");
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100487 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 PrintF("{");
489
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100490 PrintList("parameters", 0,
491 ParameterEntriesIndex(),
492 ParameterEntriesIndex() + ParameterCount(),
493 this);
494 PrintList("stack slots", 0,
495 StackLocalEntriesIndex(),
496 StackLocalEntriesIndex() + StackLocalCount(),
497 this);
498 PrintList("context slots",
499 Context::MIN_CONTEXT_SLOTS,
500 ContextLocalNameEntriesIndex(),
501 ContextLocalNameEntriesIndex() + ContextLocalCount(),
502 this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000503
504 PrintF("}\n");
505}
506#endif // DEBUG
507
Steve Blocka7e24c12009-10-30 11:49:00 +0000508} } // namespace v8::internal