blob: c9df1fb5801792881e256b11ac74ed6b2dc68dc7 [file] [log] [blame]
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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
whesse@chromium.org030d38e2011-07-13 13:23:34 +000035#include "allocation-inl.h"
36
kasperl@chromium.org71affb52009-05-26 05:44:31 +000037namespace v8 {
38namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
40
mmassi@chromium.org7028c052012-06-13 11:51:58 +000041Handle<ScopeInfo> ScopeInfo::Create(Scope* scope, Zone* zone) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000042 // Collect stack and context locals.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000043 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
44 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000045 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);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000052 // 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) {
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000056 Variable* var = scope->function()->proxy()->var();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000057 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 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000071 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
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000077 Factory* factory = Isolate::Current()->factory();
78 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000079
80 // Encode the flags.
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000081 int flags = ScopeTypeField::encode(scope->scope_type()) |
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000082 CallsEvalField::encode(scope->calls_eval()) |
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000083 LanguageModeField::encode(scope->language_mode()) |
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000084 FunctionVariableField::encode(function_name_info) |
85 FunctionVariableMode::encode(function_variable_mode);
86 scope_info->SetFlags(flags);
87 scope_info->SetParameterCount(parameter_count);
88 scope_info->SetStackLocalCount(stack_local_count);
89 scope_info->SetContextLocalCount(context_local_count);
90
91 int index = kVariablePartIndex;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092 // Add parameters.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000093 ASSERT(index == scope_info->ParameterEntriesIndex());
94 for (int i = 0; i < parameter_count; ++i) {
95 scope_info->set(index++, *scope->parameter(i)->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096 }
97
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000098 // Add stack locals' names. We are assuming that the stack locals'
99 // slots are allocated in increasing order, so we can simply add
100 // them to the ScopeInfo object.
101 ASSERT(index == scope_info->StackLocalEntriesIndex());
102 for (int i = 0; i < stack_local_count; ++i) {
103 ASSERT(stack_locals[i]->index() == i);
104 scope_info->set(index++, *stack_locals[i]->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000105 }
106
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000107 // Due to usage analysis, context-allocated locals are not necessarily in
108 // increasing order: Some of them may be parameters which are allocated before
109 // the non-parameter locals. When the non-parameter locals are sorted
110 // according to usage, the allocated slot indices may not be in increasing
111 // order with the variable list anymore. Thus, we first need to sort them by
112 // context slot index before adding them to the ScopeInfo object.
113 context_locals.Sort(&Variable::CompareIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000115 // Add context locals' names.
116 ASSERT(index == scope_info->ContextLocalNameEntriesIndex());
117 for (int i = 0; i < context_local_count; ++i) {
118 scope_info->set(index++, *context_locals[i]->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119 }
120
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000121 // Add context locals' info.
122 ASSERT(index == scope_info->ContextLocalInfoEntriesIndex());
123 for (int i = 0; i < context_local_count; ++i) {
124 Variable* var = context_locals[i];
125 uint32_t value = ContextLocalMode::encode(var->mode()) |
126 ContextLocalInitFlag::encode(var->initialization_flag());
127 scope_info->set(index++, Smi::FromInt(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000130 // If present, add the function variable name and its index.
131 ASSERT(index == scope_info->FunctionNameEntryIndex());
132 if (has_function_name) {
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000133 int var_index = scope->function()->proxy()->var()->index();
134 scope_info->set(index++, *scope->function()->proxy()->name());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000135 scope_info->set(index++, Smi::FromInt(var_index));
136 ASSERT(function_name_info != STACK ||
137 (var_index == scope_info->StackLocalCount() &&
138 var_index == scope_info->StackSlotCount() - 1));
139 ASSERT(function_name_info != CONTEXT ||
140 var_index == scope_info->ContextLength() - 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000142
143 ASSERT(index == scope_info->length());
144 ASSERT(scope->num_parameters() == scope_info->ParameterCount());
145 ASSERT(scope->num_stack_slots() == scope_info->StackSlotCount());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000146 ASSERT(scope->num_heap_slots() == scope_info->ContextLength() ||
147 (scope->num_heap_slots() == kVariablePartIndex &&
148 scope_info->ContextLength() == 0));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000149 return scope_info;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000150}
151
152
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000153ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
154 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155}
156
157
ulan@chromium.orgdfe53072013-06-06 14:14:51 +0000158ScopeType ScopeInfo::scope_type() {
ager@chromium.orgb5737492010-07-15 09:29:43 +0000159 ASSERT(length() > 0);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +0000160 return ScopeTypeField::decode(Flags());
ager@chromium.orgb5737492010-07-15 09:29:43 +0000161}
162
163
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000164bool ScopeInfo::CallsEval() {
165 return length() > 0 && CallsEvalField::decode(Flags());
ager@chromium.orgb5737492010-07-15 09:29:43 +0000166}
167
168
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000169LanguageMode ScopeInfo::language_mode() {
170 return length() > 0 ? LanguageModeField::decode(Flags()) : CLASSIC_MODE;
ager@chromium.orgb5737492010-07-15 09:29:43 +0000171}
172
173
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000174int ScopeInfo::LocalCount() {
175 return StackLocalCount() + ContextLocalCount();
176}
177
178
179int ScopeInfo::StackSlotCount() {
ager@chromium.orgb5737492010-07-15 09:29:43 +0000180 if (length() > 0) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000181 bool function_name_stack_slot =
182 FunctionVariableField::decode(Flags()) == STACK;
183 return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
ager@chromium.orgb5737492010-07-15 09:29:43 +0000184 }
185 return 0;
186}
187
188
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000189int ScopeInfo::ContextLength() {
ager@chromium.orgb5737492010-07-15 09:29:43 +0000190 if (length() > 0) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000191 int context_locals = ContextLocalCount();
192 bool function_name_context_slot =
193 FunctionVariableField::decode(Flags()) == CONTEXT;
194 bool has_context = context_locals > 0 ||
195 function_name_context_slot ||
ulan@chromium.orgdfe53072013-06-06 14:14:51 +0000196 scope_type() == WITH_SCOPE ||
197 (scope_type() == FUNCTION_SCOPE && CallsEval()) ||
198 scope_type() == MODULE_SCOPE;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000199 if (has_context) {
200 return Context::MIN_CONTEXT_SLOTS + context_locals +
201 (function_name_context_slot ? 1 : 0);
202 }
ager@chromium.orgb5737492010-07-15 09:29:43 +0000203 }
204 return 0;
205}
206
207
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000208bool ScopeInfo::HasFunctionName() {
ager@chromium.orgb5737492010-07-15 09:29:43 +0000209 if (length() > 0) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000210 return NONE != FunctionVariableField::decode(Flags());
211 } else {
212 return false;
ager@chromium.orgb5737492010-07-15 09:29:43 +0000213 }
ager@chromium.orgb5737492010-07-15 09:29:43 +0000214}
215
216
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000217bool ScopeInfo::HasHeapAllocatedLocals() {
218 if (length() > 0) {
219 return ContextLocalCount() > 0;
220 } else {
221 return false;
222 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000223}
224
225
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000226bool ScopeInfo::HasContext() {
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000227 return ContextLength() > 0;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000228}
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) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000284 ASSERT(name->IsInternalizedString());
ager@chromium.orgb5737492010-07-15 09:29:43 +0000285 if (length() > 0) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000286 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 }
ager@chromium.orgb5737492010-07-15 09:29:43 +0000292 }
293 }
294 return -1;
295}
296
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000297
298int ScopeInfo::ContextSlotIndex(String* name,
299 VariableMode* mode,
300 InitializationFlag* init_flag) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000301 ASSERT(name->IsInternalizedString());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000302 ASSERT(mode != NULL);
303 ASSERT(init_flag != NULL);
ager@chromium.orgb5737492010-07-15 09:29:43 +0000304 if (length() > 0) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000305 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());
ager@chromium.orgb5737492010-07-15 09:29:43 +0000322 return result;
323 }
ager@chromium.orgb5737492010-07-15 09:29:43 +0000324 }
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000325 // Cache as not found. Mode and init flag don't matter.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000326 context_slot_cache->Update(this, name, INTERNAL, kNeedsInitialization, -1);
ager@chromium.orgb5737492010-07-15 09:29:43 +0000327 }
ager@chromium.orgb5737492010-07-15 09:29:43 +0000328 return -1;
329}
330
331
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000332int ScopeInfo::ParameterIndex(String* name) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000333 ASSERT(name->IsInternalizedString());
ager@chromium.orgb5737492010-07-15 09:29:43 +0000334 if (length() > 0) {
335 // We must read parameters from the end since for
336 // multiply declared parameters the value of the
337 // last declaration of that parameter is used
338 // inside a function (and thus we need to look
339 // at the last index). Was bug# 1110337.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000340 int start = ParameterEntriesIndex();
341 int end = ParameterEntriesIndex() + ParameterCount();
342 for (int i = end - 1; i >= start; --i) {
343 if (name == get(i)) {
344 return i - start;
345 }
ager@chromium.orgb5737492010-07-15 09:29:43 +0000346 }
347 }
348 return -1;
349}
350
351
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000352int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000353 ASSERT(name->IsInternalizedString());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000354 ASSERT(mode != NULL);
ager@chromium.orgb5737492010-07-15 09:29:43 +0000355 if (length() > 0) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000356 if (FunctionVariableField::decode(Flags()) == CONTEXT &&
357 FunctionName() == name) {
358 *mode = FunctionVariableMode::decode(Flags());
359 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
ager@chromium.orgb5737492010-07-15 09:29:43 +0000360 }
361 }
362 return -1;
363}
364
365
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +0000366bool ScopeInfo::CopyContextLocalsToScopeObject(
367 Isolate* isolate,
368 Handle<Context> context,
369 Handle<JSObject> scope_object) {
370 int local_count = ContextLocalCount();
371 if (local_count == 0) return true;
372 // Fill all context locals to the context extension.
373 int start = ContextLocalNameEntriesIndex();
374 int end = start + local_count;
375 for (int i = start; i < end; ++i) {
376 int context_index = Context::MIN_CONTEXT_SLOTS + i - start;
377 RETURN_IF_EMPTY_HANDLE_VALUE(
378 isolate,
379 SetProperty(isolate,
380 scope_object,
381 Handle<String>(String::cast(get(i))),
382 Handle<Object>(context->get(context_index), isolate),
383 ::NONE,
384 kNonStrictMode),
385 false);
386 }
387 return true;
388}
389
390
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000391int ScopeInfo::ParameterEntriesIndex() {
392 ASSERT(length() > 0);
393 return kVariablePartIndex;
394}
395
396
397int ScopeInfo::StackLocalEntriesIndex() {
398 return ParameterEntriesIndex() + ParameterCount();
399}
400
401
402int ScopeInfo::ContextLocalNameEntriesIndex() {
403 return StackLocalEntriesIndex() + StackLocalCount();
404}
405
406
407int ScopeInfo::ContextLocalInfoEntriesIndex() {
408 return ContextLocalNameEntriesIndex() + ContextLocalCount();
409}
410
411
412int ScopeInfo::FunctionNameEntryIndex() {
413 return ContextLocalInfoEntriesIndex() + ContextLocalCount();
414}
415
416
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000417int ContextSlotCache::Hash(Object* data, String* name) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000418 // Uses only lower 32 bits if pointers are larger.
419 uintptr_t addr_hash =
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000420 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000421 return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000422}
423
424
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000425int ContextSlotCache::Lookup(Object* data,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000426 String* name,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000427 VariableMode* mode,
428 InitializationFlag* init_flag) {
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000429 int index = Hash(data, name);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000430 Key& key = keys_[index];
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000431 if ((key.data == data) && key.name->Equals(name)) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000432 Value result(values_[index]);
433 if (mode != NULL) *mode = result.mode();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000434 if (init_flag != NULL) *init_flag = result.initialization_flag();
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000435 return result.index() + kNotFound;
436 }
437 return kNotFound;
438}
439
440
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000441void ContextSlotCache::Update(Object* data,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000442 String* name,
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000443 VariableMode mode,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000444 InitializationFlag init_flag,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000445 int slot_index) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000446 String* internalized_name;
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000447 ASSERT(slot_index > kNotFound);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000448 if (HEAP->InternalizeStringIfExists(name, &internalized_name)) {
449 int index = Hash(data, internalized_name);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000450 Key& key = keys_[index];
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000451 key.data = data;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000452 key.name = internalized_name;
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000453 // Please note value only takes a uint as index.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000454 values_[index] = Value(mode, init_flag, slot_index - kNotFound).raw();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455#ifdef DEBUG
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000456 ValidateEntry(data, name, mode, init_flag, slot_index);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000457#endif
458 }
459}
460
461
462void ContextSlotCache::Clear() {
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000463 for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000464}
465
466
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000467#ifdef DEBUG
468
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000469void ContextSlotCache::ValidateEntry(Object* data,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000470 String* name,
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000471 VariableMode mode,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000472 InitializationFlag init_flag,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000473 int slot_index) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000474 String* internalized_name;
475 if (HEAP->InternalizeStringIfExists(name, &internalized_name)) {
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000476 int index = Hash(data, name);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000477 Key& key = keys_[index];
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000478 ASSERT(key.data == data);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000479 ASSERT(key.name->Equals(name));
480 Value result(values_[index]);
481 ASSERT(result.mode() == mode);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000482 ASSERT(result.initialization_flag() == init_flag);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000483 ASSERT(result.index() + kNotFound == slot_index);
484 }
485}
486
487
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488static void PrintList(const char* list_name,
489 int nof_internal_slots,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000490 int start,
491 int end,
492 ScopeInfo* scope_info) {
493 if (start < end) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000494 PrintF("\n // %s\n", list_name);
495 if (nof_internal_slots > 0) {
496 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
497 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000498 for (int i = nof_internal_slots; start < end; ++i, ++start) {
499 PrintF(" %2d ", i);
500 String::cast(scope_info->get(start))->ShortPrint();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 PrintF("\n");
502 }
503 }
504}
505
506
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000507void ScopeInfo::Print() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508 PrintF("ScopeInfo ");
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000509 if (HasFunctionName()) {
510 FunctionName()->ShortPrint();
511 } else {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000512 PrintF("/* no function name */");
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000513 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000514 PrintF("{");
515
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000516 PrintList("parameters", 0,
517 ParameterEntriesIndex(),
518 ParameterEntriesIndex() + ParameterCount(),
519 this);
520 PrintList("stack slots", 0,
521 StackLocalEntriesIndex(),
522 StackLocalEntriesIndex() + StackLocalCount(),
523 this);
524 PrintList("context slots",
525 Context::MIN_CONTEXT_SLOTS,
526 ContextLocalNameEntriesIndex(),
527 ContextLocalNameEntriesIndex() + ContextLocalCount(),
528 this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529
530 PrintF("}\n");
531}
532#endif // DEBUG
533
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000534
535//---------------------------------------------------------------------------
536// ModuleInfo.
537
538Handle<ModuleInfo> ModuleInfo::Create(
539 Isolate* isolate, Interface* interface, Scope* scope) {
540 Handle<ModuleInfo> info = Allocate(isolate, interface->Length());
541 info->set_host_index(interface->Index());
542 int i = 0;
543 for (Interface::Iterator it = interface->iterator();
544 !it.done(); it.Advance(), ++i) {
545 Variable* var = scope->LocalLookup(it.name());
546 info->set_name(i, *it.name());
547 info->set_mode(i, var->mode());
548 ASSERT((var->mode() == MODULE) == (it.interface()->IsModule()));
549 if (var->mode() == MODULE) {
550 ASSERT(it.interface()->IsFrozen());
551 ASSERT(it.interface()->Index() >= 0);
552 info->set_index(i, it.interface()->Index());
553 } else {
554 ASSERT(var->index() >= 0);
555 info->set_index(i, var->index());
556 }
557 }
558 ASSERT(i == info->length());
559 return info;
560}
561
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000562} } // namespace v8::internal