1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/ast/context-slot-cache.h" 6 7 #include <stdlib.h> 8 9 #include "src/ast/scopes.h" 10 #include "src/bootstrapper.h" 11 // FIXME(mstarzinger, marja): This is weird, but required because of the missing 12 // (disallowed) include: src/factory.h -> src/objects-inl.h 13 #include "src/objects-inl.h" 14 // FIXME(mstarzinger, marja): This is weird, but required because of the missing 15 // (disallowed) include: src/feedback-vector.h -> 16 // src/feedback-vector-inl.h 17 #include "src/feedback-vector-inl.h" 18 19 namespace v8 { 20 namespace internal { 21 22 int ContextSlotCache::Hash(Object* data, String* name) { 23 // Uses only lower 32 bits if pointers are larger. 24 uintptr_t addr_hash = 25 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2; 26 return static_cast<int>((addr_hash ^ name->Hash()) % kLength); 27 } 28 29 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode, 30 InitializationFlag* init_flag, 31 MaybeAssignedFlag* maybe_assigned_flag) { 32 int index = Hash(data, name); 33 Key& key = keys_[index]; 34 if ((key.data == data) && key.name->Equals(name)) { 35 Value result(values_[index]); 36 if (mode != nullptr) *mode = result.mode(); 37 if (init_flag != nullptr) *init_flag = result.initialization_flag(); 38 if (maybe_assigned_flag != nullptr) 39 *maybe_assigned_flag = result.maybe_assigned_flag(); 40 return result.index() + kNotFound; 41 } 42 return kNotFound; 43 } 44 45 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name, 46 VariableMode mode, InitializationFlag init_flag, 47 MaybeAssignedFlag maybe_assigned_flag, 48 int slot_index) { 49 DisallowHeapAllocation no_gc; 50 Handle<String> internalized_name; 51 DCHECK(slot_index > kNotFound); 52 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name) 53 .ToHandle(&internalized_name)) { 54 int index = Hash(*data, *internalized_name); 55 Key& key = keys_[index]; 56 key.data = *data; 57 key.name = *internalized_name; 58 // Please note value only takes a uint as index. 59 values_[index] = 60 Value(mode, init_flag, maybe_assigned_flag, slot_index - kNotFound) 61 .raw(); 62 #ifdef DEBUG 63 ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index); 64 #endif 65 } 66 } 67 68 void ContextSlotCache::Clear() { 69 for (int index = 0; index < kLength; index++) keys_[index].data = nullptr; 70 } 71 72 #ifdef DEBUG 73 74 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name, 75 VariableMode mode, 76 InitializationFlag init_flag, 77 MaybeAssignedFlag maybe_assigned_flag, 78 int slot_index) { 79 DisallowHeapAllocation no_gc; 80 Handle<String> internalized_name; 81 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name) 82 .ToHandle(&internalized_name)) { 83 int index = Hash(*data, *name); 84 Key& key = keys_[index]; 85 DCHECK(key.data == *data); 86 DCHECK(key.name->Equals(*name)); 87 Value result(values_[index]); 88 DCHECK(result.mode() == mode); 89 DCHECK(result.initialization_flag() == init_flag); 90 DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag); 91 DCHECK(result.index() + kNotFound == slot_index); 92 } 93 } 94 95 #endif // DEBUG 96 97 } // namespace internal 98 } // namespace v8 99