OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/scopeinfo.h" | 9 #include "src/scopeinfo.h" |
10 #include "src/scopes.h" | 10 #include "src/scopes.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 // Add context locals' names. | 90 // Add context locals' names. |
91 ASSERT(index == scope_info->ContextLocalNameEntriesIndex()); | 91 ASSERT(index == scope_info->ContextLocalNameEntriesIndex()); |
92 for (int i = 0; i < context_local_count; ++i) { | 92 for (int i = 0; i < context_local_count; ++i) { |
93 scope_info->set(index++, *context_locals[i]->name()); | 93 scope_info->set(index++, *context_locals[i]->name()); |
94 } | 94 } |
95 | 95 |
96 // Add context locals' info. | 96 // Add context locals' info. |
97 ASSERT(index == scope_info->ContextLocalInfoEntriesIndex()); | 97 ASSERT(index == scope_info->ContextLocalInfoEntriesIndex()); |
98 for (int i = 0; i < context_local_count; ++i) { | 98 for (int i = 0; i < context_local_count; ++i) { |
99 Variable* var = context_locals[i]; | 99 Variable* var = context_locals[i]; |
100 uint32_t value = ContextLocalMode::encode(var->mode()) | | 100 uint32_t value = |
101 ContextLocalInitFlag::encode(var->initialization_flag()); | 101 ContextLocalMode::encode(var->mode()) | |
| 102 ContextLocalInitFlag::encode(var->initialization_flag()) | |
| 103 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); |
102 scope_info->set(index++, Smi::FromInt(value)); | 104 scope_info->set(index++, Smi::FromInt(value)); |
103 } | 105 } |
104 | 106 |
105 // If present, add the function variable name and its index. | 107 // If present, add the function variable name and its index. |
106 ASSERT(index == scope_info->FunctionNameEntryIndex()); | 108 ASSERT(index == scope_info->FunctionNameEntryIndex()); |
107 if (has_function_name) { | 109 if (has_function_name) { |
108 int var_index = scope->function()->proxy()->var()->index(); | 110 int var_index = scope->function()->proxy()->var()->index(); |
109 scope_info->set(index++, *scope->function()->proxy()->name()); | 111 scope_info->set(index++, *scope->function()->proxy()->name()); |
110 scope_info->set(index++, Smi::FromInt(var_index)); | 112 scope_info->set(index++, Smi::FromInt(var_index)); |
111 ASSERT(function_name_info != STACK || | 113 ASSERT(function_name_info != STACK || |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 | 250 |
249 | 251 |
250 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { | 252 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { |
251 ASSERT(0 <= var && var < ContextLocalCount()); | 253 ASSERT(0 <= var && var < ContextLocalCount()); |
252 int info_index = ContextLocalInfoEntriesIndex() + var; | 254 int info_index = ContextLocalInfoEntriesIndex() + var; |
253 int value = Smi::cast(get(info_index))->value(); | 255 int value = Smi::cast(get(info_index))->value(); |
254 return ContextLocalInitFlag::decode(value); | 256 return ContextLocalInitFlag::decode(value); |
255 } | 257 } |
256 | 258 |
257 | 259 |
| 260 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { |
| 261 ASSERT(0 <= var && var < ContextLocalCount()); |
| 262 int info_index = ContextLocalInfoEntriesIndex() + var; |
| 263 int value = Smi::cast(get(info_index))->value(); |
| 264 return ContextLocalMaybeAssignedFlag::decode(value); |
| 265 } |
| 266 |
| 267 |
258 bool ScopeInfo::LocalIsSynthetic(int var) { | 268 bool ScopeInfo::LocalIsSynthetic(int var) { |
259 ASSERT(0 <= var && var < LocalCount()); | 269 ASSERT(0 <= var && var < LocalCount()); |
260 // There's currently no flag stored on the ScopeInfo to indicate that a | 270 // There's currently no flag stored on the ScopeInfo to indicate that a |
261 // variable is a compiler-introduced temporary. However, to avoid conflict | 271 // variable is a compiler-introduced temporary. However, to avoid conflict |
262 // with user declarations, the current temporaries like .generator_object and | 272 // with user declarations, the current temporaries like .generator_object and |
263 // .result start with a dot, so we can use that as a flag. It's a hack! | 273 // .result start with a dot, so we can use that as a flag. It's a hack! |
264 Handle<String> name(LocalName(var)); | 274 Handle<String> name(LocalName(var)); |
265 return name->length() > 0 && name->Get(0) == '.'; | 275 return name->length() > 0 && name->Get(0) == '.'; |
266 } | 276 } |
267 | 277 |
268 | 278 |
269 int ScopeInfo::StackSlotIndex(String* name) { | 279 int ScopeInfo::StackSlotIndex(String* name) { |
270 ASSERT(name->IsInternalizedString()); | 280 ASSERT(name->IsInternalizedString()); |
271 if (length() > 0) { | 281 if (length() > 0) { |
272 int start = StackLocalEntriesIndex(); | 282 int start = StackLocalEntriesIndex(); |
273 int end = StackLocalEntriesIndex() + StackLocalCount(); | 283 int end = StackLocalEntriesIndex() + StackLocalCount(); |
274 for (int i = start; i < end; ++i) { | 284 for (int i = start; i < end; ++i) { |
275 if (name == get(i)) { | 285 if (name == get(i)) { |
276 return i - start; | 286 return i - start; |
277 } | 287 } |
278 } | 288 } |
279 } | 289 } |
280 return -1; | 290 return -1; |
281 } | 291 } |
282 | 292 |
283 | 293 |
284 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, | 294 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, |
285 Handle<String> name, | 295 Handle<String> name, VariableMode* mode, |
286 VariableMode* mode, | 296 InitializationFlag* init_flag, |
287 InitializationFlag* init_flag) { | 297 MaybeAssignedFlag* maybe_assigned_flag) { |
288 ASSERT(name->IsInternalizedString()); | 298 ASSERT(name->IsInternalizedString()); |
289 ASSERT(mode != NULL); | 299 ASSERT(mode != NULL); |
290 ASSERT(init_flag != NULL); | 300 ASSERT(init_flag != NULL); |
291 if (scope_info->length() > 0) { | 301 if (scope_info->length() > 0) { |
292 ContextSlotCache* context_slot_cache = | 302 ContextSlotCache* context_slot_cache = |
293 scope_info->GetIsolate()->context_slot_cache(); | 303 scope_info->GetIsolate()->context_slot_cache(); |
294 int result = | 304 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, |
295 context_slot_cache->Lookup(*scope_info, *name, mode, init_flag); | 305 maybe_assigned_flag); |
296 if (result != ContextSlotCache::kNotFound) { | 306 if (result != ContextSlotCache::kNotFound) { |
297 ASSERT(result < scope_info->ContextLength()); | 307 ASSERT(result < scope_info->ContextLength()); |
298 return result; | 308 return result; |
299 } | 309 } |
300 | 310 |
301 int start = scope_info->ContextLocalNameEntriesIndex(); | 311 int start = scope_info->ContextLocalNameEntriesIndex(); |
302 int end = scope_info->ContextLocalNameEntriesIndex() + | 312 int end = scope_info->ContextLocalNameEntriesIndex() + |
303 scope_info->ContextLocalCount(); | 313 scope_info->ContextLocalCount(); |
304 for (int i = start; i < end; ++i) { | 314 for (int i = start; i < end; ++i) { |
305 if (*name == scope_info->get(i)) { | 315 if (*name == scope_info->get(i)) { |
306 int var = i - start; | 316 int var = i - start; |
307 *mode = scope_info->ContextLocalMode(var); | 317 *mode = scope_info->ContextLocalMode(var); |
308 *init_flag = scope_info->ContextLocalInitFlag(var); | 318 *init_flag = scope_info->ContextLocalInitFlag(var); |
| 319 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); |
309 result = Context::MIN_CONTEXT_SLOTS + var; | 320 result = Context::MIN_CONTEXT_SLOTS + var; |
310 context_slot_cache->Update(scope_info, name, *mode, *init_flag, result); | 321 context_slot_cache->Update(scope_info, name, *mode, *init_flag, |
| 322 *maybe_assigned_flag, result); |
311 ASSERT(result < scope_info->ContextLength()); | 323 ASSERT(result < scope_info->ContextLength()); |
312 return result; | 324 return result; |
313 } | 325 } |
314 } | 326 } |
315 // Cache as not found. Mode and init flag don't matter. | 327 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. |
316 context_slot_cache->Update( | 328 context_slot_cache->Update(scope_info, name, INTERNAL, kNeedsInitialization, |
317 scope_info, name, INTERNAL, kNeedsInitialization, -1); | 329 kNotAssigned, -1); |
318 } | 330 } |
319 return -1; | 331 return -1; |
320 } | 332 } |
321 | 333 |
322 | 334 |
323 int ScopeInfo::ParameterIndex(String* name) { | 335 int ScopeInfo::ParameterIndex(String* name) { |
324 ASSERT(name->IsInternalizedString()); | 336 ASSERT(name->IsInternalizedString()); |
325 if (length() > 0) { | 337 if (length() > 0) { |
326 // We must read parameters from the end since for | 338 // We must read parameters from the end since for |
327 // multiply declared parameters the value of the | 339 // multiply declared parameters the value of the |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 418 |
407 | 419 |
408 int ContextSlotCache::Hash(Object* data, String* name) { | 420 int ContextSlotCache::Hash(Object* data, String* name) { |
409 // Uses only lower 32 bits if pointers are larger. | 421 // Uses only lower 32 bits if pointers are larger. |
410 uintptr_t addr_hash = | 422 uintptr_t addr_hash = |
411 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; | 423 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; |
412 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); | 424 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); |
413 } | 425 } |
414 | 426 |
415 | 427 |
416 int ContextSlotCache::Lookup(Object* data, | 428 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode, |
417 String* name, | 429 InitializationFlag* init_flag, |
418 VariableMode* mode, | 430 MaybeAssignedFlag* maybe_assigned_flag) { |
419 InitializationFlag* init_flag) { | |
420 int index = Hash(data, name); | 431 int index = Hash(data, name); |
421 Key& key = keys_[index]; | 432 Key& key = keys_[index]; |
422 if ((key.data == data) && key.name->Equals(name)) { | 433 if ((key.data == data) && key.name->Equals(name)) { |
423 Value result(values_[index]); | 434 Value result(values_[index]); |
424 if (mode != NULL) *mode = result.mode(); | 435 if (mode != NULL) *mode = result.mode(); |
425 if (init_flag != NULL) *init_flag = result.initialization_flag(); | 436 if (init_flag != NULL) *init_flag = result.initialization_flag(); |
| 437 if (maybe_assigned_flag != NULL) |
| 438 *maybe_assigned_flag = result.maybe_assigned_flag(); |
426 return result.index() + kNotFound; | 439 return result.index() + kNotFound; |
427 } | 440 } |
428 return kNotFound; | 441 return kNotFound; |
429 } | 442 } |
430 | 443 |
431 | 444 |
432 void ContextSlotCache::Update(Handle<Object> data, | 445 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name, |
433 Handle<String> name, | 446 VariableMode mode, InitializationFlag init_flag, |
434 VariableMode mode, | 447 MaybeAssignedFlag maybe_assigned_flag, |
435 InitializationFlag init_flag, | |
436 int slot_index) { | 448 int slot_index) { |
437 DisallowHeapAllocation no_gc; | 449 DisallowHeapAllocation no_gc; |
438 Handle<String> internalized_name; | 450 Handle<String> internalized_name; |
439 ASSERT(slot_index > kNotFound); | 451 ASSERT(slot_index > kNotFound); |
440 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name). | 452 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name). |
441 ToHandle(&internalized_name)) { | 453 ToHandle(&internalized_name)) { |
442 int index = Hash(*data, *internalized_name); | 454 int index = Hash(*data, *internalized_name); |
443 Key& key = keys_[index]; | 455 Key& key = keys_[index]; |
444 key.data = *data; | 456 key.data = *data; |
445 key.name = *internalized_name; | 457 key.name = *internalized_name; |
446 // Please note value only takes a uint as index. | 458 // Please note value only takes a uint as index. |
447 values_[index] = Value(mode, init_flag, slot_index - kNotFound).raw(); | 459 values_[index] = Value(mode, init_flag, maybe_assigned_flag, |
| 460 slot_index - kNotFound).raw(); |
448 #ifdef DEBUG | 461 #ifdef DEBUG |
449 ValidateEntry(data, name, mode, init_flag, slot_index); | 462 ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index); |
450 #endif | 463 #endif |
451 } | 464 } |
452 } | 465 } |
453 | 466 |
454 | 467 |
455 void ContextSlotCache::Clear() { | 468 void ContextSlotCache::Clear() { |
456 for (int index = 0; index < kLength; index++) keys_[index].data = NULL; | 469 for (int index = 0; index < kLength; index++) keys_[index].data = NULL; |
457 } | 470 } |
458 | 471 |
459 | 472 |
460 #ifdef DEBUG | 473 #ifdef DEBUG |
461 | 474 |
462 void ContextSlotCache::ValidateEntry(Handle<Object> data, | 475 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name, |
463 Handle<String> name, | |
464 VariableMode mode, | 476 VariableMode mode, |
465 InitializationFlag init_flag, | 477 InitializationFlag init_flag, |
| 478 MaybeAssignedFlag maybe_assigned_flag, |
466 int slot_index) { | 479 int slot_index) { |
467 DisallowHeapAllocation no_gc; | 480 DisallowHeapAllocation no_gc; |
468 Handle<String> internalized_name; | 481 Handle<String> internalized_name; |
469 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name). | 482 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name). |
470 ToHandle(&internalized_name)) { | 483 ToHandle(&internalized_name)) { |
471 int index = Hash(*data, *name); | 484 int index = Hash(*data, *name); |
472 Key& key = keys_[index]; | 485 Key& key = keys_[index]; |
473 ASSERT(key.data == *data); | 486 ASSERT(key.data == *data); |
474 ASSERT(key.name->Equals(*name)); | 487 ASSERT(key.name->Equals(*name)); |
475 Value result(values_[index]); | 488 Value result(values_[index]); |
476 ASSERT(result.mode() == mode); | 489 ASSERT(result.mode() == mode); |
477 ASSERT(result.initialization_flag() == init_flag); | 490 ASSERT(result.initialization_flag() == init_flag); |
| 491 ASSERT(result.maybe_assigned_flag() == maybe_assigned_flag); |
478 ASSERT(result.index() + kNotFound == slot_index); | 492 ASSERT(result.index() + kNotFound == slot_index); |
479 } | 493 } |
480 } | 494 } |
481 | 495 |
482 | 496 |
483 static void PrintList(const char* list_name, | 497 static void PrintList(const char* list_name, |
484 int nof_internal_slots, | 498 int nof_internal_slots, |
485 int start, | 499 int start, |
486 int end, | 500 int end, |
487 ScopeInfo* scope_info) { | 501 ScopeInfo* scope_info) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 } else { | 562 } else { |
549 ASSERT(var->index() >= 0); | 563 ASSERT(var->index() >= 0); |
550 info->set_index(i, var->index()); | 564 info->set_index(i, var->index()); |
551 } | 565 } |
552 } | 566 } |
553 ASSERT(i == info->length()); | 567 ASSERT(i == info->length()); |
554 return info; | 568 return info; |
555 } | 569 } |
556 | 570 |
557 } } // namespace v8::internal | 571 } } // namespace v8::internal |
OLD | NEW |