| 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 |