OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/js-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
9 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
11 #include "src/compiler/js-operator.h" | 11 #include "src/compiler/js-operator.h" |
12 #include "src/contexts.h" | 12 #include "src/contexts.h" |
13 #include "src/field-index-inl.h" | 13 #include "src/field-index-inl.h" |
14 #include "src/lookup.h" | 14 #include "src/lookup.h" |
15 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | 15 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
| 16 #include "src/type-cache.h" |
16 #include "src/type-feedback-vector.h" | 17 #include "src/type-feedback-vector.h" |
17 | 18 |
18 namespace v8 { | 19 namespace v8 { |
19 namespace internal { | 20 namespace internal { |
20 namespace compiler { | 21 namespace compiler { |
21 | 22 |
22 struct JSNativeContextSpecialization::ScriptContextTableLookupResult { | 23 struct JSNativeContextSpecialization::ScriptContextTableLookupResult { |
23 Handle<Context> context; | 24 Handle<Context> context; |
24 bool immutable; | 25 bool immutable; |
25 int index; | 26 int index; |
26 }; | 27 }; |
27 | 28 |
28 | 29 |
29 JSNativeContextSpecialization::JSNativeContextSpecialization( | 30 JSNativeContextSpecialization::JSNativeContextSpecialization( |
30 Editor* editor, JSGraph* jsgraph, Flags flags, | 31 Editor* editor, JSGraph* jsgraph, Flags flags, |
31 Handle<GlobalObject> global_object, CompilationDependencies* dependencies, | 32 Handle<GlobalObject> global_object, CompilationDependencies* dependencies, |
32 Zone* zone) | 33 Zone* zone) |
33 : AdvancedReducer(editor), | 34 : AdvancedReducer(editor), |
34 jsgraph_(jsgraph), | 35 jsgraph_(jsgraph), |
35 flags_(flags), | 36 flags_(flags), |
36 global_object_(global_object), | 37 global_object_(global_object), |
37 native_context_(global_object->native_context(), isolate()), | 38 native_context_(global_object->native_context(), isolate()), |
38 dependencies_(dependencies), | 39 dependencies_(dependencies), |
39 zone_(zone) {} | 40 zone_(zone), |
| 41 type_cache_(TypeCache::Get()) {} |
40 | 42 |
41 | 43 |
42 Reduction JSNativeContextSpecialization::Reduce(Node* node) { | 44 Reduction JSNativeContextSpecialization::Reduce(Node* node) { |
43 switch (node->opcode()) { | 45 switch (node->opcode()) { |
44 case IrOpcode::kJSLoadGlobal: | 46 case IrOpcode::kJSLoadGlobal: |
45 return ReduceJSLoadGlobal(node); | 47 return ReduceJSLoadGlobal(node); |
46 case IrOpcode::kJSStoreGlobal: | 48 case IrOpcode::kJSStoreGlobal: |
47 return ReduceJSStoreGlobal(node); | 49 return ReduceJSStoreGlobal(node); |
48 case IrOpcode::kJSLoadNamed: | 50 case IrOpcode::kJSLoadNamed: |
49 return ReduceJSLoadNamed(node); | 51 return ReduceJSLoadNamed(node); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 // Load from constant/undefined global property can be constant-folded. | 109 // Load from constant/undefined global property can be constant-folded. |
108 if ((property_details.cell_type() == PropertyCellType::kConstant || | 110 if ((property_details.cell_type() == PropertyCellType::kConstant || |
109 property_details.cell_type() == PropertyCellType::kUndefined)) { | 111 property_details.cell_type() == PropertyCellType::kUndefined)) { |
110 return Replace(node, property_cell_value); | 112 return Replace(node, property_cell_value); |
111 } | 113 } |
112 | 114 |
113 // Load from constant type cell can benefit from type feedback. | 115 // Load from constant type cell can benefit from type feedback. |
114 if (property_details.cell_type() == PropertyCellType::kConstantType) { | 116 if (property_details.cell_type() == PropertyCellType::kConstantType) { |
115 // Compute proper type based on the current value in the cell. | 117 // Compute proper type based on the current value in the cell. |
116 if (property_cell_value->IsSmi()) { | 118 if (property_cell_value->IsSmi()) { |
117 property_cell_value_type = Type::Intersect( | 119 property_cell_value_type = type_cache_.kSmi; |
118 Type::SignedSmall(), Type::TaggedSigned(), graph()->zone()); | |
119 } else if (property_cell_value->IsNumber()) { | 120 } else if (property_cell_value->IsNumber()) { |
120 property_cell_value_type = Type::Intersect( | 121 property_cell_value_type = type_cache_.kHeapNumber; |
121 Type::Number(), Type::TaggedPointer(), graph()->zone()); | |
122 } else { | 122 } else { |
123 Handle<Map> property_cell_value_map( | 123 Handle<Map> property_cell_value_map( |
124 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); | 124 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); |
125 property_cell_value_type = | 125 property_cell_value_type = |
126 Type::Class(property_cell_value_map, graph()->zone()); | 126 Type::Class(property_cell_value_map, graph()->zone()); |
127 } | 127 } |
128 } | 128 } |
129 } else if (property_details.IsConfigurable()) { | 129 } else if (property_details.IsConfigurable()) { |
130 // Access to configurable global properties requires deoptimization support. | 130 // Access to configurable global properties requires deoptimization support. |
131 return NoChange(); | 131 return NoChange(); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 // Don't bother optimizing stores to special JSObject field accessors. | 324 // Don't bother optimizing stores to special JSObject field accessors. |
325 if (access_mode == kStore) { | 325 if (access_mode == kStore) { |
326 break; | 326 break; |
327 } | 327 } |
328 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); | 328 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); |
329 Type* field_type = Type::Tagged(); | 329 Type* field_type = Type::Tagged(); |
330 if (map->IsStringMap()) { | 330 if (map->IsStringMap()) { |
331 DCHECK(Name::Equals(factory()->length_string(), name)); | 331 DCHECK(Name::Equals(factory()->length_string(), name)); |
332 // The String::length property is always a smi in the range | 332 // The String::length property is always a smi in the range |
333 // [0, String::kMaxLength]. | 333 // [0, String::kMaxLength]. |
334 field_type = Type::Intersect( | 334 field_type = type_cache_.kStringLengthType; |
335 Type::Range(0.0, String::kMaxLength, graph()->zone()), | |
336 Type::TaggedSigned(), graph()->zone()); | |
337 } else if (map->IsJSArrayMap()) { | 335 } else if (map->IsJSArrayMap()) { |
338 DCHECK(Name::Equals(factory()->length_string(), name)); | 336 DCHECK(Name::Equals(factory()->length_string(), name)); |
339 // The JSArray::length property is a smi in the range | 337 // The JSArray::length property is a smi in the range |
340 // [0, FixedDoubleArray::kMaxLength] in case of fast double | 338 // [0, FixedDoubleArray::kMaxLength] in case of fast double |
341 // elements, a smi in the range [0, FixedArray::kMaxLength] | 339 // elements, a smi in the range [0, FixedArray::kMaxLength] |
342 // in case of other fast elements, and [0, kMaxUInt32] in | 340 // in case of other fast elements, and [0, kMaxUInt32] in |
343 // case of other arrays. | 341 // case of other arrays. |
344 Type* field_type_rep = Type::Tagged(); | 342 if (IsFastDoubleElementsKind(map->elements_kind())) { |
345 double field_type_upper = kMaxUInt32; | 343 field_type = type_cache_.kFixedDoubleArrayLengthType; |
346 if (IsFastElementsKind(map->elements_kind())) { | 344 } else if (IsFastElementsKind(map->elements_kind())) { |
347 field_type_rep = Type::TaggedSigned(); | 345 field_type = type_cache_.kFixedArrayLengthType; |
348 field_type_upper = IsFastDoubleElementsKind(map->elements_kind()) | 346 } else { |
349 ? FixedDoubleArray::kMaxLength | 347 field_type = type_cache_.kJSArrayLengthType; |
350 : FixedArray::kMaxLength; | |
351 } | 348 } |
352 field_type = | |
353 Type::Intersect(Type::Range(0.0, field_type_upper, graph()->zone()), | |
354 field_type_rep, graph()->zone()); | |
355 } | 349 } |
356 *access_info = PropertyAccessInfo::DataField(receiver_type, field_index, | 350 *access_info = PropertyAccessInfo::DataField(receiver_type, field_index, |
357 field_type, holder); | 351 field_type, holder); |
358 return true; | 352 return true; |
359 } | 353 } |
360 | 354 |
361 // Lookup the named property on the {map}. | 355 // Lookup the named property on the {map}. |
362 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); | 356 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); |
363 int const number = descriptors->SearchWithCache(*name, *map); | 357 int const number = descriptors->SearchWithCache(*name, *map); |
364 if (number != DescriptorArray::kNotFound) { | 358 if (number != DescriptorArray::kNotFound) { |
(...skipping 10 matching lines...) Expand all Loading... |
375 // Don't bother optimizing stores to read-only properties. | 369 // Don't bother optimizing stores to read-only properties. |
376 if (access_mode == kStore && details.IsReadOnly()) { | 370 if (access_mode == kStore && details.IsReadOnly()) { |
377 break; | 371 break; |
378 } | 372 } |
379 int index = descriptors->GetFieldIndex(number); | 373 int index = descriptors->GetFieldIndex(number); |
380 Representation field_representation = details.representation(); | 374 Representation field_representation = details.representation(); |
381 FieldIndex field_index = FieldIndex::ForPropertyIndex( | 375 FieldIndex field_index = FieldIndex::ForPropertyIndex( |
382 *map, index, field_representation.IsDouble()); | 376 *map, index, field_representation.IsDouble()); |
383 Type* field_type = Type::Tagged(); | 377 Type* field_type = Type::Tagged(); |
384 if (field_representation.IsSmi()) { | 378 if (field_representation.IsSmi()) { |
385 field_type = Type::Intersect(Type::SignedSmall(), | 379 field_type = type_cache_.kSmi; |
386 Type::TaggedSigned(), graph()->zone()); | |
387 } else if (field_representation.IsDouble()) { | 380 } else if (field_representation.IsDouble()) { |
388 if (access_mode == kStore) { | 381 if (access_mode == kStore) { |
389 // TODO(bmeurer): Add support for storing to double fields. | 382 // TODO(bmeurer): Add support for storing to double fields. |
390 break; | 383 break; |
391 } | 384 } |
392 field_type = Type::Intersect(Type::Number(), Type::UntaggedFloat64(), | 385 field_type = type_cache_.kFloat64; |
393 graph()->zone()); | |
394 } else if (field_representation.IsHeapObject()) { | 386 } else if (field_representation.IsHeapObject()) { |
395 // Extract the field type from the property details (make sure its | 387 // Extract the field type from the property details (make sure its |
396 // representation is TaggedPointer to reflect the heap object case). | 388 // representation is TaggedPointer to reflect the heap object case). |
397 field_type = Type::Intersect( | 389 field_type = Type::Intersect( |
398 Type::Convert<HeapType>( | 390 Type::Convert<HeapType>( |
399 handle(descriptors->GetFieldType(number), isolate()), | 391 handle(descriptors->GetFieldType(number), isolate()), |
400 graph()->zone()), | 392 graph()->zone()), |
401 Type::TaggedPointer(), graph()->zone()); | 393 Type::TaggedPointer(), graph()->zone()); |
402 if (field_type->Is(Type::None())) { | 394 if (field_type->Is(Type::None())) { |
403 if (access_mode == kStore) { | 395 if (access_mode == kStore) { |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 } | 828 } |
837 | 829 |
838 | 830 |
839 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 831 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
840 return jsgraph()->simplified(); | 832 return jsgraph()->simplified(); |
841 } | 833 } |
842 | 834 |
843 } // namespace compiler | 835 } // namespace compiler |
844 } // namespace internal | 836 } // namespace internal |
845 } // namespace v8 | 837 } // namespace v8 |
OLD | NEW |