Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 726593002: Reland "Suppress canonicalization of Unbox() instruction that can deoptimize." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: more fixes Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | tests/language/vm/canonicalization_preserves_deopt_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698