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
3// found in the LICENSE file.
4
5#ifndef V8_SCOPEINFO_H_
6#define V8_SCOPEINFO_H_
7
8#include "src/allocation.h"
9#include "src/variables.h"
10#include "src/zone-inl.h"
11
12namespace v8 {
13namespace internal {
14
15// Cache for mapping (data, property name) into context slot index.
16// The cache contains both positive and negative results.
17// Slot index equals -1 means the property is absent.
18// Cleared at startup and prior to mark sweep collection.
19class ContextSlotCache {
20 public:
21  // Lookup context slot index for (data, name).
22  // If absent, kNotFound is returned.
23  int Lookup(Object* data, String* name, VariableMode* mode,
24             InitializationFlag* init_flag,
25             MaybeAssignedFlag* maybe_assigned_flag);
26
27  // Update an element in the cache.
28  void Update(Handle<Object> data, Handle<String> name, VariableMode mode,
29              InitializationFlag init_flag,
30              MaybeAssignedFlag maybe_assigned_flag, int slot_index);
31
32  // Clear the cache.
33  void Clear();
34
35  static const int kNotFound = -2;
36
37 private:
38  ContextSlotCache() {
39    for (int i = 0; i < kLength; ++i) {
40      keys_[i].data = NULL;
41      keys_[i].name = NULL;
42      values_[i] = kNotFound;
43    }
44  }
45
46  inline static int Hash(Object* data, String* name);
47
48#ifdef DEBUG
49  void ValidateEntry(Handle<Object> data, Handle<String> name,
50                     VariableMode mode, InitializationFlag init_flag,
51                     MaybeAssignedFlag maybe_assigned_flag, int slot_index);
52#endif
53
54  static const int kLength = 256;
55  struct Key {
56    Object* data;
57    String* name;
58  };
59
60  struct Value {
61    Value(VariableMode mode, InitializationFlag init_flag,
62          MaybeAssignedFlag maybe_assigned_flag, int index) {
63      DCHECK(ModeField::is_valid(mode));
64      DCHECK(InitField::is_valid(init_flag));
65      DCHECK(MaybeAssignedField::is_valid(maybe_assigned_flag));
66      DCHECK(IndexField::is_valid(index));
67      value_ = ModeField::encode(mode) | IndexField::encode(index) |
68               InitField::encode(init_flag) |
69               MaybeAssignedField::encode(maybe_assigned_flag);
70      DCHECK(mode == this->mode());
71      DCHECK(init_flag == this->initialization_flag());
72      DCHECK(maybe_assigned_flag == this->maybe_assigned_flag());
73      DCHECK(index == this->index());
74    }
75
76    explicit inline Value(uint32_t value) : value_(value) {}
77
78    uint32_t raw() { return value_; }
79
80    VariableMode mode() { return ModeField::decode(value_); }
81
82    InitializationFlag initialization_flag() {
83      return InitField::decode(value_);
84    }
85
86    MaybeAssignedFlag maybe_assigned_flag() {
87      return MaybeAssignedField::decode(value_);
88    }
89
90    int index() { return IndexField::decode(value_); }
91
92    // Bit fields in value_ (type, shift, size). Must be public so the
93    // constants can be embedded in generated code.
94    class ModeField : public BitField<VariableMode, 0, 4> {};
95    class InitField : public BitField<InitializationFlag, 4, 1> {};
96    class MaybeAssignedField : public BitField<MaybeAssignedFlag, 5, 1> {};
97    class IndexField : public BitField<int, 6, 32 - 6> {};
98
99   private:
100    uint32_t value_;
101  };
102
103  Key keys_[kLength];
104  uint32_t values_[kLength];
105
106  friend class Isolate;
107  DISALLOW_COPY_AND_ASSIGN(ContextSlotCache);
108};
109
110
111
112
113//---------------------------------------------------------------------------
114// Auxiliary class used for the description of module instances.
115// Used by Runtime_DeclareModules.
116
117class ModuleInfo: public FixedArray {
118 public:
119  static ModuleInfo* cast(Object* description) {
120    return static_cast<ModuleInfo*>(FixedArray::cast(description));
121  }
122
123  static Handle<ModuleInfo> Create(
124      Isolate* isolate, Interface* interface, Scope* scope);
125
126  // Index of module's context in host context.
127  int host_index() { return Smi::cast(get(HOST_OFFSET))->value(); }
128
129  // Name, mode, and index of the i-th export, respectively.
130  // For value exports, the index is the slot of the value in the module
131  // context, for exported modules it is the slot index of the
132  // referred module's context in the host context.
133  // TODO(rossberg): This format cannot yet handle exports of modules declared
134  // in earlier scripts.
135  String* name(int i) { return String::cast(get(name_offset(i))); }
136  VariableMode mode(int i) {
137    return static_cast<VariableMode>(Smi::cast(get(mode_offset(i)))->value());
138  }
139  int index(int i) { return Smi::cast(get(index_offset(i)))->value(); }
140
141  int length() { return (FixedArray::length() - HEADER_SIZE) / ITEM_SIZE; }
142
143 private:
144  // The internal format is: Index, (Name, VariableMode, Index)*
145  enum {
146    HOST_OFFSET,
147    NAME_OFFSET,
148    MODE_OFFSET,
149    INDEX_OFFSET,
150    HEADER_SIZE = NAME_OFFSET,
151    ITEM_SIZE = INDEX_OFFSET - NAME_OFFSET + 1
152  };
153  inline int name_offset(int i) { return NAME_OFFSET + i * ITEM_SIZE; }
154  inline int mode_offset(int i) { return MODE_OFFSET + i * ITEM_SIZE; }
155  inline int index_offset(int i) { return INDEX_OFFSET + i * ITEM_SIZE; }
156
157  static Handle<ModuleInfo> Allocate(Isolate* isolate, int length) {
158    return Handle<ModuleInfo>::cast(
159        isolate->factory()->NewFixedArray(HEADER_SIZE + ITEM_SIZE * length));
160  }
161  void set_host_index(int index) { set(HOST_OFFSET, Smi::FromInt(index)); }
162  void set_name(int i, String* name) { set(name_offset(i), name); }
163  void set_mode(int i, VariableMode mode) {
164    set(mode_offset(i), Smi::FromInt(mode));
165  }
166  void set_index(int i, int index) {
167    set(index_offset(i), Smi::FromInt(index));
168  }
169};
170
171
172} }  // namespace v8::internal
173
174#endif  // V8_SCOPEINFO_H_
175