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
19namespace v8 {
20namespace internal {
21
22int 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
29int 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
45void 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
68void ContextSlotCache::Clear() {
69  for (int index = 0; index < kLength; index++) keys_[index].data = nullptr;
70}
71
72#ifdef DEBUG
73
74void 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