blob: 94ef11ba5c29d40f40e3755cafd16f2837252cfc [file] [log] [blame]
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_INTERFACE_H_
29#define V8_INTERFACE_H_
30
31#include "zone-inl.h" // For operator new.
32
33namespace v8 {
34namespace internal {
35
36
37// This class implements the following abstract grammar of interfaces
38// (i.e. module types):
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000039// interface ::= UNDETERMINED | VALUE | CONST | MODULE(exports)
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000040// exports ::= {name : interface, ...}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000041// A frozen type is one that is fully determined. Unification does not
42// allow to turn non-const values into const, or adding additional exports to
43// frozen interfaces. Otherwise, unifying modules merges their exports.
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000044// Undetermined types are unification variables that can be unified freely.
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000045// There is a natural subsort lattice that reflects the increase of knowledge:
46//
47// undetermined
48// // | \\ .
49// value (frozen) module
50// // \\ / \ //
51// const fr.value fr.module
52// \\ /
53// fr.const
54//
55// where the bold lines are the only transitions allowed.
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000056
57class Interface : public ZoneObject {
58 public:
59 // ---------------------------------------------------------------------------
60 // Factory methods.
61
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000062 static Interface* NewUnknown(Zone* zone) {
63 return new(zone) Interface(NONE);
64 }
65
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000066 static Interface* NewValue() {
67 static Interface value_interface(VALUE + FROZEN); // Cached.
68 return &value_interface;
69 }
70
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000071 static Interface* NewConst() {
72 static Interface value_interface(VALUE + CONST + FROZEN); // Cached.
73 return &value_interface;
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000074 }
75
mmassi@chromium.org7028c052012-06-13 11:51:58 +000076 static Interface* NewModule(Zone* zone) {
77 return new(zone) Interface(MODULE);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000078 }
79
80 // ---------------------------------------------------------------------------
81 // Mutators.
82
83 // Add a name to the list of exports. If it already exists, unify with
84 // interface, otherwise insert unless this is closed.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000085 void Add(Handle<String> name, Interface* interface, Zone* zone, bool* ok) {
86 DoAdd(name.location(), name->Hash(), interface, zone, ok);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000087 }
88
89 // Unify with another interface. If successful, both interface objects will
90 // represent the same type, and changes to one are reflected in the other.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000091 void Unify(Interface* that, Zone* zone, bool* ok);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000092
93 // Determine this interface to be a value interface.
94 void MakeValue(bool* ok) {
95 *ok = !IsModule();
96 if (*ok) Chase()->flags_ |= VALUE;
97 }
98
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000099 // Determine this interface to be an immutable interface.
100 void MakeConst(bool* ok) {
101 *ok = !IsModule() && (IsConst() || !IsFrozen());
102 if (*ok) Chase()->flags_ |= VALUE + CONST;
103 }
104
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000105 // Determine this interface to be a module interface.
106 void MakeModule(bool* ok) {
107 *ok = !IsValue();
108 if (*ok) Chase()->flags_ |= MODULE;
109 }
110
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000111 // Set associated instance object.
112 void MakeSingleton(Handle<JSModule> instance, bool* ok) {
113 *ok = IsModule() && Chase()->instance_.is_null();
114 if (*ok) Chase()->instance_ = instance;
115 }
116
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000117 // Do not allow any further refinements, directly or through unification.
118 void Freeze(bool* ok) {
119 *ok = IsValue() || IsModule();
120 if (*ok) Chase()->flags_ |= FROZEN;
121 }
122
123 // ---------------------------------------------------------------------------
124 // Accessors.
125
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000126 // Check whether this is still a fully undetermined type.
127 bool IsUnknown() { return Chase()->flags_ == NONE; }
128
129 // Check whether this is a value type.
130 bool IsValue() { return Chase()->flags_ & VALUE; }
131
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000132 // Check whether this is a constant type.
133 bool IsConst() { return Chase()->flags_ & CONST; }
134
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000135 // Check whether this is a module type.
136 bool IsModule() { return Chase()->flags_ & MODULE; }
137
138 // Check whether this is closed (i.e. fully determined).
139 bool IsFrozen() { return Chase()->flags_ & FROZEN; }
140
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000141 Handle<JSModule> Instance() { return Chase()->instance_; }
142
143 // Look up an exported name. Returns NULL if not (yet) defined.
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000144 Interface* Lookup(Handle<String> name, Zone* zone);
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000145
146 // ---------------------------------------------------------------------------
147 // Iterators.
148
149 // Use like:
150 // for (auto it = interface->iterator(); !it.done(); it.Advance()) {
151 // ... it.name() ... it.interface() ...
152 // }
153 class Iterator {
154 public:
155 bool done() const { return entry_ == NULL; }
156 Handle<String> name() const {
157 ASSERT(!done());
158 return Handle<String>(*static_cast<String**>(entry_->key));
159 }
160 Interface* interface() const {
161 ASSERT(!done());
162 return static_cast<Interface*>(entry_->value);
163 }
164 void Advance() { entry_ = exports_->Next(entry_); }
165
166 private:
167 friend class Interface;
168 explicit Iterator(const ZoneHashMap* exports)
169 : exports_(exports), entry_(exports ? exports->Start() : NULL) {}
170
171 const ZoneHashMap* exports_;
172 ZoneHashMap::Entry* entry_;
173 };
174
175 Iterator iterator() const { return Iterator(this->exports_); }
176
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000177 // ---------------------------------------------------------------------------
178 // Debugging.
179#ifdef DEBUG
180 void Print(int n = 0); // n = indentation; n < 0 => don't print recursively
181#endif
182
183 // ---------------------------------------------------------------------------
184 // Implementation.
185 private:
186 enum Flags { // All flags are monotonic
187 NONE = 0,
188 VALUE = 1, // This type describes a value
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000189 CONST = 2, // This type describes a constant
190 MODULE = 4, // This type describes a module
191 FROZEN = 8 // This type is fully determined
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000192 };
193
194 int flags_;
195 Interface* forward_; // Unification link
196 ZoneHashMap* exports_; // Module exports and their types (allocated lazily)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000197 Handle<JSModule> instance_;
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000198
199 explicit Interface(int flags)
200 : flags_(flags),
201 forward_(NULL),
202 exports_(NULL) {
203#ifdef DEBUG
204 if (FLAG_print_interface_details)
205 PrintF("# Creating %p\n", static_cast<void*>(this));
206#endif
207 }
208
209 Interface* Chase() {
210 Interface* result = this;
211 while (result->forward_ != NULL) result = result->forward_;
212 if (result != this) forward_ = result; // On-the-fly path compression.
213 return result;
214 }
215
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000216 void DoAdd(void* name, uint32_t hash, Interface* interface, Zone* zone,
217 bool* ok);
218 void DoUnify(Interface* that, bool* ok, Zone* zone);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000219};
220
221} } // namespace v8::internal
222
223#endif // V8_INTERFACE_H_