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 |