| 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 |