OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cpu.h" | 8 #include "vm/cpu.h" |
9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
10 #include "vm/flow_graph_allocator.h" | 10 #include "vm/flow_graph_allocator.h" |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 if (curr == this) return true; | 782 if (curr == this) return true; |
783 } | 783 } |
784 | 784 |
785 return false; | 785 return false; |
786 } | 786 } |
787 | 787 |
788 return dom_block->Dominates(block); | 788 return dom_block->Dominates(block); |
789 } | 789 } |
790 | 790 |
791 | 791 |
| 792 bool Instruction::HasUnmatchedInputRepresentations() const { |
| 793 for (intptr_t i = 0; i < InputCount(); i++) { |
| 794 Definition* input = InputAt(i)->definition(); |
| 795 if (RequiredInputRepresentation(i) != input->representation()) { |
| 796 return true; |
| 797 } |
| 798 } |
| 799 |
| 800 return false; |
| 801 } |
| 802 |
| 803 |
792 void Definition::ReplaceWith(Definition* other, | 804 void Definition::ReplaceWith(Definition* other, |
793 ForwardInstructionIterator* iterator) { | 805 ForwardInstructionIterator* iterator) { |
794 // Record other's input uses. | 806 // Record other's input uses. |
795 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) { | 807 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) { |
796 Value* input = other->InputAt(i); | 808 Value* input = other->InputAt(i); |
797 input->definition()->AddInputUse(input); | 809 input->definition()->AddInputUse(input); |
798 } | 810 } |
799 // Take other's environment from this definition. | 811 // Take other's environment from this definition. |
800 ASSERT(other->env() == NULL); | 812 ASSERT(other->env() == NULL); |
801 other->SetEnvironment(env()); | 813 other->SetEnvironment(env()); |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 switch (op_kind()) { | 1210 switch (op_kind()) { |
1199 case Token::kBIT_AND: | 1211 case Token::kBIT_AND: |
1200 case Token::kBIT_OR: | 1212 case Token::kBIT_OR: |
1201 case Token::kBIT_XOR: | 1213 case Token::kBIT_XOR: |
1202 return false; | 1214 return false; |
1203 | 1215 |
1204 case Token::kSHR: | 1216 case Token::kSHR: |
1205 return false; | 1217 return false; |
1206 | 1218 |
1207 case Token::kSHL: | 1219 case Token::kSHL: |
1208 return true; | 1220 return can_overflow() || |
| 1221 !RangeUtils::IsPositive(right()->definition()->range()); |
1209 | 1222 |
1210 case Token::kMOD: { | 1223 case Token::kMOD: { |
1211 UNREACHABLE(); | 1224 UNREACHABLE(); |
1212 } | 1225 } |
1213 | 1226 |
1214 default: | 1227 default: |
1215 return can_overflow(); | 1228 return can_overflow(); |
1216 } | 1229 } |
1217 } | 1230 } |
1218 | 1231 |
1219 | 1232 |
1220 bool BinarySmiOpInstr::CanDeoptimize() const { | 1233 bool BinarySmiOpInstr::CanDeoptimize() const { |
1221 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) { | 1234 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) { |
1222 // If Smi's are bigger than 32-bits, then the instruction could deoptimize | 1235 // If Smi's are bigger than 32-bits, then the instruction could deoptimize |
1223 // if the result is too big. | 1236 // if the result is too big. |
1224 return true; | 1237 return true; |
1225 } | 1238 } |
1226 switch (op_kind()) { | 1239 switch (op_kind()) { |
1227 case Token::kBIT_AND: | 1240 case Token::kBIT_AND: |
1228 case Token::kBIT_OR: | 1241 case Token::kBIT_OR: |
1229 case Token::kBIT_XOR: | 1242 case Token::kBIT_XOR: |
1230 return false; | 1243 return false; |
1231 case Token::kSHR: { | 1244 |
1232 // Can't deopt if shift-count is known positive. | 1245 case Token::kSHR: |
1233 Range* right_range = this->right()->definition()->range(); | 1246 return !RangeUtils::IsPositive(right()->definition()->range()); |
1234 return (right_range == NULL) || !right_range->IsPositive(); | 1247 |
1235 } | 1248 case Token::kSHL: |
1236 case Token::kSHL: { | 1249 return can_overflow() || |
1237 Range* right_range = this->right()->definition()->range(); | 1250 !RangeUtils::IsPositive(right()->definition()->range()); |
1238 if ((right_range != NULL) && !can_overflow()) { | 1251 |
1239 // Can deoptimize if right can be negative. | |
1240 return !right_range->IsPositive(); | |
1241 } | |
1242 return true; | |
1243 } | |
1244 case Token::kMOD: { | 1252 case Token::kMOD: { |
1245 Range* right_range = this->right()->definition()->range(); | 1253 Range* right_range = this->right()->definition()->range(); |
1246 return (right_range == NULL) || right_range->Overlaps(0, 0); | 1254 return (right_range == NULL) || right_range->Overlaps(0, 0); |
1247 } | 1255 } |
1248 default: | 1256 default: |
1249 return can_overflow(); | 1257 return can_overflow(); |
1250 } | 1258 } |
1251 } | 1259 } |
1252 | 1260 |
1253 | 1261 |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1987 } | 1995 } |
1988 | 1996 |
1989 return replacement; | 1997 return replacement; |
1990 } | 1998 } |
1991 | 1999 |
1992 return this; | 2000 return this; |
1993 } | 2001 } |
1994 | 2002 |
1995 | 2003 |
1996 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) { | 2004 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) { |
1997 if (!HasUses()) return NULL; | 2005 if (!HasUses() && !CanDeoptimize()) return NULL; |
1998 | 2006 |
1999 // Fold away Unbox<rep>(Box<rep>(v)). | 2007 // Fold away Unbox<rep>(Box<rep>(v)). |
2000 BoxInstr* box_defn = value()->definition()->AsBox(); | 2008 BoxInstr* box_defn = value()->definition()->AsBox(); |
2001 if ((box_defn != NULL) && | 2009 if ((box_defn != NULL) && |
2002 (box_defn->from_representation() == representation())) { | 2010 (box_defn->from_representation() == representation())) { |
2003 return box_defn->value()->definition(); | 2011 return box_defn->value()->definition(); |
2004 } | 2012 } |
2005 | 2013 |
2006 if ((representation() == kUnboxedDouble) && value()->BindsToConstant()) { | 2014 if ((representation() == kUnboxedDouble) && value()->BindsToConstant()) { |
2007 UnboxedConstantInstr* uc = NULL; | 2015 UnboxedConstantInstr* uc = NULL; |
(...skipping 11 matching lines...) Expand all Loading... |
2019 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); | 2027 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); |
2020 return uc; | 2028 return uc; |
2021 } | 2029 } |
2022 } | 2030 } |
2023 | 2031 |
2024 return this; | 2032 return this; |
2025 } | 2033 } |
2026 | 2034 |
2027 | 2035 |
2028 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { | 2036 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { |
2029 if (!HasUses()) return NULL; | 2037 if (!HasUses() && !CanDeoptimize()) return NULL; |
2030 | 2038 |
2031 // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)). | 2039 // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)). |
2032 BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger(); | 2040 BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger(); |
2033 if (box_defn != NULL) { | 2041 if (box_defn != NULL) { |
2034 if (box_defn->value()->definition()->representation() == representation()) { | 2042 if (box_defn->value()->definition()->representation() == representation()) { |
2035 return box_defn->value()->definition(); | 2043 return box_defn->value()->definition(); |
2036 } else { | 2044 } else { |
2037 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( | 2045 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( |
2038 box_defn->value()->definition()->representation(), | 2046 box_defn->value()->definition()->representation(), |
2039 representation(), | 2047 representation(), |
2040 box_defn->value()->CopyWithType(), | 2048 box_defn->value()->CopyWithType(), |
2041 (representation() == kUnboxedInt32) ? | 2049 (representation() == kUnboxedInt32) ? |
2042 GetDeoptId() : Isolate::kNoDeoptId); | 2050 GetDeoptId() : Isolate::kNoDeoptId); |
2043 if ((representation() == kUnboxedInt32) && is_truncating()) { | 2051 if ((representation() == kUnboxedInt32) && !CanDeoptimize()) { |
2044 converter->mark_truncating(); | 2052 converter->mark_truncating(); |
2045 } | 2053 } |
2046 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); | 2054 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); |
2047 return converter; | 2055 return converter; |
2048 } | 2056 } |
2049 } | 2057 } |
2050 | 2058 |
2051 return this; | 2059 return this; |
2052 } | 2060 } |
2053 | 2061 |
(...skipping 10 matching lines...) Expand all Loading... |
2064 // Check that constant fits into 32-bit integer. | 2072 // Check that constant fits into 32-bit integer. |
2065 const int64_t value = | 2073 const int64_t value = |
2066 static_cast<int64_t>(Smi::Cast(c->value()).Value()); | 2074 static_cast<int64_t>(Smi::Cast(c->value()).Value()); |
2067 if (!Utils::IsInt(32, value)) { | 2075 if (!Utils::IsInt(32, value)) { |
2068 return this; | 2076 return this; |
2069 } | 2077 } |
2070 } | 2078 } |
2071 | 2079 |
2072 UnboxedConstantInstr* uc = | 2080 UnboxedConstantInstr* uc = |
2073 new UnboxedConstantInstr(c->value(), kUnboxedInt32); | 2081 new UnboxedConstantInstr(c->value(), kUnboxedInt32); |
| 2082 if (c->range() != NULL) { |
| 2083 uc->set_range(*c->range()); |
| 2084 } |
2074 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); | 2085 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); |
2075 return uc; | 2086 return uc; |
2076 } | 2087 } |
2077 | 2088 |
2078 return this; | 2089 return this; |
2079 } | 2090 } |
2080 | 2091 |
2081 | 2092 |
2082 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { | 2093 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { |
2083 if (!HasUses()) return NULL; | 2094 if (!HasUses()) return NULL; |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2243 Isolate* isolate = flow_graph->isolate(); | 2254 Isolate* isolate = flow_graph->isolate(); |
2244 // Only handle strict-compares. | 2255 // Only handle strict-compares. |
2245 if (comparison()->IsStrictCompare()) { | 2256 if (comparison()->IsStrictCompare()) { |
2246 bool negated = false; | 2257 bool negated = false; |
2247 Definition* replacement = | 2258 Definition* replacement = |
2248 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated); | 2259 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated); |
2249 if (replacement == comparison()) { | 2260 if (replacement == comparison()) { |
2250 return this; | 2261 return this; |
2251 } | 2262 } |
2252 ComparisonInstr* comp = replacement->AsComparison(); | 2263 ComparisonInstr* comp = replacement->AsComparison(); |
2253 if ((comp == NULL) || comp->CanDeoptimize()) { | 2264 if ((comp == NULL) || |
| 2265 comp->CanDeoptimize() || |
| 2266 comp->HasUnmatchedInputRepresentations()) { |
2254 return this; | 2267 return this; |
2255 } | 2268 } |
2256 | 2269 |
2257 // Assert that the comparison is not serving as a pending deoptimization | |
2258 // target for conversions. | |
2259 for (intptr_t i = 0; i < comp->InputCount(); i++) { | |
2260 if (comp->RequiredInputRepresentation(i) != | |
2261 comp->InputAt(i)->definition()->representation()) { | |
2262 return this; | |
2263 } | |
2264 } | |
2265 | |
2266 // Replace the comparison if the replacement is used at this branch, | 2270 // Replace the comparison if the replacement is used at this branch, |
2267 // and has exactly one use. | 2271 // and has exactly one use. |
2268 Value* use = comp->input_use_list(); | 2272 Value* use = comp->input_use_list(); |
2269 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { | 2273 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { |
2270 if (negated) { | 2274 if (negated) { |
2271 comp->NegateComparison(); | 2275 comp->NegateComparison(); |
2272 } | 2276 } |
2273 RemoveEnvironment(); | 2277 RemoveEnvironment(); |
2274 flow_graph->CopyDeoptTarget(this, comp); | 2278 flow_graph->CopyDeoptTarget(this, comp); |
2275 // Unlink environment from the comparison since it is copied to the | 2279 // Unlink environment from the comparison since it is copied to the |
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3365 case Token::kTRUNCDIV: return 0; | 3369 case Token::kTRUNCDIV: return 0; |
3366 case Token::kMOD: return 1; | 3370 case Token::kMOD: return 1; |
3367 default: UNIMPLEMENTED(); return -1; | 3371 default: UNIMPLEMENTED(); return -1; |
3368 } | 3372 } |
3369 } | 3373 } |
3370 | 3374 |
3371 | 3375 |
3372 #undef __ | 3376 #undef __ |
3373 | 3377 |
3374 } // namespace dart | 3378 } // namespace dart |
OLD | NEW |