1 // Copyright 2012 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.
5 #ifndef V8_INTERFACE_H_
6 #define V8_INTERFACE_H_
8 #include "zone-inl.h" // For operator new.
14 // This class implements the following abstract grammar of interfaces
15 // (i.e. module types):
16 // interface ::= UNDETERMINED | VALUE | CONST | MODULE(exports)
17 // exports ::= {name : interface, ...}
18 // A frozen type is one that is fully determined. Unification does not
19 // allow to turn non-const values into const, or adding additional exports to
20 // frozen interfaces. Otherwise, unifying modules merges their exports.
21 // Undetermined types are unification variables that can be unified freely.
22 // There is a natural subsort lattice that reflects the increase of knowledge:
26 // value (frozen) module
28 // const fr.value fr.module
32 // where the bold lines are the only transitions allowed.
34 class Interface : public ZoneObject {
36 // ---------------------------------------------------------------------------
39 static Interface* NewUnknown(Zone* zone) {
40 return new(zone) Interface(NONE);
43 static Interface* NewValue() {
44 static Interface value_interface(VALUE + FROZEN); // Cached.
45 return &value_interface;
48 static Interface* NewConst() {
49 static Interface value_interface(VALUE + CONST + FROZEN); // Cached.
50 return &value_interface;
53 static Interface* NewModule(Zone* zone) {
54 return new(zone) Interface(MODULE);
57 // ---------------------------------------------------------------------------
60 // Add a name to the list of exports. If it already exists, unify with
61 // interface, otherwise insert unless this is closed.
62 void Add(Handle<String> name, Interface* interface, Zone* zone, bool* ok) {
63 DoAdd(name.location(), name->Hash(), interface, zone, ok);
66 // Unify with another interface. If successful, both interface objects will
67 // represent the same type, and changes to one are reflected in the other.
68 void Unify(Interface* that, Zone* zone, bool* ok);
70 // Determine this interface to be a value interface.
71 void MakeValue(bool* ok) {
73 if (*ok) Chase()->flags_ |= VALUE;
76 // Determine this interface to be an immutable interface.
77 void MakeConst(bool* ok) {
78 *ok = !IsModule() && (IsConst() || !IsFrozen());
79 if (*ok) Chase()->flags_ |= VALUE + CONST;
82 // Determine this interface to be a module interface.
83 void MakeModule(bool* ok) {
85 if (*ok) Chase()->flags_ |= MODULE;
88 // Do not allow any further refinements, directly or through unification.
89 void Freeze(bool* ok) {
90 *ok = IsValue() || IsModule();
91 if (*ok) Chase()->flags_ |= FROZEN;
95 void Allocate(int index) {
96 ASSERT(IsModule() && IsFrozen() && Chase()->index_ == -1);
97 Chase()->index_ = index;
100 // ---------------------------------------------------------------------------
103 // Check whether this is still a fully undetermined type.
104 bool IsUnknown() { return Chase()->flags_ == NONE; }
106 // Check whether this is a value type.
107 bool IsValue() { return Chase()->flags_ & VALUE; }
109 // Check whether this is a constant type.
110 bool IsConst() { return Chase()->flags_ & CONST; }
112 // Check whether this is a module type.
113 bool IsModule() { return Chase()->flags_ & MODULE; }
115 // Check whether this is closed (i.e. fully determined).
116 bool IsFrozen() { return Chase()->flags_ & FROZEN; }
118 bool IsUnified(Interface* that) {
119 return Chase() == that->Chase()
120 || (this->IsValue() == that->IsValue() &&
121 this->IsConst() == that->IsConst());
125 ASSERT(IsModule() && IsFrozen());
126 ZoneHashMap* exports = Chase()->exports_;
127 return exports ? exports->occupancy() : 0;
130 // The context slot in the hosting global context pointing to this module.
132 ASSERT(IsModule() && IsFrozen());
133 return Chase()->index_;
136 // Look up an exported name. Returns NULL if not (yet) defined.
137 Interface* Lookup(Handle<String> name, Zone* zone);
139 // ---------------------------------------------------------------------------
143 // for (auto it = interface->iterator(); !it.done(); it.Advance()) {
144 // ... it.name() ... it.interface() ...
148 bool done() const { return entry_ == NULL; }
149 Handle<String> name() const {
151 return Handle<String>(*static_cast<String**>(entry_->key));
153 Interface* interface() const {
155 return static_cast<Interface*>(entry_->value);
157 void Advance() { entry_ = exports_->Next(entry_); }
160 friend class Interface;
161 explicit Iterator(const ZoneHashMap* exports)
162 : exports_(exports), entry_(exports ? exports->Start() : NULL) {}
164 const ZoneHashMap* exports_;
165 ZoneHashMap::Entry* entry_;
168 Iterator iterator() const { return Iterator(this->exports_); }
170 // ---------------------------------------------------------------------------
173 void Print(int n = 0); // n = indentation; n < 0 => don't print recursively
176 // ---------------------------------------------------------------------------
179 enum Flags { // All flags are monotonic
181 VALUE = 1, // This type describes a value
182 CONST = 2, // This type describes a constant
183 MODULE = 4, // This type describes a module
184 FROZEN = 8 // This type is fully determined
188 Interface* forward_; // Unification link
189 ZoneHashMap* exports_; // Module exports and their types (allocated lazily)
192 explicit Interface(int flags)
198 if (FLAG_print_interface_details)
199 PrintF("# Creating %p\n", static_cast<void*>(this));
204 Interface* result = this;
205 while (result->forward_ != NULL) result = result->forward_;
206 if (result != this) forward_ = result; // On-the-fly path compression.
210 void DoAdd(void* name, uint32_t hash, Interface* interface, Zone* zone,
212 void DoUnify(Interface* that, bool* ok, Zone* zone);
215 } } // namespace v8::internal
217 #endif // V8_INTERFACE_H_