| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "hydrogen-bch.h" | 37 #include "hydrogen-bch.h" |
| 38 #include "hydrogen-canonicalize.h" | 38 #include "hydrogen-canonicalize.h" |
| 39 #include "hydrogen-dce.h" | 39 #include "hydrogen-dce.h" |
| 40 #include "hydrogen-dehoist.h" | 40 #include "hydrogen-dehoist.h" |
| 41 #include "hydrogen-deoptimizing-mark.h" | 41 #include "hydrogen-deoptimizing-mark.h" |
| 42 #include "hydrogen-environment-liveness.h" | 42 #include "hydrogen-environment-liveness.h" |
| 43 #include "hydrogen-escape-analysis.h" | 43 #include "hydrogen-escape-analysis.h" |
| 44 #include "hydrogen-infer-representation.h" | 44 #include "hydrogen-infer-representation.h" |
| 45 #include "hydrogen-infer-types.h" | 45 #include "hydrogen-infer-types.h" |
| 46 #include "hydrogen-gvn.h" | 46 #include "hydrogen-gvn.h" |
| 47 #include "hydrogen-mark-deoptimize.h" | |
| 48 #include "hydrogen-minus-zero.h" | 47 #include "hydrogen-minus-zero.h" |
| 49 #include "hydrogen-osr.h" | 48 #include "hydrogen-osr.h" |
| 50 #include "hydrogen-range-analysis.h" | 49 #include "hydrogen-range-analysis.h" |
| 51 #include "hydrogen-redundant-phi.h" | 50 #include "hydrogen-redundant-phi.h" |
| 52 #include "hydrogen-removable-simulates.h" | 51 #include "hydrogen-removable-simulates.h" |
| 53 #include "hydrogen-representation-changes.h" | 52 #include "hydrogen-representation-changes.h" |
| 54 #include "hydrogen-sce.h" | 53 #include "hydrogen-sce.h" |
| 55 #include "hydrogen-uint32-analysis.h" | 54 #include "hydrogen-uint32-analysis.h" |
| 56 #include "lithium-allocator.h" | 55 #include "lithium-allocator.h" |
| 57 #include "parser.h" | 56 #include "parser.h" |
| (...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 979 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 981 ASSERT(current_block() != NULL); | 980 ASSERT(current_block() != NULL); |
| 982 current_block()->AddInstruction(instr); | 981 current_block()->AddInstruction(instr); |
| 983 if (no_side_effects_scope_count_ > 0) { | 982 if (no_side_effects_scope_count_ > 0) { |
| 984 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 983 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
| 985 } | 984 } |
| 986 return instr; | 985 return instr; |
| 987 } | 986 } |
| 988 | 987 |
| 989 | 988 |
| 990 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, | |
| 991 HValue* context) { | |
| 992 if (FLAG_native_code_counters && counter->Enabled()) { | |
| 993 HValue* reference = Add<HConstant>(ExternalReference(counter)); | |
| 994 HValue* old_value = AddLoad(reference, HObjectAccess::ForCounter(), NULL); | |
| 995 HValue* new_value = AddInstruction( | |
| 996 HAdd::New(zone(), context, old_value, graph()->GetConstant1())); | |
| 997 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | |
| 998 AddStore(reference, HObjectAccess::ForCounter(), new_value); | |
| 999 } | |
| 1000 } | |
| 1001 | |
| 1002 | |
| 1003 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 989 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
| 1004 HBasicBlock* b = graph()->CreateBasicBlock(); | 990 HBasicBlock* b = graph()->CreateBasicBlock(); |
| 1005 b->SetInitialEnvironment(env); | 991 b->SetInitialEnvironment(env); |
| 1006 return b; | 992 return b; |
| 1007 } | 993 } |
| 1008 | 994 |
| 1009 | 995 |
| 1010 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 996 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
| 1011 HBasicBlock* header = graph()->CreateBasicBlock(); | 997 HBasicBlock* header = graph()->CreateBasicBlock(); |
| 1012 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 998 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 HValue* current_capacity = AddLoadFixedArrayLength(elements); | 1071 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
| 1086 | 1072 |
| 1087 IfBuilder capacity_checker(this); | 1073 IfBuilder capacity_checker(this); |
| 1088 | 1074 |
| 1089 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, | 1075 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, |
| 1090 Token::GTE); | 1076 Token::GTE); |
| 1091 capacity_checker.Then(); | 1077 capacity_checker.Then(); |
| 1092 | 1078 |
| 1093 HValue* context = environment()->LookupContext(); | 1079 HValue* context = environment()->LookupContext(); |
| 1094 | 1080 |
| 1095 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); | 1081 HValue* new_capacity = BuildNewElementsCapacity(context, key); |
| 1096 HValue* max_capacity = AddInstruction( | |
| 1097 HAdd::New(zone, context, current_capacity, max_gap)); | |
| 1098 IfBuilder key_checker(this); | |
| 1099 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); | |
| 1100 key_checker.Then(); | |
| 1101 key_checker.ElseDeopt(); | |
| 1102 key_checker.End(); | |
| 1103 | 1082 |
| 1104 HValue* new_capacity = BuildNewElementsCapacity(context, key); | |
| 1105 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1083 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1106 kind, kind, length, | 1084 kind, kind, length, |
| 1107 new_capacity); | 1085 new_capacity); |
| 1108 | 1086 |
| 1109 environment()->Push(new_elements); | 1087 environment()->Push(new_elements); |
| 1110 capacity_checker.Else(); | 1088 capacity_checker.Else(); |
| 1111 | 1089 |
| 1112 environment()->Push(elements); | 1090 environment()->Push(elements); |
| 1113 capacity_checker.End(); | 1091 capacity_checker.End(); |
| 1114 | 1092 |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 | 1330 |
| 1353 AddStoreMapConstant(elements, map); | 1331 AddStoreMapConstant(elements, map); |
| 1354 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity); | 1332 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity); |
| 1355 } | 1333 } |
| 1356 | 1334 |
| 1357 | 1335 |
| 1358 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 1336 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
| 1359 HValue* context, | 1337 HValue* context, |
| 1360 ElementsKind kind, | 1338 ElementsKind kind, |
| 1361 HValue* capacity) { | 1339 HValue* capacity) { |
| 1362 // The HForceRepresentation is to prevent possible deopt on int-smi | |
| 1363 // conversion after allocation but before the new object fields are set. | |
| 1364 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); | |
| 1365 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1340 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
| 1366 BuildInitializeElementsHeader(new_elements, kind, capacity); | 1341 BuildInitializeElementsHeader(new_elements, kind, capacity); |
| 1367 return new_elements; | 1342 return new_elements; |
| 1368 } | 1343 } |
| 1369 | 1344 |
| 1370 | 1345 |
| 1371 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1346 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
| 1372 HValue* array_map, | 1347 HValue* array_map, |
| 1373 AllocationSiteMode mode, | 1348 AllocationSiteMode mode, |
| 1374 ElementsKind elements_kind, | 1349 ElementsKind elements_kind, |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 return AddLoad(object, HObjectAccess::ForFixedArrayLength()); | 1467 return AddLoad(object, HObjectAccess::ForFixedArrayLength()); |
| 1493 } | 1468 } |
| 1494 | 1469 |
| 1495 | 1470 |
| 1496 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1471 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
| 1497 HValue* old_capacity) { | 1472 HValue* old_capacity) { |
| 1498 Zone* zone = this->zone(); | 1473 Zone* zone = this->zone(); |
| 1499 HValue* half_old_capacity = | 1474 HValue* half_old_capacity = |
| 1500 AddInstruction(HShr::New(zone, context, old_capacity, | 1475 AddInstruction(HShr::New(zone, context, old_capacity, |
| 1501 graph_->GetConstant1())); | 1476 graph_->GetConstant1())); |
| 1477 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
| 1502 | 1478 |
| 1503 HValue* new_capacity = AddInstruction( | 1479 HValue* new_capacity = AddInstruction( |
| 1504 HAdd::New(zone, context, half_old_capacity, old_capacity)); | 1480 HAdd::New(zone, context, half_old_capacity, old_capacity)); |
| 1505 new_capacity->ClearFlag(HValue::kCanOverflow); | 1481 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1506 | 1482 |
| 1507 HValue* min_growth = Add<HConstant>(16); | 1483 HValue* min_growth = Add<HConstant>(16); |
| 1508 | 1484 |
| 1509 new_capacity = AddInstruction( | 1485 new_capacity = AddInstruction( |
| 1510 HAdd::New(zone, context, new_capacity, min_growth)); | 1486 HAdd::New(zone, context, new_capacity, min_growth)); |
| 1511 new_capacity->ClearFlag(HValue::kCanOverflow); | 1487 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1512 | 1488 |
| 1513 return new_capacity; | 1489 return new_capacity; |
| 1514 } | 1490 } |
| 1515 | 1491 |
| 1516 | 1492 |
| 1517 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { | 1493 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { |
| 1518 Heap* heap = isolate()->heap(); | 1494 Heap* heap = isolate()->heap(); |
| 1519 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize | 1495 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize |
| 1520 : kPointerSize; | 1496 : kPointerSize; |
| 1521 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; | 1497 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; |
| 1522 max_size -= JSArray::kSize / element_size; | 1498 max_size -= JSArray::kSize / element_size; |
| 1523 HConstant* max_size_constant = Add<HConstant>(max_size); | 1499 HConstant* max_size_constant = Add<HConstant>(max_size); |
| 1500 // Since we're forcing Integer32 representation for this HBoundsCheck, |
| 1501 // there's no need to Smi-check the index. |
| 1524 Add<HBoundsCheck>(length, max_size_constant); | 1502 Add<HBoundsCheck>(length, max_size_constant); |
| 1525 } | 1503 } |
| 1526 | 1504 |
| 1527 | 1505 |
| 1528 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1506 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
| 1529 HValue* elements, | 1507 HValue* elements, |
| 1530 ElementsKind kind, | 1508 ElementsKind kind, |
| 1531 ElementsKind new_kind, | 1509 ElementsKind new_kind, |
| 1532 HValue* length, | 1510 HValue* length, |
| 1533 HValue* new_capacity) { | 1511 HValue* new_capacity) { |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1942 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); | 1920 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); |
| 1943 } | 1921 } |
| 1944 | 1922 |
| 1945 | 1923 |
| 1946 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | 1924 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
| 1947 HValue* capacity, | 1925 HValue* capacity, |
| 1948 HValue* length_field, | 1926 HValue* length_field, |
| 1949 bool fill_with_hole) { | 1927 bool fill_with_hole) { |
| 1950 HValue* context = builder()->environment()->LookupContext(); | 1928 HValue* context = builder()->environment()->LookupContext(); |
| 1951 | 1929 |
| 1952 // These HForceRepresentations are because we store these as fields in the | |
| 1953 // objects we construct, and an int32-to-smi HChange could deopt. Accept | |
| 1954 // the deopt possibility now, before allocation occurs. | |
| 1955 capacity = builder()->Add<HForceRepresentation>(capacity, | |
| 1956 Representation::Smi()); | |
| 1957 length_field = builder()->Add<HForceRepresentation>(length_field, | |
| 1958 Representation::Smi()); | |
| 1959 | |
| 1960 // Allocate (dealing with failure appropriately) | 1930 // Allocate (dealing with failure appropriately) |
| 1961 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); | 1931 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); |
| 1962 HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes, | 1932 HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes, |
| 1963 HType::JSArray(), flags); | 1933 HType::JSArray(), flags); |
| 1964 | 1934 |
| 1965 // Fill in the fields: map, properties, length | 1935 // Fill in the fields: map, properties, length |
| 1966 HValue* map; | 1936 HValue* map; |
| 1967 if (allocation_site_payload_ == NULL) { | 1937 if (allocation_site_payload_ == NULL) { |
| 1968 map = EmitInternalMapCode(); | 1938 map = EmitInternalMapCode(); |
| 1969 } else { | 1939 } else { |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2508 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone()); | 2478 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone()); |
| 2509 for (int i = 0; i < block_count; ++i) { | 2479 for (int i = 0; i < block_count; ++i) { |
| 2510 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { | 2480 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { |
| 2511 HPhi* phi = blocks_[i]->phis()->at(j); | 2481 HPhi* phi = blocks_[i]->phis()->at(j); |
| 2512 phi_list_->Add(phi, zone()); | 2482 phi_list_->Add(phi, zone()); |
| 2513 } | 2483 } |
| 2514 } | 2484 } |
| 2515 } | 2485 } |
| 2516 | 2486 |
| 2517 | 2487 |
| 2488 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { |
| 2489 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return; |
| 2490 phi->ClearFlag(HValue::kAllowUndefinedAsNaN); |
| 2491 for (int i = 0; i < phi->OperandCount(); ++i) { |
| 2492 HValue* input = phi->OperandAt(i); |
| 2493 if (input->IsPhi()) { |
| 2494 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); |
| 2495 } |
| 2496 } |
| 2497 } |
| 2498 |
| 2499 |
| 2500 void HGraph::MarkDeoptimizeOnUndefined() { |
| 2501 HPhase phase("H_MarkDeoptimizeOnUndefined", this); |
| 2502 // Compute DeoptimizeOnUndefined flag for phis. Any phi that can reach a use |
| 2503 // with DeoptimizeOnUndefined set must have DeoptimizeOnUndefined set. |
| 2504 // Currently only HCompareNumericAndBranch, with double input representation, |
| 2505 // has this flag set. The flag is used by HChange tagged->double, which must |
| 2506 // deoptimize if one of its uses has this flag set. |
| 2507 for (int i = 0; i < phi_list()->length(); i++) { |
| 2508 HPhi* phi = phi_list()->at(i); |
| 2509 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
| 2510 HValue* use_value = it.value(); |
| 2511 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { |
| 2512 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); |
| 2513 break; |
| 2514 } |
| 2515 } |
| 2516 } |
| 2517 } |
| 2518 |
| 2519 |
| 2518 // Implementation of utility class to encapsulate the translation state for | 2520 // Implementation of utility class to encapsulate the translation state for |
| 2519 // a (possibly inlined) function. | 2521 // a (possibly inlined) function. |
| 2520 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, | 2522 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, |
| 2521 CompilationInfo* info, | 2523 CompilationInfo* info, |
| 2522 InliningKind inlining_kind) | 2524 InliningKind inlining_kind) |
| 2523 : owner_(owner), | 2525 : owner_(owner), |
| 2524 compilation_info_(info), | 2526 compilation_info_(info), |
| 2525 call_context_(NULL), | 2527 call_context_(NULL), |
| 2526 inlining_kind_(inlining_kind), | 2528 inlining_kind_(inlining_kind), |
| 2527 function_return_(NULL), | 2529 function_return_(NULL), |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2980 | 2982 |
| 2981 if (has_osr()) osr()->FinishOsrValues(); | 2983 if (has_osr()) osr()->FinishOsrValues(); |
| 2982 | 2984 |
| 2983 Run<HInferRepresentationPhase>(); | 2985 Run<HInferRepresentationPhase>(); |
| 2984 | 2986 |
| 2985 // Remove HSimulate instructions that have turned out not to be needed | 2987 // Remove HSimulate instructions that have turned out not to be needed |
| 2986 // after all by folding them into the following HSimulate. | 2988 // after all by folding them into the following HSimulate. |
| 2987 // This must happen after inferring representations. | 2989 // This must happen after inferring representations. |
| 2988 Run<HMergeRemovableSimulatesPhase>(); | 2990 Run<HMergeRemovableSimulatesPhase>(); |
| 2989 | 2991 |
| 2990 Run<HMarkDeoptimizeOnUndefinedPhase>(); | 2992 MarkDeoptimizeOnUndefined(); |
| 2991 Run<HRepresentationChangesPhase>(); | 2993 Run<HRepresentationChangesPhase>(); |
| 2992 | 2994 |
| 2993 Run<HInferTypesPhase>(); | 2995 Run<HInferTypesPhase>(); |
| 2994 | 2996 |
| 2995 // Must be performed before canonicalization to ensure that Canonicalize | 2997 // Must be performed before canonicalization to ensure that Canonicalize |
| 2996 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 2998 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
| 2997 // zero. | 2999 // zero. |
| 2998 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); | 3000 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); |
| 2999 | 3001 |
| 3000 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); | 3002 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); |
| (...skipping 6909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9910 if (ShouldProduceTraceOutput()) { | 9912 if (ShouldProduceTraceOutput()) { |
| 9911 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9913 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9912 } | 9914 } |
| 9913 | 9915 |
| 9914 #ifdef DEBUG | 9916 #ifdef DEBUG |
| 9915 graph_->Verify(false); // No full verify. | 9917 graph_->Verify(false); // No full verify. |
| 9916 #endif | 9918 #endif |
| 9917 } | 9919 } |
| 9918 | 9920 |
| 9919 } } // namespace v8::internal | 9921 } } // namespace v8::internal |
| OLD | NEW |