Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: src/types.cc

Issue 558193003: Redesign of the internal type system. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/types.h" 5 #include "src/types.h"
6 6
7 #include "src/ostreams.h" 7 #include "src/ostreams.h"
8 #include "src/types-inl.h" 8 #include "src/types-inl.h"
9 9
10 namespace v8 { 10 namespace v8 {
11 namespace internal { 11 namespace internal {
12 12
13 13
14 // NOTE: If code is marked as being a "shortcut", this means that removing
15 // the code won't affect the semantics of the surrounding function.
16
17
18
19
14 // ----------------------------------------------------------------------------- 20 // -----------------------------------------------------------------------------
15 // Range-related custom order on doubles. 21 // Range-related helper functions.
16 // We want -0 to be less than +0.
17 22
18 static bool dle(double x, double y) { 23 // The result may be invalid (max < min).
19 return x <= y && (x != 0 || IsMinusZero(x) || !IsMinusZero(y)); 24 template<class Config>
25 typename TypeImpl<Config>::Limits TypeImpl<Config>::Intersect(
26 Limits lhs, Limits rhs) {
27 DisallowHeapAllocation no_allocation;
28 Limits result(lhs);
29 if (lhs.min->Number() < rhs.min->Number()) result.min = rhs.min;
30 if (lhs.max->Number() > rhs.max->Number()) result.max = rhs.max;
31 return result;
20 } 32 }
21 33
22 34
23 static bool deq(double x, double y) { 35 template<class Config>
24 return dle(x, y) && dle(y, x); 36 typename TypeImpl<Config>::Limits TypeImpl<Config>::Union(
37 Limits lhs, Limits rhs) {
38 DisallowHeapAllocation no_allocation;
39 Limits result(lhs);
40 if (lhs.min->Number() > rhs.min->Number()) result.min = rhs.min;
41 if (lhs.max->Number() < rhs.max->Number()) result.max = rhs.max;
42 return result;
43 }
44
45
46 template<class Config>
47 bool TypeImpl<Config>::Overlap(
48 typename TypeImpl<Config>::RangeType* lhs,
49 typename TypeImpl<Config>::RangeType* rhs) {
50 DisallowHeapAllocation no_allocation;
51 typename TypeImpl<Config>::Limits lim = Intersect(Limits(lhs), Limits(rhs));
52 return lim.min->Number() <= lim.max->Number();
53 }
54
55
56 template<class Config>
57 bool TypeImpl<Config>::Contains(
58 typename TypeImpl<Config>::RangeType* lhs,
59 typename TypeImpl<Config>::RangeType* rhs) {
60 DisallowHeapAllocation no_allocation;
61 return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max();
62 }
63
64
65 template<class Config>
66 bool TypeImpl<Config>::Contains(
67 typename TypeImpl<Config>::RangeType* range, i::Object* val) {
68 DisallowHeapAllocation no_allocation;
69 return IsInteger(val)
70 && range->Min() <= val->Number() && val->Number() <= range->Max();
71 }
72
73
74 // -----------------------------------------------------------------------------
75 // Min and Max computation.
76
77 template<class Config>
78 double TypeImpl<Config>::Min() {
79 DCHECK(this->Is(Number()));
80 if (this->IsBitset()) return BitsetType::Min(this->AsBitset());
81 if (this->IsUnion()) {
82 double min = +V8_INFINITY;
83 for (int i = 0; i < this->AsUnion()->Length(); ++i) {
84 min = std::min(min, this->AsUnion()->Get(i)->Min());
85 }
86 return min;
87 }
88 if (this->IsRange()) return this->AsRange()->Min();
89 if (this->IsConstant()) return this->AsConstant()->Value()->Number();
90 UNREACHABLE();
91 return 0;
92 }
93
94
95 template<class Config>
96 double TypeImpl<Config>::Max() {
97 DCHECK(this->Is(Number()));
98 if (this->IsBitset()) return BitsetType::Max(this->AsBitset());
99 if (this->IsUnion()) {
100 double max = -V8_INFINITY;
101 for (int i = 0; i < this->AsUnion()->Length(); ++i) {
102 max = std::max(max, this->AsUnion()->Get(i)->Max());
103 }
104 return max;
105 }
106 if (this->IsRange()) return this->AsRange()->Max();
107 if (this->IsConstant()) return this->AsConstant()->Value()->Number();
108 UNREACHABLE();
109 return 0;
25 } 110 }
26 111
27 112
28 // ----------------------------------------------------------------------------- 113 // -----------------------------------------------------------------------------
29 // Glb and lub computation. 114 // Glb and lub computation.
30 115
116
31 // The largest bitset subsumed by this type. 117 // The largest bitset subsumed by this type.
32 template<class Config> 118 template<class Config>
33 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { 119 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) {
34 DisallowHeapAllocation no_allocation; 120 DisallowHeapAllocation no_allocation;
35 if (type->IsBitset()) { 121 if (type->IsBitset()) {
36 return type->AsBitset(); 122 return type->AsBitset();
37 } else if (type->IsUnion()) { 123 } else if (type->IsUnion()) {
38 UnionHandle unioned = handle(type->AsUnion()); 124 SLOW_DCHECK(type->AsUnion()->Wellformed());
39 DCHECK(unioned->Wellformed()); 125 return type->AsUnion()->Get(0)->BitsetGlb(); // Shortcut.
40 return unioned->Get(0)->BitsetGlb(); // Other BitsetGlb's are kNone anyway. 126 // (The remaining BitsetGlb's are None anyway).
41 } else { 127 } else {
42 return kNone; 128 return kNone;
43 } 129 }
44 } 130 }
45 131
46 132
47 // The smallest bitset subsuming this type. 133 // The smallest bitset subsuming this type.
48 template<class Config> 134 template<class Config>
49 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { 135 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
50 DisallowHeapAllocation no_allocation; 136 DisallowHeapAllocation no_allocation;
51 if (type->IsBitset()) { 137 if (type->IsBitset()) return type->AsBitset();
52 return type->AsBitset(); 138 if (type->IsUnion()) {
53 } else if (type->IsUnion()) {
54 UnionHandle unioned = handle(type->AsUnion());
55 int bitset = kNone; 139 int bitset = kNone;
56 for (int i = 0; i < unioned->Length(); ++i) { 140 for (int i = 0; i < type->AsUnion()->Length(); ++i) {
57 bitset |= unioned->Get(i)->BitsetLub(); 141 bitset |= type->AsUnion()->Get(i)->BitsetLub();
58 } 142 }
59 return bitset; 143 return bitset;
60 } else if (type->IsClass()) {
61 // Little hack to avoid the need for a region for handlification here...
62 return Config::is_class(type) ? Lub(*Config::as_class(type)) :
63 type->AsClass()->Bound(NULL)->AsBitset();
64 } else if (type->IsConstant()) {
65 return type->AsConstant()->Bound()->AsBitset();
66 } else if (type->IsRange()) {
67 return type->AsRange()->Bound()->AsBitset();
68 } else if (type->IsContext()) {
69 return type->AsContext()->Bound()->AsBitset();
70 } else if (type->IsArray()) {
71 return type->AsArray()->Bound()->AsBitset();
72 } else if (type->IsFunction()) {
73 return type->AsFunction()->Bound()->AsBitset();
74 } else {
75 UNREACHABLE();
76 return kNone;
77 } 144 }
145 if (type->IsClass()) return Lub(*type->AsClass()->Map());
146 if (type->IsConstant()) return Lub(*type->AsConstant()->Value());
147 if (type->IsRange()) return Lub(Limits(type->AsRange()));
148 if (type->IsContext()) return kInternal & kTaggedPtr;
149 if (type->IsArray()) return kArray;
150 if (type->IsFunction()) return kFunction;
151 UNREACHABLE();
152 return kNone;
78 } 153 }
79 154
80 155
81 // The smallest bitset subsuming this type, ignoring explicit bounds.
82 template<class Config>
83 int TypeImpl<Config>::BitsetType::InherentLub(TypeImpl* type) {
84 DisallowHeapAllocation no_allocation;
85 if (type->IsBitset()) {
86 return type->AsBitset();
87 } else if (type->IsUnion()) {
88 UnionHandle unioned = handle(type->AsUnion());
89 int bitset = kNone;
90 for (int i = 0; i < unioned->Length(); ++i) {
91 bitset |= unioned->Get(i)->InherentBitsetLub();
92 }
93 return bitset;
94 } else if (type->IsClass()) {
95 return Lub(*type->AsClass()->Map());
96 } else if (type->IsConstant()) {
97 return Lub(*type->AsConstant()->Value());
98 } else if (type->IsRange()) {
99 return Lub(type->AsRange()->Min(), type->AsRange()->Max());
100 } else if (type->IsContext()) {
101 return kInternal & kTaggedPtr;
102 } else if (type->IsArray()) {
103 return kArray;
104 } else if (type->IsFunction()) {
105 return kFunction;
106 } else {
107 UNREACHABLE();
108 return kNone;
109 }
110 }
111
112
113 template<class Config>
114 int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
115 DisallowHeapAllocation no_allocation;
116 if (value->IsNumber()) {
117 return Lub(value->Number()) & (value->IsSmi() ? kTaggedInt : kTaggedPtr);
118 }
119 return Lub(i::HeapObject::cast(value)->map());
120 }
121
122
123 template<class Config>
124 int TypeImpl<Config>::BitsetType::Lub(double value) {
125 DisallowHeapAllocation no_allocation;
126 if (i::IsMinusZero(value)) return kMinusZero;
127 if (std::isnan(value)) return kNaN;
128 if (IsUint32Double(value)) return Lub(FastD2UI(value));
129 if (IsInt32Double(value)) return Lub(FastD2I(value));
130 return kOtherNumber;
131 }
132
133
134 template<class Config>
135 int TypeImpl<Config>::BitsetType::Lub(double min, double max) {
136 DisallowHeapAllocation no_allocation;
137 DCHECK(dle(min, max));
138 if (deq(min, max)) return BitsetType::Lub(min); // Singleton range.
139 int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN);
140 if (dle(0, min) || max < 0) bitset ^= SEMANTIC(BitsetType::kMinusZero);
141 return bitset;
142 // TODO(neis): Could refine this further by doing more checks on min/max.
143 }
144
145
146 template<class Config>
147 int TypeImpl<Config>::BitsetType::Lub(int32_t value) {
148 if (value >= 0x40000000) {
149 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
150 }
151 if (value >= 0) return kUnsignedSmall;
152 if (value >= -0x40000000) return kOtherSignedSmall;
153 return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall;
154 }
155
156
157 template<class Config>
158 int TypeImpl<Config>::BitsetType::Lub(uint32_t value) {
159 DisallowHeapAllocation no_allocation;
160 if (value >= 0x80000000u) return kOtherUnsigned32;
161 if (value >= 0x40000000u) {
162 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
163 }
164 return kUnsignedSmall;
165 }
166
167
168 template<class Config> 156 template<class Config>
169 int TypeImpl<Config>::BitsetType::Lub(i::Map* map) { 157 int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
170 DisallowHeapAllocation no_allocation; 158 DisallowHeapAllocation no_allocation;
171 switch (map->instance_type()) { 159 switch (map->instance_type()) {
172 case STRING_TYPE: 160 case STRING_TYPE:
173 case ONE_BYTE_STRING_TYPE: 161 case ONE_BYTE_STRING_TYPE:
174 case CONS_STRING_TYPE: 162 case CONS_STRING_TYPE:
175 case CONS_ONE_BYTE_STRING_TYPE: 163 case CONS_ONE_BYTE_STRING_TYPE:
176 case SLICED_STRING_TYPE: 164 case SLICED_STRING_TYPE:
177 case SLICED_ONE_BYTE_STRING_TYPE: 165 case SLICED_ONE_BYTE_STRING_TYPE:
178 case EXTERNAL_STRING_TYPE: 166 case EXTERNAL_STRING_TYPE:
179 case EXTERNAL_ONE_BYTE_STRING_TYPE: 167 case EXTERNAL_ONE_BYTE_STRING_TYPE:
180 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: 168 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
181 case SHORT_EXTERNAL_STRING_TYPE: 169 case SHORT_EXTERNAL_STRING_TYPE:
182 case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE: 170 case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE:
183 case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: 171 case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
172 return kOtherString;
184 case INTERNALIZED_STRING_TYPE: 173 case INTERNALIZED_STRING_TYPE:
185 case ONE_BYTE_INTERNALIZED_STRING_TYPE: 174 case ONE_BYTE_INTERNALIZED_STRING_TYPE:
186 case EXTERNAL_INTERNALIZED_STRING_TYPE: 175 case EXTERNAL_INTERNALIZED_STRING_TYPE:
187 case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE: 176 case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
188 case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: 177 case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
189 case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE: 178 case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE:
190 case SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE: 179 case SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
191 case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: 180 case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
192 return kString; 181 return kInternalizedString;
193 case SYMBOL_TYPE: 182 case SYMBOL_TYPE:
194 return kSymbol; 183 return kSymbol;
195 case ODDBALL_TYPE: { 184 case ODDBALL_TYPE: {
196 Heap* heap = map->GetHeap(); 185 Heap* heap = map->GetHeap();
197 if (map == heap->undefined_map()) return kUndefined; 186 if (map == heap->undefined_map()) return kUndefined;
198 if (map == heap->null_map()) return kNull; 187 if (map == heap->null_map()) return kNull;
199 if (map == heap->boolean_map()) return kBoolean; 188 if (map == heap->boolean_map()) return kBoolean;
200 DCHECK(map == heap->the_hole_map() || 189 DCHECK(map == heap->the_hole_map() ||
201 map == heap->uninitialized_map() || 190 map == heap->uninitialized_map() ||
202 map == heap->no_interceptor_result_sentinel_map() || 191 map == heap->no_interceptor_result_sentinel_map() ||
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 case FOREIGN_TYPE: 243 case FOREIGN_TYPE:
255 case CODE_TYPE: 244 case CODE_TYPE:
256 return kInternal & kTaggedPtr; 245 return kInternal & kTaggedPtr;
257 default: 246 default:
258 UNREACHABLE(); 247 UNREACHABLE();
259 return kNone; 248 return kNone;
260 } 249 }
261 } 250 }
262 251
263 252
253 template<class Config>
254 int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
255 DisallowHeapAllocation no_allocation;
256 if (value->IsNumber()) {
257 return Lub(value->Number()) & (value->IsSmi() ? kTaggedInt : kTaggedPtr);
258 }
259 return Lub(i::HeapObject::cast(value)->map());
260 }
261
262
263 template<class Config>
264 int TypeImpl<Config>::BitsetType::Lub(double value) {
265 DisallowHeapAllocation no_allocation;
266 if (i::IsMinusZero(value)) return kMinusZero;
267 if (std::isnan(value)) return kNaN;
268 if (IsUint32Double(value)) return Lub(FastD2UI(value));
269 if (IsInt32Double(value)) return Lub(FastD2I(value));
270 return kOtherNumber;
271 }
272
273
274 template<class Config>
275 int TypeImpl<Config>::BitsetType::Lub(int32_t value) {
276 DisallowHeapAllocation no_allocation;
277 if (value >= 0x40000000) {
278 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
279 }
280 if (value >= 0) return kUnsignedSmall;
281 if (value >= -0x40000000) return kOtherSignedSmall;
282 return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall;
283 }
284
285
286 template<class Config>
287 int TypeImpl<Config>::BitsetType::Lub(uint32_t value) {
288 DisallowHeapAllocation no_allocation;
289 if (value >= 0x80000000u) return kOtherUnsigned32;
290 if (value >= 0x40000000u) {
291 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
292 }
293 return kUnsignedSmall;
294 }
295
296
297 template<class Config>
298 const typename TypeImpl<Config>::BitsetType::Numeral
299 TypeImpl<Config>::BitsetType::Numerals31[] = {
300 {kOtherNumber, -V8_INFINITY},
301 {kOtherSigned32, kMinInt},
302 {kOtherSignedSmall, -0x40000000},
303 {kUnsignedSmall, 0},
304 {kOtherUnsigned31, 0x40000000},
305 {kOtherUnsigned32, 0x80000000},
306 {kOtherNumber, static_cast<double>(kMaxUInt32) + 1}
307 };
308
309
310 template<class Config>
311 const typename TypeImpl<Config>::BitsetType::Numeral
312 TypeImpl<Config>::BitsetType::Numerals32[] = {
313 {kOtherNumber, -V8_INFINITY},
314 {kOtherSignedSmall, kMinInt},
315 {kUnsignedSmall, 0},
316 {kOtherUnsigned32, 0x80000000},
317 {kOtherNumber, static_cast<double>(kMaxUInt32) + 1}
318 };
319
320
321 template<class Config>
322 int TypeImpl<Config>::BitsetType::Lub(Limits lim) {
323 DisallowHeapAllocation no_allocation;
324 double min = lim.min->Number();
325 double max = lim.max->Number();
326 int lub = kNone;
327
328 for (size_t i = 1; i < NumeralsSize(); ++i) {
329 if (min < Numerals()[i].min) {
330 lub |= Numerals()[i-1].bitset;
331 if (max < Numerals()[i].min) return lub;
332 }
333 }
334 return lub |= Numerals()[NumeralsSize()-1].bitset;
335 }
336
337
338 template<class Config>
339 double TypeImpl<Config>::BitsetType::Min(int bitset) {
340 DisallowHeapAllocation no_allocation;
341 for (size_t i = 0; i < NumeralsSize(); ++i) {
342 if (BitsetType::Is(Numerals()[i].bitset, bitset)) return Numerals()[i].min;
343 }
344 UNREACHABLE();
345 return 0;
346 }
347
348
349 template<class Config>
350 double TypeImpl<Config>::BitsetType::Max(int bitset) {
351 DisallowHeapAllocation no_allocation;
352 if (BitsetType::Is(Numerals()[NumeralsSize()-1].bitset, bitset)) {
353 return +V8_INFINITY;
354 }
355 for (int i = NumeralsSize()-2; i >= 0; --i) {
356 if (BitsetType::Is(Numerals()[i].bitset, bitset)) {
357 return Numerals()[i+1].min - 1;
358 }
359 }
360 UNREACHABLE();
361 return 0;
362 }
363
364
264 // ----------------------------------------------------------------------------- 365 // -----------------------------------------------------------------------------
265 // Predicates. 366 // Predicates.
266 367
267 // Check this <= that. 368
369 template<class Config>
370 bool TypeImpl<Config>::SimplyEquals(TypeImpl* that) {
371 DisallowHeapAllocation no_allocation;
372 if (this->IsClass()) {
373 return that->IsClass()
374 && *this->AsClass()->Map() == *that->AsClass()->Map();
375 }
376 if (this->IsConstant()) {
377 return that->IsConstant()
378 && *this->AsConstant()->Value() == *that->AsConstant()->Value();
379 }
380 if (this->IsContext()) {
381 return that->IsContext()
382 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer());
383 }
384 if (this->IsArray()) {
385 return that->IsArray()
386 && this->AsArray()->Element()->Equals(that->AsArray()->Element());
387 }
388 if (this->IsFunction()) {
389 if (!that->IsFunction()) return false;
390 FunctionType* this_fun = this->AsFunction();
391 FunctionType* that_fun = that->AsFunction();
392 if (this_fun->Arity() != that_fun->Arity() ||
393 !this_fun->Result()->Equals(that_fun->Result()) ||
394 !this_fun->Receiver()->Equals(that_fun->Receiver())) {
395 return false;
396 }
397 for (int i = 0; i < this_fun->Arity(); ++i) {
398 if (!this_fun->Parameter(i)->Equals(that_fun->Parameter(i))) return false;
399 }
400 return true;
401 }
402 UNREACHABLE();
403 return false;
404 }
405
406
407 // Check if [this] <= [that].
268 template<class Config> 408 template<class Config>
269 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { 409 bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
270 DisallowHeapAllocation no_allocation; 410 DisallowHeapAllocation no_allocation;
271 411
272 // Fast path for bitsets.
273 if (this->IsNone()) return true;
274 if (that->IsBitset()) { 412 if (that->IsBitset()) {
275 return BitsetType::Is(BitsetType::Lub(this), that->AsBitset()); 413 return BitsetType::Is(this->BitsetLub(), that->AsBitset());
414 }
415 if (this->IsBitset()) {
416 return BitsetType::Is(this->AsBitset(), that->BitsetGlb());
276 } 417 }
277 418
278 if (that->IsClass()) { 419 // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T)
279 return this->IsClass()
280 && *this->AsClass()->Map() == *that->AsClass()->Map()
281 && ((Config::is_class(that) && Config::is_class(this)) ||
282 BitsetType::New(this->BitsetLub())->Is(
283 BitsetType::New(that->BitsetLub())));
284 }
285 if (that->IsConstant()) {
286 return this->IsConstant()
287 && *this->AsConstant()->Value() == *that->AsConstant()->Value()
288 && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound());
289 }
290 if (that->IsRange()) {
291 return this->IsRange()
292 && this->AsRange()->Bound()->Is(that->AsRange()->Bound())
293 && dle(that->AsRange()->Min(), this->AsRange()->Min())
294 && dle(this->AsRange()->Max(), that->AsRange()->Max());
295 }
296 if (that->IsContext()) {
297 return this->IsContext()
298 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer());
299 }
300 if (that->IsArray()) {
301 return this->IsArray()
302 && this->AsArray()->Element()->Equals(that->AsArray()->Element());
303 }
304 if (that->IsFunction()) {
305 // We currently do not allow for any variance here, in order to keep
306 // Union and Intersect operations simple.
307 if (!this->IsFunction()) return false;
308 FunctionType* this_fun = this->AsFunction();
309 FunctionType* that_fun = that->AsFunction();
310 if (this_fun->Arity() != that_fun->Arity() ||
311 !this_fun->Result()->Equals(that_fun->Result()) ||
312 !that_fun->Receiver()->Equals(this_fun->Receiver())) {
313 return false;
314 }
315 for (int i = 0; i < this_fun->Arity(); ++i) {
316 if (!that_fun->Parameter(i)->Equals(this_fun->Parameter(i))) return false;
317 }
318 return true;
319 }
320
321 // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
322 if (this->IsUnion()) { 420 if (this->IsUnion()) {
323 UnionHandle unioned = handle(this->AsUnion()); 421 UnionHandle unioned = handle(this->AsUnion());
324 for (int i = 0; i < unioned->Length(); ++i) { 422 for (int i = 0; i < unioned->Length(); ++i) {
325 if (!unioned->Get(i)->Is(that)) return false; 423 if (!unioned->Get(i)->Is(that)) return false;
326 } 424 }
327 return true; 425 return true;
328 } 426 }
329 427
330 // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn) 428 // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn)
331 // (iff T is not a union) 429 if (that->IsUnion()) {
332 DCHECK(!this->IsUnion() && that->IsUnion()); 430 for (int i = 0; i < that->AsUnion()->Length(); ++i) {
333 UnionHandle unioned = handle(that->AsUnion()); 431 if (this->Is(that->AsUnion()->Get(i))) return true;
334 for (int i = 0; i < unioned->Length(); ++i) { 432 if (i > 1 && this->IsRange()) return false; // Shortcut.
335 if (this->Is(unioned->Get(i))) return true; 433 }
336 if (this->IsBitset()) break; // Fast fail, only first field is a bitset. 434 return false;
337 } 435 }
338 return false; 436
437 if (that->IsRange()) {
438 return (this->IsRange() && Contains(that->AsRange(), this->AsRange()))
439 || (this->IsConstant() &&
440 Contains(that->AsRange(), *this->AsConstant()->Value()));
441 }
442 if (this->IsRange()) return false;
443 return this->SimplyEquals(that);
339 } 444 }
340 445
341 446
342 template<class Config> 447 template<class Config>
343 bool TypeImpl<Config>::NowIs(TypeImpl* that) { 448 bool TypeImpl<Config>::NowIs(TypeImpl* that) {
344 DisallowHeapAllocation no_allocation; 449 DisallowHeapAllocation no_allocation;
345 450
346 // TODO(rossberg): this is incorrect for 451 // TODO(rossberg): this is incorrect for
347 // Union(Constant(V), T)->NowIs(Class(M)) 452 // Union(Constant(V), T)->NowIs(Class(M))
348 // but fuzzing does not cover that! 453 // but fuzzing does not cover that!
349 if (this->IsConstant()) { 454 if (this->IsConstant()) {
350 i::Object* object = *this->AsConstant()->Value(); 455 i::Object* object = *this->AsConstant()->Value();
351 if (object->IsHeapObject()) { 456 if (object->IsHeapObject()) {
352 i::Map* map = i::HeapObject::cast(object)->map(); 457 i::Map* map = i::HeapObject::cast(object)->map();
353 for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) { 458 for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) {
354 if (*it.Current() == map) return true; 459 if (*it.Current() == map) return true;
355 } 460 }
356 } 461 }
357 } 462 }
358 return this->Is(that); 463 return this->Is(that);
359 } 464 }
360 465
361 466
362 // Check if this contains only (currently) stable classes. 467 // Check if [this] contains only (currently) stable classes.
363 template<class Config> 468 template<class Config>
364 bool TypeImpl<Config>::NowStable() { 469 bool TypeImpl<Config>::NowStable() {
365 DisallowHeapAllocation no_allocation; 470 DisallowHeapAllocation no_allocation;
366 for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) { 471 for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) {
367 if (!it.Current()->is_stable()) return false; 472 if (!it.Current()->is_stable()) return false;
368 } 473 }
369 return true; 474 return true;
370 } 475 }
371 476
372 477
373 // Check this overlaps that. 478 // Check if [this] and [that] overlap.
374 template<class Config> 479 template<class Config>
375 bool TypeImpl<Config>::Maybe(TypeImpl* that) { 480 bool TypeImpl<Config>::Maybe(TypeImpl* that) {
376 DisallowHeapAllocation no_allocation; 481 DisallowHeapAllocation no_allocation;
377 482
378 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) 483 // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T)
379 if (this->IsUnion()) { 484 if (this->IsUnion()) {
380 UnionHandle unioned = handle(this->AsUnion()); 485 UnionHandle unioned = handle(this->AsUnion());
381 for (int i = 0; i < unioned->Length(); ++i) { 486 for (int i = 0; i < unioned->Length(); ++i) {
382 if (unioned->Get(i)->Maybe(that)) return true; 487 if (unioned->Get(i)->Maybe(that)) return true;
383 } 488 }
384 return false; 489 return false;
385 } 490 }
386 491
387 // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn) 492 // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn)
388 if (that->IsUnion()) { 493 if (that->IsUnion()) {
389 UnionHandle unioned = handle(that->AsUnion()); 494 for (int i = 0; i < that->AsUnion()->Length(); ++i) {
390 for (int i = 0; i < unioned->Length(); ++i) { 495 if (this->Maybe(that->AsUnion()->Get(i))) return true;
391 if (this->Maybe(unioned->Get(i))) return true;
392 } 496 }
393 return false; 497 return false;
394 } 498 }
395 499
396 DCHECK(!this->IsUnion() && !that->IsUnion()); 500 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub()))
397 if (this->IsBitset() || that->IsBitset()) { 501 return false;
398 return BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub()); 502 if (this->IsBitset() || that->IsBitset()) return true;
503
504 if (this->IsClass() != that->IsClass()) return true;
505
506 if (this->IsRange()) {
507 if (that->IsConstant()) {
508 return Contains(this->AsRange(), *that->AsConstant()->Value());
509 }
510 return that->IsRange() && Overlap(this->AsRange(), that->AsRange());
399 } 511 }
400 if (this->IsClass()) { 512 if (that->IsRange()) {
401 return that->IsClass() 513 if (this->IsConstant()) {
402 && *this->AsClass()->Map() == *that->AsClass()->Map(); 514 return Contains(that->AsRange(), *this->AsConstant()->Value());
403 } 515 }
404 if (this->IsConstant()) { 516 return this->IsRange() && Overlap(this->AsRange(), that->AsRange());
405 return that->IsConstant()
406 && *this->AsConstant()->Value() == *that->AsConstant()->Value();
407 }
408 if (this->IsContext()) {
409 return this->Equals(that);
410 }
411 if (this->IsArray()) {
412 // There is no variance!
413 return this->Equals(that);
414 }
415 if (this->IsFunction()) {
416 // There is no variance!
417 return this->Equals(that);
418 } 517 }
419 518
420 return false; 519 return this->SimplyEquals(that);
421 } 520 }
422 521
423 522
424 // Check if value is contained in (inhabits) type. 523 // Return the range in [this], or [NULL].
524 template<class Config>
525 typename TypeImpl<Config>::RangeType* TypeImpl<Config>::GetRange() {
526 DisallowHeapAllocation no_allocation;
527 if (this->IsRange()) return this->AsRange();
528 if (this->IsUnion() && this->AsUnion()->Get(1)->IsRange()) {
529 return this->AsUnion()->Get(1)->AsRange();
530 }
531 return NULL;
532 }
533
534
425 template<class Config> 535 template<class Config>
426 bool TypeImpl<Config>::Contains(i::Object* value) { 536 bool TypeImpl<Config>::Contains(i::Object* value) {
427 DisallowHeapAllocation no_allocation; 537 DisallowHeapAllocation no_allocation;
428 if (this->IsRange()) {
429 return value->IsNumber() &&
430 dle(this->AsRange()->Min(), value->Number()) &&
431 dle(value->Number(), this->AsRange()->Max()) &&
432 BitsetType::Is(BitsetType::Lub(value), this->BitsetLub());
433 }
434 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { 538 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) {
435 if (*it.Current() == value) return true; 539 if (*it.Current() == value) return true;
436 } 540 }
541 if (IsInteger(value)) {
542 RangeType* range = this->GetRange();
543 if (range != NULL && Contains(range, value)) return true;
544 }
437 return BitsetType::New(BitsetType::Lub(value))->Is(this); 545 return BitsetType::New(BitsetType::Lub(value))->Is(this);
438 } 546 }
439 547
440 548
441 template<class Config> 549 template<class Config>
442 bool TypeImpl<Config>::UnionType::Wellformed() { 550 bool TypeImpl<Config>::UnionType::Wellformed() {
443 DCHECK(this->Length() >= 2); 551 DisallowHeapAllocation no_allocation;
552 // This checks the invariants of the union representation:
553 // 1. There are at least two elements.
554 // 2. At most one element is a bitset, and it must be the first one.
555 // 3. At most one element is a range, and it must be the second one.
556 // 4. No element is itself a union.
557 // 5. No element is a subtype of any other.
558 DCHECK(this->Length() >= 2); // (1)
444 for (int i = 0; i < this->Length(); ++i) { 559 for (int i = 0; i < this->Length(); ++i) {
445 DCHECK(!this->Get(i)->IsUnion()); 560 if (i != 0) DCHECK(!this->Get(i)->IsBitset()); // (2)
446 if (i > 0) DCHECK(!this->Get(i)->IsBitset()); 561 if (i != 1) DCHECK(!this->Get(i)->IsRange()); // (3)
562 DCHECK(!this->Get(i)->IsUnion()); // (4)
447 for (int j = 0; j < this->Length(); ++j) { 563 for (int j = 0; j < this->Length(); ++j) {
448 if (i != j) DCHECK(!this->Get(i)->Is(this->Get(j))); 564 if (i != j) DCHECK(!this->Get(i)->Is(this->Get(j))); // (5)
449 } 565 }
450 } 566 }
451 return true; 567 return true;
452 } 568 }
453 569
454 570
455 // ----------------------------------------------------------------------------- 571 // -----------------------------------------------------------------------------
456 // Union and intersection 572 // Union and intersection
457 573
458 template<class Config> 574
459 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound( 575 static bool AddIsSafe(int x, int y) {
460 int bitset, Region* region) { 576 return x >= 0 ?
461 TypeHandle bound = BitsetType::New(bitset, region); 577 y <= std::numeric_limits<int>::max() - x :
462 if (this->IsClass()) { 578 y >= std::numeric_limits<int>::min() - x;
463 return ClassType::New(this->AsClass()->Map(), bound, region); 579 }
464 } else if (this->IsConstant()) { 580
465 return ConstantType::New(this->AsConstant()->Value(), bound, region); 581
466 } else if (this->IsRange()) { 582 template<class Config>
467 return RangeType::New( 583 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
468 this->AsRange()->Min(), this->AsRange()->Max(), bound, region); 584 TypeHandle type1, TypeHandle type2, Region* region) {
469 } else if (this->IsContext()) { 585 int bitset = type1->BitsetGlb() & type2->BitsetGlb();
470 return ContextType::New(this->AsContext()->Outer(), bound, region); 586 if (!BitsetType::IsInhabited(bitset)) bitset = BitsetType::kNone;
471 } else if (this->IsArray()) { 587
472 return ArrayType::New(this->AsArray()->Element(), bound, region); 588 // Fast case: bit sets.
473 } else if (this->IsFunction()) { 589 if (type1->IsBitset() && type2->IsBitset()) {
474 FunctionHandle function = Config::handle(this->AsFunction()); 590 return BitsetType::New(bitset, region);
475 int arity = function->Arity(); 591 }
476 FunctionHandle type = FunctionType::New( 592
477 function->Result(), function->Receiver(), bound, arity, region); 593 // Fast case: top or bottom types.
478 for (int i = 0; i < arity; ++i) { 594 if (type1->IsNone() || type2->IsAny()) return type1;
479 type->InitParameter(i, function->Parameter(i)); 595 if (type2->IsNone() || type2->IsAny()) return type2;
480 } 596
481 return type; 597 // Semi-fast case.
482 } 598 if (type1->Is(type2)) return type1;
483 UNREACHABLE(); 599 if (type2->Is(type1)) return type2;
484 return TypeHandle(); 600
485 } 601 // Slow case: create union.
486 602 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1;
487 603 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1;
488 template<class Config> 604 if (!AddIsSafe(size1, size2)) return Any(region);
489 int TypeImpl<Config>::BoundBy(TypeImpl* that) { 605 int size = size1 + size2;
490 DCHECK(!this->IsUnion()); 606 if (!AddIsSafe(size, 2)) return Any(region);
491 if (that->IsUnion()) { 607 size += 2;
492 UnionType* unioned = that->AsUnion(); 608 UnionHandle result = UnionType::New(size, region);
493 int length = unioned->Length(); 609 size = 0;
494 int bitset = BitsetType::kNone; 610
495 for (int i = 0; i < length; ++i) { 611 // Deal with bitsets.
496 bitset |= BoundBy(unioned->Get(i)->unhandle()); 612 result->Set(size++, BitsetType::New(bitset, region));
497 } 613
498 return bitset; 614 // Deal with ranges.
499 } else if (that->IsClass() && this->IsClass() && 615 TypeHandle range = None(region);
500 *this->AsClass()->Map() == *that->AsClass()->Map()) { 616 RangeType* range1 = type1->GetRange();
501 return that->BitsetLub(); 617 RangeType* range2 = type2->GetRange();
502 } else if (that->IsConstant() && this->IsConstant() && 618 if (range1 != NULL && range2 != NULL) {
503 *this->AsConstant()->Value() == *that->AsConstant()->Value()) { 619 Limits lim = Intersect(Limits(range1), Limits(range2));
504 return that->AsConstant()->Bound()->AsBitset(); 620 if (lim.min->Number() <= lim.max->Number()) {
505 } else if (that->IsContext() && this->IsContext() && this->Is(that)) { 621 range = RangeType::New(lim, region);
506 return that->AsContext()->Bound()->AsBitset(); 622 }
507 } else if (that->IsArray() && this->IsArray() && this->Is(that)) { 623 }
508 return that->AsArray()->Bound()->AsBitset(); 624 result->Set(size++, range);
509 } else if (that->IsFunction() && this->IsFunction() && this->Is(that)) { 625
510 return that->AsFunction()->Bound()->AsBitset(); 626 size = IntersectAux(type1, type2, result, size, region);
511 } 627 return NormalizeUnion(result, size);
512 return that->BitsetGlb(); 628 }
513 } 629
514 630
515 631 template<class Config>
516 template<class Config> 632 int TypeImpl<Config>::UpdateRange(
517 int TypeImpl<Config>::IndexInUnion( 633 RangeHandle range, UnionHandle result, int size, Region* region) {
518 int bound, UnionHandle unioned, int current_size) { 634 TypeHandle old_range = result->Get(1);
519 DCHECK(!this->IsUnion()); 635 if (range->Is(old_range)) return size;
520 for (int i = 0; i < current_size; ++i) { 636 if (!old_range->Is(range->unhandle())) {
521 TypeHandle that = unioned->Get(i); 637 range = RangeType::New(
522 if (that->IsBitset()) { 638 Union(Limits(range->AsRange()), Limits(old_range->AsRange())), region);
523 if (BitsetType::Is(bound, that->AsBitset())) return i; 639 }
524 } else if (that->IsClass() && this->IsClass()) { 640 result->Set(1, range);
525 if (*this->AsClass()->Map() == *that->AsClass()->Map()) return i; 641
526 } else if (that->IsConstant() && this->IsConstant()) { 642 // Remove any components that just got subsumed.
527 if (*this->AsConstant()->Value() == *that->AsConstant()->Value()) 643 for (int i = 2; i < size; ) {
528 return i; 644 if (result->Get(i)->Is(range->unhandle())) {
529 } else if (that->IsContext() && this->IsContext()) { 645 result->Set(i, result->Get(--size));
530 if (this->Is(that)) return i; 646 } else {
531 } else if (that->IsArray() && this->IsArray()) { 647 ++i;
532 if (this->Is(that)) return i;
533 } else if (that->IsFunction() && this->IsFunction()) {
534 if (this->Is(that)) return i;
535 }
536 }
537 return -1;
538 }
539
540
541 // Get non-bitsets from type, bounded by upper.
542 // Store at result starting at index. Returns updated index.
543 template<class Config>
544 int TypeImpl<Config>::ExtendUnion(
545 UnionHandle result, int size, TypeHandle type,
546 TypeHandle other, bool is_intersect, Region* region) {
547 if (type->IsUnion()) {
548 UnionHandle unioned = handle(type->AsUnion());
549 for (int i = 0; i < unioned->Length(); ++i) {
550 TypeHandle type_i = unioned->Get(i);
551 DCHECK(i == 0 || !(type_i->IsBitset() || type_i->Is(unioned->Get(0))));
552 if (!type_i->IsBitset()) {
553 size = ExtendUnion(result, size, type_i, other, is_intersect, region);
554 }
555 }
556 } else if (!type->IsBitset()) {
557 DCHECK(type->IsClass() || type->IsConstant() || type->IsRange() ||
558 type->IsContext() || type->IsArray() || type->IsFunction());
559 int inherent_bound = type->InherentBitsetLub();
560 int old_bound = type->BitsetLub();
561 int other_bound = type->BoundBy(other->unhandle()) & inherent_bound;
562 int new_bound =
563 is_intersect ? (old_bound & other_bound) : (old_bound | other_bound);
564 if (new_bound != BitsetType::kNone) {
565 int i = type->IndexInUnion(new_bound, result, size);
566 if (i == -1) {
567 i = size++;
568 } else if (result->Get(i)->IsBitset()) {
569 return size; // Already fully subsumed.
570 } else {
571 int type_i_bound = result->Get(i)->BitsetLub();
572 new_bound |= type_i_bound;
573 if (new_bound == type_i_bound) return size;
574 }
575 if (new_bound != old_bound) type = type->Rebound(new_bound, region);
576 result->Set(i, type);
577 } 648 }
578 } 649 }
579 return size; 650 return size;
580 } 651 }
581 652
582 653
583 // Union is O(1) on simple bitsets, but O(n*m) on structured unions. 654 template<class Config>
655 int TypeImpl<Config>::IntersectAux(
656 TypeHandle lhs, TypeHandle rhs,
657 UnionHandle result, int size, Region* region) {
658 if (lhs->IsUnion()) {
659 for (int i = 0; i < lhs->AsUnion()->Length(); ++i) {
660 size = IntersectAux(lhs->AsUnion()->Get(i), rhs, result, size, region);
661 }
662 return size;
663 }
664 if (rhs->IsUnion()) {
665 for (int i = 0; i < rhs->AsUnion()->Length(); ++i) {
666 size = IntersectAux(lhs, rhs->AsUnion()->Get(i), result, size, region);
667 }
668 return size;
669 }
670
671 if (!BitsetType::IsInhabited(lhs->BitsetLub() & rhs->BitsetLub())) {
672 return size;
673 }
674
675 if (lhs->IsBitset()) {
rossberg 2014/09/16 14:04:40 Hm, I wonder if this code wouldn't become clearer
neis1 2014/09/18 13:05:18 Done.
676 if (rhs->IsRange()) {
677 return UpdateRange(
678 Config::template cast<RangeType>(rhs), result, size, region);
679 } else {
680 return AddToUnion(rhs, result, size, region);
681 }
682 }
683 if (rhs->IsBitset()) {
684 if (lhs->IsRange()) {
685 return UpdateRange(
686 Config::template cast<RangeType>(lhs), result, size, region);
687 } else {
688 return AddToUnion(lhs, result, size, region);
689 }
690 }
691 if (lhs->IsClass() && !rhs->IsClass()) {
692 if (rhs->IsRange()) {
693 return UpdateRange(
694 Config::template cast<RangeType>(rhs), result, size, region);
695 } else {
696 return AddToUnion(rhs, result, size, region);
697 }
698 }
699 if (rhs->IsClass() && !lhs->IsClass()) {
700 if (lhs->IsRange()) {
701 return UpdateRange(
702 Config::template cast<RangeType>(lhs), result, size, region);
703 } else {
704 return AddToUnion(lhs, result, size, region);
705 }
706 }
707 if (lhs->IsRange()) {
708 if (rhs->IsConstant() &&
709 Contains(lhs->AsRange(), *rhs->AsConstant()->Value())) {
710 return AddToUnion(rhs, result, size, region);
711 }
712 return size; // Shortcut.
713 }
714 if (rhs->IsRange()) {
715 if (lhs->IsConstant() &&
716 Contains(rhs->AsRange(), *lhs->AsConstant()->Value())) {
717 return AddToUnion(lhs, result, size, region);
718 }
719 return size; // Shortcut.
720 }
721
722 if (lhs->Is(rhs)) return AddToUnion(lhs, result, size, region);
723 if (rhs->Is(lhs)) return AddToUnion(rhs, result, size, region);
724 return size;
725 }
726
727
584 template<class Config> 728 template<class Config>
585 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( 729 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
586 TypeHandle type1, TypeHandle type2, Region* region) { 730 TypeHandle type1, TypeHandle type2, Region* region) {
731
587 // Fast case: bit sets. 732 // Fast case: bit sets.
588 if (type1->IsBitset() && type2->IsBitset()) { 733 if (type1->IsBitset() && type2->IsBitset()) {
589 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); 734 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region);
590 } 735 }
591 736
592 // Fast case: top or bottom types. 737 // Fast case: top or bottom types.
593 if (type1->IsAny() || type2->IsNone()) return type1; 738 if (type1->IsAny() || type2->IsNone()) return type1;
594 if (type2->IsAny() || type1->IsNone()) return type2; 739 if (type2->IsAny() || type1->IsNone()) return type2;
595 740
596 // Semi-fast case: Unioned objects are neither involved nor produced. 741 // Semi-fast case.
597 if (!(type1->IsUnion() || type2->IsUnion())) { 742 if (type1->Is(type2)) return type2;
598 if (type1->Is(type2)) return type2; 743 if (type2->Is(type1)) return type1;
599 if (type2->Is(type1)) return type1; 744
600 } 745 // Slow case: create union.
601 746 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1;
602 // Slow case: may need to produce a Unioned object. 747 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1;
603 int size = 0; 748 if (!AddIsSafe(size1, size2)) return Any(region);
604 if (!type1->IsBitset()) { 749 int size = size1 + size2;
605 size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1); 750 if (!AddIsSafe(size, 2)) return Any(region);
606 } 751 size += 2;
607 if (!type2->IsBitset()) { 752 UnionHandle result = UnionType::New(size, region);
608 size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1);
609 }
610 int bitset = type1->BitsetGlb() | type2->BitsetGlb();
611 if (bitset != BitsetType::kNone) ++size;
612 DCHECK(size >= 1);
613
614 UnionHandle unioned = UnionType::New(size, region);
615 size = 0; 753 size = 0;
616 if (bitset != BitsetType::kNone) { 754
617 unioned->Set(size++, BitsetType::New(bitset, region)); 755 // Deal with bitsets.
618 } 756 TypeHandle bitset = BitsetType::New(
619 size = ExtendUnion(unioned, size, type1, type2, false, region); 757 type1->BitsetGlb() | type2->BitsetGlb(), region);
620 size = ExtendUnion(unioned, size, type2, type1, false, region); 758 result->Set(size++, bitset);
621 759
622 if (size == 1) { 760 // Deal with ranges.
623 return unioned->Get(0); 761 TypeHandle range = None(region);
624 } else { 762 RangeType* range1 = type1->GetRange();
625 unioned->Shrink(size); 763 RangeType* range2 = type2->GetRange();
626 DCHECK(unioned->Wellformed()); 764 if (range1 != NULL && range2 != NULL) {
627 return unioned; 765 range = RangeType::New(Union(Limits(range1), Limits(range2)), region);
628 } 766 } else if (range1 != NULL) {
629 } 767 range = handle(range1);
630 768 } else if (range2 != NULL) {
631 769 range = handle(range2);
632 // Intersection is O(1) on simple bitsets, but O(n*m) on structured unions. 770 }
633 template<class Config> 771 result->Set(size++, range);
634 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect( 772
635 TypeHandle type1, TypeHandle type2, Region* region) { 773 size = AddToUnion(type1, result, size, region);
636 // Fast case: bit sets. 774 size = AddToUnion(type2, result, size, region);
637 if (type1->IsBitset() && type2->IsBitset()) { 775 return NormalizeUnion(result, size);
638 return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region); 776 }
639 } 777
640 778
641 // Fast case: top or bottom types. 779 // Add [type] to [result] unless [type] is bitset, range, or already subsumed.
642 if (type1->IsNone() || type2->IsAny()) return type1; 780 // Return new size of [result].
643 if (type2->IsNone() || type1->IsAny()) return type2; 781 template<class Config>
644 782 int TypeImpl<Config>::AddToUnion(
645 // Semi-fast case: Unioned objects are neither involved nor produced. 783 TypeHandle type, UnionHandle result, int size, Region* region) {
646 if (!(type1->IsUnion() || type2->IsUnion())) { 784 if (type->IsBitset() || type->IsRange()) return size;
647 if (type1->Is(type2)) return type1; 785 if (type->IsUnion()) {
648 if (type2->Is(type1)) return type2; 786 for (int i = 0; i < type->AsUnion()->Length(); ++i) {
649 } 787 size = AddToUnion(type->AsUnion()->Get(i), result, size, region);
650 788 }
651 // Slow case: may need to produce a Unioned object. 789 return size;
652 int size = 0; 790 }
653 if (!type1->IsBitset()) { 791 for (int i = 0; i < size; ++i) {
654 size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1); 792 if (type->Is(result->Get(i))) return size;
655 } 793 }
656 if (!type2->IsBitset()) { 794 result->Set(size++, type);
657 size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1); 795 return size;
658 } 796 }
659 int bitset = type1->BitsetGlb() & type2->BitsetGlb(); 797
660 if (bitset != BitsetType::kNone) ++size; 798
661 DCHECK(size >= 1); 799 template<class Config>
662 800 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeUnion(
663 UnionHandle unioned = UnionType::New(size, region); 801 UnionHandle unioned, int size) {
664 size = 0; 802 DCHECK(size >= 2);
665 if (bitset != BitsetType::kNone) { 803 // If range is subsumed by bitset, use its place for a different type.
666 unioned->Set(size++, BitsetType::New(bitset, region)); 804 if (unioned->Get(1)->Is(unioned->Get(0))) {
667 } 805 unioned->Set(1, unioned->Get(--size));
668 size = ExtendUnion(unioned, size, type1, type2, true, region); 806 }
669 size = ExtendUnion(unioned, size, type2, type1, true, region); 807 // If bitset is None, use its place for a different type.
670 808 if (size >= 2 && unioned->Get(0)->IsNone()) {
671 if (size == 0) { 809 unioned->Set(0, unioned->Get(--size));
672 return None(region); 810 }
673 } else if (size == 1) { 811 if (size == 1) return unioned->Get(0);
674 return unioned->Get(0); 812 unioned->Shrink(size);
675 } else { 813 SLOW_DCHECK(unioned->Wellformed());
676 unioned->Shrink(size); 814 return unioned;
677 DCHECK(unioned->Wellformed()); 815 }
678 return unioned; 816
679 } 817
680 }
681
682
683 // ----------------------------------------------------------------------------- 818 // -----------------------------------------------------------------------------
684 // Iteration. 819 // Iteration.
685 820
686 template<class Config> 821 template<class Config>
687 int TypeImpl<Config>::NumClasses() { 822 int TypeImpl<Config>::NumClasses() {
688 DisallowHeapAllocation no_allocation; 823 DisallowHeapAllocation no_allocation;
689 if (this->IsClass()) { 824 if (this->IsClass()) {
690 return 1; 825 return 1;
691 } else if (this->IsUnion()) { 826 } else if (this->IsUnion()) {
692 UnionHandle unioned = handle(this->AsUnion()); 827 UnionHandle unioned = handle(this->AsUnion());
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 // ----------------------------------------------------------------------------- 921 // -----------------------------------------------------------------------------
787 // Conversion between low-level representations. 922 // Conversion between low-level representations.
788 923
789 template<class Config> 924 template<class Config>
790 template<class OtherType> 925 template<class OtherType>
791 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( 926 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
792 typename OtherType::TypeHandle type, Region* region) { 927 typename OtherType::TypeHandle type, Region* region) {
793 if (type->IsBitset()) { 928 if (type->IsBitset()) {
794 return BitsetType::New(type->AsBitset(), region); 929 return BitsetType::New(type->AsBitset(), region);
795 } else if (type->IsClass()) { 930 } else if (type->IsClass()) {
796 TypeHandle bound = BitsetType::New(type->BitsetLub(), region); 931 return ClassType::New(type->AsClass()->Map(), region);
797 return ClassType::New(type->AsClass()->Map(), bound, region);
798 } else if (type->IsConstant()) { 932 } else if (type->IsConstant()) {
799 TypeHandle bound = Convert<OtherType>(type->AsConstant()->Bound(), region); 933 return ConstantType::New(type->AsConstant()->Value(), region);
800 return ConstantType::New(type->AsConstant()->Value(), bound, region);
801 } else if (type->IsRange()) { 934 } else if (type->IsRange()) {
802 TypeHandle bound = Convert<OtherType>(type->AsRange()->Bound(), region);
803 return RangeType::New( 935 return RangeType::New(
804 type->AsRange()->Min(), type->AsRange()->Max(), bound, region); 936 type->AsRange()->MinV(), type->AsRange()->MaxV(), region);
805 } else if (type->IsContext()) { 937 } else if (type->IsContext()) {
806 TypeHandle bound = Convert<OtherType>(type->AsContext()->Bound(), region);
807 TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region); 938 TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region);
808 return ContextType::New(outer, bound, region); 939 return ContextType::New(outer, region);
809 } else if (type->IsUnion()) { 940 } else if (type->IsUnion()) {
810 int length = type->AsUnion()->Length(); 941 int length = type->AsUnion()->Length();
811 UnionHandle unioned = UnionType::New(length, region); 942 UnionHandle unioned = UnionType::New(length, region);
812 for (int i = 0; i < length; ++i) { 943 for (int i = 0; i < length; ++i) {
813 TypeHandle t = Convert<OtherType>(type->AsUnion()->Get(i), region); 944 TypeHandle t = Convert<OtherType>(type->AsUnion()->Get(i), region);
814 unioned->Set(i, t); 945 unioned->Set(i, t);
815 } 946 }
816 return unioned; 947 return unioned;
817 } else if (type->IsArray()) { 948 } else if (type->IsArray()) {
818 TypeHandle element = Convert<OtherType>(type->AsArray()->Element(), region); 949 TypeHandle element = Convert<OtherType>(type->AsArray()->Element(), region);
819 TypeHandle bound = Convert<OtherType>(type->AsArray()->Bound(), region); 950 return ArrayType::New(element, region);
820 return ArrayType::New(element, bound, region);
821 } else if (type->IsFunction()) { 951 } else if (type->IsFunction()) {
822 TypeHandle res = Convert<OtherType>(type->AsFunction()->Result(), region); 952 TypeHandle res = Convert<OtherType>(type->AsFunction()->Result(), region);
823 TypeHandle rcv = Convert<OtherType>(type->AsFunction()->Receiver(), region); 953 TypeHandle rcv = Convert<OtherType>(type->AsFunction()->Receiver(), region);
824 TypeHandle bound = Convert<OtherType>(type->AsFunction()->Bound(), region);
825 FunctionHandle function = FunctionType::New( 954 FunctionHandle function = FunctionType::New(
826 res, rcv, bound, type->AsFunction()->Arity(), region); 955 res, rcv, type->AsFunction()->Arity(), region);
827 for (int i = 0; i < function->Arity(); ++i) { 956 for (int i = 0; i < function->Arity(); ++i) {
828 TypeHandle param = Convert<OtherType>( 957 TypeHandle param = Convert<OtherType>(
829 type->AsFunction()->Parameter(i), region); 958 type->AsFunction()->Parameter(i), region);
830 function->InitParameter(i, param); 959 function->InitParameter(i, param);
831 } 960 }
832 return function; 961 return function;
833 } else { 962 } else {
834 UNREACHABLE(); 963 UNREACHABLE();
835 return None(region); 964 return None(region);
836 } 965 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 DisallowHeapAllocation no_allocation; 1030 DisallowHeapAllocation no_allocation;
902 if (dim != REPRESENTATION_DIM) { 1031 if (dim != REPRESENTATION_DIM) {
903 if (this->IsBitset()) { 1032 if (this->IsBitset()) {
904 BitsetType::Print(os, SEMANTIC(this->AsBitset())); 1033 BitsetType::Print(os, SEMANTIC(this->AsBitset()));
905 } else if (this->IsClass()) { 1034 } else if (this->IsClass()) {
906 os << "Class(" << static_cast<void*>(*this->AsClass()->Map()) << " < "; 1035 os << "Class(" << static_cast<void*>(*this->AsClass()->Map()) << " < ";
907 BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim); 1036 BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim);
908 os << ")"; 1037 os << ")";
909 } else if (this->IsConstant()) { 1038 } else if (this->IsConstant()) {
910 os << "Constant(" << static_cast<void*>(*this->AsConstant()->Value()) 1039 os << "Constant(" << static_cast<void*>(*this->AsConstant()->Value())
911 << " : "; 1040 << ")";
912 BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim);
913 os << ")";
914 } else if (this->IsRange()) { 1041 } else if (this->IsRange()) {
915 os << "Range(" << this->AsRange()->Min() 1042 os << "Range(" << this->AsRange()->Min()
916 << ".." << this->AsRange()->Max() << " : "; 1043 << ", " << this->AsRange()->Max() << ")";
917 BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim);
918 os << ")";
919 } else if (this->IsContext()) { 1044 } else if (this->IsContext()) {
920 os << "Context("; 1045 os << "Context(";
921 this->AsContext()->Outer()->PrintTo(os, dim); 1046 this->AsContext()->Outer()->PrintTo(os, dim);
922 os << ")"; 1047 os << ")";
923 } else if (this->IsUnion()) { 1048 } else if (this->IsUnion()) {
924 os << "("; 1049 os << "(";
925 UnionHandle unioned = handle(this->AsUnion()); 1050 UnionHandle unioned = handle(this->AsUnion());
926 for (int i = 0; i < unioned->Length(); ++i) { 1051 for (int i = 0; i < unioned->Length(); ++i) {
927 TypeHandle type_i = unioned->Get(i); 1052 TypeHandle type_i = unioned->Get(i);
928 if (i > 0) os << " | "; 1053 if (i > 0) os << " | ";
929 type_i->PrintTo(os, dim); 1054 type_i->PrintTo(os, dim);
930 } 1055 }
931 os << ")"; 1056 os << ")";
932 } else if (this->IsArray()) { 1057 } else if (this->IsArray()) {
933 os << "Array("; 1058 os << "Array(";
934 AsArray()->Element()->PrintTo(os, dim); 1059 AsArray()->Element()->PrintTo(os, dim);
935 os << ")"; 1060 os << ")";
936 } else if (this->IsFunction()) { 1061 } else if (this->IsFunction()) {
1062 os << "Function[";
937 if (!this->AsFunction()->Receiver()->IsAny()) { 1063 if (!this->AsFunction()->Receiver()->IsAny()) {
938 this->AsFunction()->Receiver()->PrintTo(os, dim); 1064 this->AsFunction()->Receiver()->PrintTo(os, dim);
939 os << "."; 1065 os << ".";
940 } 1066 }
941 os << "("; 1067 os << "(";
942 for (int i = 0; i < this->AsFunction()->Arity(); ++i) { 1068 for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
943 if (i > 0) os << ", "; 1069 if (i > 0) os << ", ";
944 this->AsFunction()->Parameter(i)->PrintTo(os, dim); 1070 this->AsFunction()->Parameter(i)->PrintTo(os, dim);
945 } 1071 }
946 os << ")->"; 1072 os << ")->";
947 this->AsFunction()->Result()->PrintTo(os, dim); 1073 this->AsFunction()->Result()->PrintTo(os, dim);
1074 os << "]";
948 } else { 1075 } else {
949 UNREACHABLE(); 1076 UNREACHABLE();
950 } 1077 }
951 } 1078 }
952 if (dim == BOTH_DIMS) os << "/"; 1079 if (dim == BOTH_DIMS) os << "/";
953 if (dim != SEMANTIC_DIM) { 1080 if (dim != SEMANTIC_DIM) {
954 BitsetType::Print(os, REPRESENTATION(this->BitsetLub())); 1081 BitsetType::Print(os, REPRESENTATION(this->BitsetLub()));
955 } 1082 }
956 } 1083 }
957 1084
958 1085
959 #ifdef DEBUG 1086 #ifdef DEBUG
960 template <class Config> 1087 template <class Config>
961 void TypeImpl<Config>::Print() { 1088 void TypeImpl<Config>::Print() {
962 OFStream os(stdout); 1089 OFStream os(stdout);
963 PrintTo(os); 1090 PrintTo(os);
964 os << endl; 1091 os << endl;
965 } 1092 }
1093 template <class Config>
1094 void TypeImpl<Config>::BitsetType::Print(int bitset) {
1095 OFStream os(stdout);
1096 Print(os, bitset);
1097 os << endl;
1098 }
966 #endif 1099 #endif
967 1100
968 1101
969 // ----------------------------------------------------------------------------- 1102 // -----------------------------------------------------------------------------
970 // Instantiations. 1103 // Instantiations.
971 1104
972 template class TypeImpl<ZoneTypeConfig>; 1105 template class TypeImpl<ZoneTypeConfig>;
973 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>; 1106 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>;
974 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>; 1107 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>;
975 1108
976 template class TypeImpl<HeapTypeConfig>; 1109 template class TypeImpl<HeapTypeConfig>;
977 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>; 1110 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>;
978 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; 1111 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>;
979 1112
980 template TypeImpl<ZoneTypeConfig>::TypeHandle 1113 template TypeImpl<ZoneTypeConfig>::TypeHandle
981 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( 1114 TypeImpl<ZoneTypeConfig>::Convert<HeapType>(
982 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); 1115 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*);
983 template TypeImpl<HeapTypeConfig>::TypeHandle 1116 template TypeImpl<HeapTypeConfig>::TypeHandle
984 TypeImpl<HeapTypeConfig>::Convert<Type>( 1117 TypeImpl<HeapTypeConfig>::Convert<Type>(
985 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); 1118 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*);
986 1119
987 } } // namespace v8::internal 1120 } } // namespace v8::internal
OLDNEW
« src/types.h ('K') | « src/types.h ('k') | test/cctest/test-types.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698