| 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-global-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
| 6 | 6 |
| 7 #include "src/compilation-dependencies.h" | 7 #include "src/compilation-dependencies.h" |
| 8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/js-operator.h" | 10 #include "src/compiler/js-operator.h" |
| 11 #include "src/contexts.h" | 11 #include "src/contexts.h" |
| 12 #include "src/field-index-inl.h" | 12 #include "src/field-index-inl.h" |
| 13 #include "src/lookup.h" | 13 #include "src/lookup.h" |
| 14 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | 14 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
| 15 #include "src/type-feedback-vector.h" | 15 #include "src/type-feedback-vector.h" |
| 16 | 16 |
| 17 namespace v8 { | 17 namespace v8 { |
| 18 namespace internal { | 18 namespace internal { |
| 19 namespace compiler { | 19 namespace compiler { |
| 20 | 20 |
| 21 struct JSGlobalSpecialization::ScriptContextTableLookupResult { | 21 struct JSNativeContextSpecialization::ScriptContextTableLookupResult { |
| 22 Handle<Context> context; | 22 Handle<Context> context; |
| 23 bool immutable; | 23 bool immutable; |
| 24 int index; | 24 int index; |
| 25 }; | 25 }; |
| 26 | 26 |
| 27 | 27 |
| 28 JSGlobalSpecialization::JSGlobalSpecialization( | 28 JSNativeContextSpecialization::JSNativeContextSpecialization( |
| 29 Editor* editor, JSGraph* jsgraph, Flags flags, | 29 Editor* editor, JSGraph* jsgraph, Flags flags, |
| 30 Handle<GlobalObject> global_object, CompilationDependencies* dependencies, | 30 Handle<GlobalObject> global_object, CompilationDependencies* dependencies, |
| 31 Zone* zone) | 31 Zone* zone) |
| 32 : AdvancedReducer(editor), | 32 : AdvancedReducer(editor), |
| 33 jsgraph_(jsgraph), | 33 jsgraph_(jsgraph), |
| 34 flags_(flags), | 34 flags_(flags), |
| 35 global_object_(global_object), | 35 global_object_(global_object), |
| 36 dependencies_(dependencies), | 36 dependencies_(dependencies), |
| 37 zone_(zone) {} | 37 zone_(zone) {} |
| 38 | 38 |
| 39 | 39 |
| 40 Reduction JSGlobalSpecialization::Reduce(Node* node) { | 40 Reduction JSNativeContextSpecialization::Reduce(Node* node) { |
| 41 switch (node->opcode()) { | 41 switch (node->opcode()) { |
| 42 case IrOpcode::kJSLoadGlobal: | 42 case IrOpcode::kJSLoadGlobal: |
| 43 return ReduceJSLoadGlobal(node); | 43 return ReduceJSLoadGlobal(node); |
| 44 case IrOpcode::kJSStoreGlobal: | 44 case IrOpcode::kJSStoreGlobal: |
| 45 return ReduceJSStoreGlobal(node); | 45 return ReduceJSStoreGlobal(node); |
| 46 case IrOpcode::kJSLoadNamed: | 46 case IrOpcode::kJSLoadNamed: |
| 47 return ReduceJSLoadNamed(node); | 47 return ReduceJSLoadNamed(node); |
| 48 default: | 48 default: |
| 49 break; | 49 break; |
| 50 } | 50 } |
| 51 return NoChange(); | 51 return NoChange(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 Reduction JSGlobalSpecialization::ReduceJSLoadGlobal(Node* node) { | 55 Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) { |
| 56 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); | 56 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); |
| 57 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); | 57 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); |
| 58 Node* effect = NodeProperties::GetEffectInput(node); | 58 Node* effect = NodeProperties::GetEffectInput(node); |
| 59 Node* control = NodeProperties::GetControlInput(node); | 59 Node* control = NodeProperties::GetControlInput(node); |
| 60 | 60 |
| 61 // Try to lookup the name on the script context table first (lexical scoping). | 61 // Try to lookup the name on the script context table first (lexical scoping). |
| 62 ScriptContextTableLookupResult result; | 62 ScriptContextTableLookupResult result; |
| 63 if (LookupInScriptContextTable(name, &result)) { | 63 if (LookupInScriptContextTable(name, &result)) { |
| 64 Node* context = jsgraph()->Constant(result.context); | 64 Node* context = jsgraph()->Constant(result.context); |
| 65 Node* value = effect = graph()->NewNode( | 65 Node* value = effect = graph()->NewNode( |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 124 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 125 dependencies()->AssumePropertyCell(property_cell); | 125 dependencies()->AssumePropertyCell(property_cell); |
| 126 } | 126 } |
| 127 Node* value = effect = graph()->NewNode( | 127 Node* value = effect = graph()->NewNode( |
| 128 simplified()->LoadField(AccessBuilder::ForPropertyCellValue()), | 128 simplified()->LoadField(AccessBuilder::ForPropertyCellValue()), |
| 129 jsgraph()->Constant(property_cell), effect, control); | 129 jsgraph()->Constant(property_cell), effect, control); |
| 130 return Replace(node, value, effect); | 130 return Replace(node, value, effect); |
| 131 } | 131 } |
| 132 | 132 |
| 133 | 133 |
| 134 Reduction JSGlobalSpecialization::ReduceJSStoreGlobal(Node* node) { | 134 Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) { |
| 135 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); | 135 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); |
| 136 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); | 136 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); |
| 137 Node* value = NodeProperties::GetValueInput(node, 2); | 137 Node* value = NodeProperties::GetValueInput(node, 2); |
| 138 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 138 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 139 Node* effect = NodeProperties::GetEffectInput(node); | 139 Node* effect = NodeProperties::GetEffectInput(node); |
| 140 Node* control = NodeProperties::GetControlInput(node); | 140 Node* control = NodeProperties::GetControlInput(node); |
| 141 | 141 |
| 142 // Try to lookup the name on the script context table first (lexical scoping). | 142 // Try to lookup the name on the script context table first (lexical scoping). |
| 143 ScriptContextTableLookupResult result; | 143 ScriptContextTableLookupResult result; |
| 144 if (LookupInScriptContextTable(name, &result)) { | 144 if (LookupInScriptContextTable(name, &result)) { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 } | 231 } |
| 232 effect = graph()->NewNode( | 232 effect = graph()->NewNode( |
| 233 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), | 233 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), |
| 234 jsgraph()->Constant(property_cell), value, effect, control); | 234 jsgraph()->Constant(property_cell), value, effect, control); |
| 235 return Replace(node, value, effect, control); | 235 return Replace(node, value, effect, control); |
| 236 } | 236 } |
| 237 | 237 |
| 238 | 238 |
| 239 // This class encapsulates all information required to access a certain | 239 // This class encapsulates all information required to access a certain |
| 240 // object property, either on the object itself or on the prototype chain. | 240 // object property, either on the object itself or on the prototype chain. |
| 241 class JSGlobalSpecialization::PropertyAccessInfo final { | 241 class JSNativeContextSpecialization::PropertyAccessInfo final { |
| 242 public: | 242 public: |
| 243 enum Kind { kInvalid, kData, kDataConstant }; | 243 enum Kind { kInvalid, kData, kDataConstant }; |
| 244 | 244 |
| 245 static PropertyAccessInfo DataConstant(Type* receiver_type, | 245 static PropertyAccessInfo DataConstant(Type* receiver_type, |
| 246 Handle<Object> constant, | 246 Handle<Object> constant, |
| 247 MaybeHandle<JSObject> holder) { | 247 MaybeHandle<JSObject> holder) { |
| 248 return PropertyAccessInfo(holder, constant, receiver_type); | 248 return PropertyAccessInfo(holder, constant, receiver_type); |
| 249 } | 249 } |
| 250 static PropertyAccessInfo Data(Type* receiver_type, FieldIndex field_index, | 250 static PropertyAccessInfo Data(Type* receiver_type, FieldIndex field_index, |
| 251 Representation field_representation, | 251 Representation field_representation, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; | 297 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; |
| 298 return map->IsJSObjectMap() && !map->is_dictionary_map() && | 298 return map->IsJSObjectMap() && !map->is_dictionary_map() && |
| 299 !map->has_named_interceptor() && | 299 !map->has_named_interceptor() && |
| 300 // TODO(verwaest): Whitelist contexts to which we have access. | 300 // TODO(verwaest): Whitelist contexts to which we have access. |
| 301 !map->is_access_check_needed(); | 301 !map->is_access_check_needed(); |
| 302 } | 302 } |
| 303 | 303 |
| 304 } // namespace | 304 } // namespace |
| 305 | 305 |
| 306 | 306 |
| 307 bool JSGlobalSpecialization::ComputePropertyAccessInfo( | 307 bool JSNativeContextSpecialization::ComputePropertyAccessInfo( |
| 308 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { | 308 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { |
| 309 MaybeHandle<JSObject> holder; | 309 MaybeHandle<JSObject> holder; |
| 310 Type* receiver_type = Type::Class(map, graph()->zone()); | 310 Type* receiver_type = Type::Class(map, graph()->zone()); |
| 311 while (CanInlinePropertyAccess(map)) { | 311 while (CanInlinePropertyAccess(map)) { |
| 312 // Lookup the named property on the {map}. | 312 // Lookup the named property on the {map}. |
| 313 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); | 313 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); |
| 314 int const number = descriptors->SearchWithCache(*name, *map); | 314 int const number = descriptors->SearchWithCache(*name, *map); |
| 315 if (number != DescriptorArray::kNotFound) { | 315 if (number != DescriptorArray::kNotFound) { |
| 316 PropertyDetails const details = descriptors->GetDetails(number); | 316 PropertyDetails const details = descriptors->GetDetails(number); |
| 317 if (details.type() == DATA_CONSTANT) { | 317 if (details.type() == DATA_CONSTANT) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 // map into the optimized code. | 351 // map into the optimized code. |
| 352 JSObject::TryMigrateInstance(map_prototype); | 352 JSObject::TryMigrateInstance(map_prototype); |
| 353 } | 353 } |
| 354 map = handle(map_prototype->map(), isolate()); | 354 map = handle(map_prototype->map(), isolate()); |
| 355 holder = map_prototype; | 355 holder = map_prototype; |
| 356 } | 356 } |
| 357 return false; | 357 return false; |
| 358 } | 358 } |
| 359 | 359 |
| 360 | 360 |
| 361 bool JSGlobalSpecialization::ComputePropertyAccessInfos( | 361 bool JSNativeContextSpecialization::ComputePropertyAccessInfos( |
| 362 MapHandleList const& maps, Handle<Name> name, | 362 MapHandleList const& maps, Handle<Name> name, |
| 363 ZoneVector<PropertyAccessInfo>* access_infos) { | 363 ZoneVector<PropertyAccessInfo>* access_infos) { |
| 364 for (Handle<Map> map : maps) { | 364 for (Handle<Map> map : maps) { |
| 365 PropertyAccessInfo access_info; | 365 PropertyAccessInfo access_info; |
| 366 if (!ComputePropertyAccessInfo(map, name, &access_info)) return false; | 366 if (!ComputePropertyAccessInfo(map, name, &access_info)) return false; |
| 367 access_infos->push_back(access_info); | 367 access_infos->push_back(access_info); |
| 368 } | 368 } |
| 369 return true; | 369 return true; |
| 370 } | 370 } |
| 371 | 371 |
| 372 | 372 |
| 373 Reduction JSGlobalSpecialization::ReduceJSLoadNamed(Node* node) { | 373 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { |
| 374 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); | 374 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); |
| 375 LoadNamedParameters const p = LoadNamedParametersOf(node->op()); | 375 LoadNamedParameters const p = LoadNamedParametersOf(node->op()); |
| 376 Handle<Name> name = p.name(); | 376 Handle<Name> name = p.name(); |
| 377 Node* receiver = NodeProperties::GetValueInput(node, 0); | 377 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 378 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 378 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 379 Node* effect = NodeProperties::GetEffectInput(node); | 379 Node* effect = NodeProperties::GetEffectInput(node); |
| 380 Node* control = NodeProperties::GetControlInput(node); | 380 Node* control = NodeProperties::GetControlInput(node); |
| 381 | 381 |
| 382 // Not much we can do if deoptimization support is disabled. | 382 // Not much we can do if deoptimization support is disabled. |
| 383 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 383 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 | 546 |
| 547 // Remember the final state for this property access. | 547 // Remember the final state for this property access. |
| 548 values.push_back(this_value); | 548 values.push_back(this_value); |
| 549 effects.push_back(this_effect); | 549 effects.push_back(this_effect); |
| 550 controls.push_back(this_control); | 550 controls.push_back(this_control); |
| 551 } | 551 } |
| 552 | 552 |
| 553 // Collect the fallthru control as final "exit" control. | 553 // Collect the fallthru control as final "exit" control. |
| 554 exit_controls.push_back(fallthrough_control); | 554 exit_controls.push_back(fallthrough_control); |
| 555 | 555 |
| 556 // TODO(bmeurer/mtrofin): Splintering cannot currently deal with deferred | 556 // TODO(bmeurer/mtrofin): Splintering cannot currently deal with deferred |
| 557 // blocks that contain only a single non-deoptimize instruction (i.e. a | 557 // blocks that contain only a single non-deoptimize instruction (i.e. a |
| 558 // jump). Generating a single Merge here, which joins all the deoptimizing | 558 // jump). Generating a single Merge here, which joins all the deoptimizing |
| 559 // controls would generate a lot of these basic blocks, however. So this | 559 // controls would generate a lot of these basic blocks, however. So this |
| 560 // is disabled for now until splintering is fixed. | 560 // is disabled for now until splintering is fixed. |
| 561 #if 0 | 561 #if 0 |
| 562 // Generate the single "exit" point, where we get if either all map/instance | 562 // Generate the single "exit" point, where we get if either all map/instance |
| 563 // type checks failed, or one of the assumptions inside one of the cases | 563 // type checks failed, or one of the assumptions inside one of the cases |
| 564 // failes (i.e. failing prototype chain check). | 564 // failes (i.e. failing prototype chain check). |
| 565 // TODO(bmeurer): Consider falling back to IC here if deoptimization is | 565 // TODO(bmeurer): Consider falling back to IC here if deoptimization is |
| 566 // disabled. | 566 // disabled. |
| 567 int const exit_control_count = static_cast<int>(exit_controls.size()); | 567 int const exit_control_count = static_cast<int>(exit_controls.size()); |
| 568 Node* exit_control = | 568 Node* exit_control = |
| 569 (exit_control_count == 1) | 569 (exit_control_count == 1) |
| 570 ? exit_controls.front() | 570 ? exit_controls.front() |
| (...skipping 26 matching lines...) Expand all Loading... |
| 597 value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count), | 597 value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count), |
| 598 control_count + 1, &values.front()); | 598 control_count + 1, &values.front()); |
| 599 effects.push_back(control); | 599 effects.push_back(control); |
| 600 effect = graph()->NewNode(common()->EffectPhi(control_count), | 600 effect = graph()->NewNode(common()->EffectPhi(control_count), |
| 601 control_count + 1, &effects.front()); | 601 control_count + 1, &effects.front()); |
| 602 } | 602 } |
| 603 return Replace(node, value, effect, control); | 603 return Replace(node, value, effect, control); |
| 604 } | 604 } |
| 605 | 605 |
| 606 | 606 |
| 607 Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) { | 607 Reduction JSNativeContextSpecialization::Replace(Node* node, |
| 608 Handle<Object> value) { |
| 608 return Replace(node, jsgraph()->Constant(value)); | 609 return Replace(node, jsgraph()->Constant(value)); |
| 609 } | 610 } |
| 610 | 611 |
| 611 | 612 |
| 612 bool JSGlobalSpecialization::LookupInScriptContextTable( | 613 bool JSNativeContextSpecialization::LookupInScriptContextTable( |
| 613 Handle<Name> name, ScriptContextTableLookupResult* result) { | 614 Handle<Name> name, ScriptContextTableLookupResult* result) { |
| 614 if (!name->IsString()) return false; | 615 if (!name->IsString()) return false; |
| 615 Handle<ScriptContextTable> script_context_table( | 616 Handle<ScriptContextTable> script_context_table( |
| 616 global_object()->native_context()->script_context_table()); | 617 global_object()->native_context()->script_context_table()); |
| 617 ScriptContextTable::LookupResult lookup_result; | 618 ScriptContextTable::LookupResult lookup_result; |
| 618 if (!ScriptContextTable::Lookup(script_context_table, | 619 if (!ScriptContextTable::Lookup(script_context_table, |
| 619 Handle<String>::cast(name), &lookup_result)) { | 620 Handle<String>::cast(name), &lookup_result)) { |
| 620 return false; | 621 return false; |
| 621 } | 622 } |
| 622 Handle<Context> script_context = ScriptContextTable::GetContext( | 623 Handle<Context> script_context = ScriptContextTable::GetContext( |
| 623 script_context_table, lookup_result.context_index); | 624 script_context_table, lookup_result.context_index); |
| 624 if (script_context->is_the_hole(lookup_result.slot_index)) return false; | 625 if (script_context->is_the_hole(lookup_result.slot_index)) return false; |
| 625 result->context = script_context; | 626 result->context = script_context; |
| 626 result->immutable = IsImmutableVariableMode(lookup_result.mode); | 627 result->immutable = IsImmutableVariableMode(lookup_result.mode); |
| 627 result->index = lookup_result.slot_index; | 628 result->index = lookup_result.slot_index; |
| 628 return true; | 629 return true; |
| 629 } | 630 } |
| 630 | 631 |
| 631 | 632 |
| 632 Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); } | 633 Graph* JSNativeContextSpecialization::graph() const { |
| 634 return jsgraph()->graph(); |
| 635 } |
| 633 | 636 |
| 634 | 637 |
| 635 Isolate* JSGlobalSpecialization::isolate() const { | 638 Isolate* JSNativeContextSpecialization::isolate() const { |
| 636 return jsgraph()->isolate(); | 639 return jsgraph()->isolate(); |
| 637 } | 640 } |
| 638 | 641 |
| 639 | 642 |
| 640 MachineOperatorBuilder* JSGlobalSpecialization::machine() const { | 643 MachineOperatorBuilder* JSNativeContextSpecialization::machine() const { |
| 641 return jsgraph()->machine(); | 644 return jsgraph()->machine(); |
| 642 } | 645 } |
| 643 | 646 |
| 644 | 647 |
| 645 CommonOperatorBuilder* JSGlobalSpecialization::common() const { | 648 CommonOperatorBuilder* JSNativeContextSpecialization::common() const { |
| 646 return jsgraph()->common(); | 649 return jsgraph()->common(); |
| 647 } | 650 } |
| 648 | 651 |
| 649 | 652 |
| 650 JSOperatorBuilder* JSGlobalSpecialization::javascript() const { | 653 JSOperatorBuilder* JSNativeContextSpecialization::javascript() const { |
| 651 return jsgraph()->javascript(); | 654 return jsgraph()->javascript(); |
| 652 } | 655 } |
| 653 | 656 |
| 654 | 657 |
| 655 SimplifiedOperatorBuilder* JSGlobalSpecialization::simplified() const { | 658 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 656 return jsgraph()->simplified(); | 659 return jsgraph()->simplified(); |
| 657 } | 660 } |
| 658 | 661 |
| 659 } // namespace compiler | 662 } // namespace compiler |
| 660 } // namespace internal | 663 } // namespace internal |
| 661 } // namespace v8 | 664 } // namespace v8 |
| OLD | NEW |