| 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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 constant_address_(0) { | 383 constant_address_(0) { |
| 384 if (representation_ == kUnboxedDouble) { | 384 if (representation_ == kUnboxedDouble) { |
| 385 ASSERT(value.IsDouble()); | 385 ASSERT(value.IsDouble()); |
| 386 constant_address_ = | 386 constant_address_ = |
| 387 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); | 387 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); |
| 388 } | 388 } |
| 389 } | 389 } |
| 390 | 390 |
| 391 | 391 |
| 392 bool Value::BindsTo32BitMaskConstant() const { | 392 bool Value::BindsTo32BitMaskConstant() const { |
| 393 if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) { | 393 if (!definition()->IsUnboxInt64() || !definition()->IsUnboxUint32()) { |
| 394 return false; | 394 return false; |
| 395 } | 395 } |
| 396 // Two cases to consider: UnboxInteger and UnboxUint32. | 396 // Two cases to consider: UnboxInt64 and UnboxUint32. |
| 397 if (definition()->IsUnboxInteger()) { | 397 if (definition()->IsUnboxInt64()) { |
| 398 UnboxIntegerInstr* instr = definition()->AsUnboxInteger(); | 398 UnboxInt64Instr* instr = definition()->AsUnboxInt64(); |
| 399 if (!instr->value()->BindsToConstant()) { | 399 if (!instr->value()->BindsToConstant()) { |
| 400 return false; | 400 return false; |
| 401 } | 401 } |
| 402 const Object& obj = instr->value()->BoundConstant(); | 402 const Object& obj = instr->value()->BoundConstant(); |
| 403 if (!obj.IsMint()) { | 403 if (!obj.IsMint()) { |
| 404 return false; | 404 return false; |
| 405 } | 405 } |
| 406 Mint& mint = Mint::Handle(); | 406 Mint& mint = Mint::Handle(); |
| 407 mint ^= obj.raw(); | 407 mint ^= obj.raw(); |
| 408 return mint.value() == kMaxUint32; | 408 return mint.value() == kMaxUint32; |
| (...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 if (!right()->definition()->IsConstant()) return false; | 1255 if (!right()->definition()->IsConstant()) return false; |
| 1256 const Object& constant = right()->definition()->AsConstant()->value(); | 1256 const Object& constant = right()->definition()->AsConstant()->value(); |
| 1257 if (!constant.IsSmi()) return false; | 1257 if (!constant.IsSmi()) return false; |
| 1258 const intptr_t int_value = Smi::Cast(constant).Value(); | 1258 const intptr_t int_value = Smi::Cast(constant).Value(); |
| 1259 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); | 1259 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); |
| 1260 } | 1260 } |
| 1261 | 1261 |
| 1262 | 1262 |
| 1263 static bool ToIntegerConstant(Value* value, int64_t* result) { | 1263 static bool ToIntegerConstant(Value* value, int64_t* result) { |
| 1264 if (!value->BindsToConstant()) { | 1264 if (!value->BindsToConstant()) { |
| 1265 if (value->definition()->IsUnboxDouble()) { | 1265 UnboxInstr* unbox = value->definition()->AsUnbox(); |
| 1266 return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(), | 1266 if ((unbox != NULL) && (unbox->representation() == kUnboxedDouble)) { |
| 1267 result); | 1267 return ToIntegerConstant(unbox->value(), result); |
| 1268 } | 1268 } |
| 1269 return false; | 1269 return false; |
| 1270 } | 1270 } |
| 1271 | 1271 |
| 1272 const Object& constant = value->BoundConstant(); | 1272 const Object& constant = value->BoundConstant(); |
| 1273 if (constant.IsDouble()) { | 1273 if (constant.IsDouble()) { |
| 1274 const Double& double_constant = Double::Cast(constant); | 1274 const Double& double_constant = Double::Cast(constant); |
| 1275 *result = static_cast<int64_t>(double_constant.value()); | 1275 *result = static_cast<int64_t>(double_constant.value()); |
| 1276 return (static_cast<double>(*result) == double_constant.value()); | 1276 return (static_cast<double>(*result) == double_constant.value()); |
| 1277 } else if (constant.IsSmi()) { | 1277 } else if (constant.IsSmi()) { |
| (...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 Value* use = it.Current(); | 1897 Value* use = it.Current(); |
| 1898 if (use->instruction()->MayThrow() && | 1898 if (use->instruction()->MayThrow() && |
| 1899 use->instruction()->GetBlock()->InsideTryBlock()) { | 1899 use->instruction()->GetBlock()->InsideTryBlock()) { |
| 1900 return true; | 1900 return true; |
| 1901 } | 1901 } |
| 1902 } | 1902 } |
| 1903 return false; | 1903 return false; |
| 1904 } | 1904 } |
| 1905 | 1905 |
| 1906 | 1906 |
| 1907 Definition* BoxDoubleInstr::Canonicalize(FlowGraph* flow_graph) { | 1907 Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1908 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { | 1908 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { |
| 1909 // Environments can accomodate any representation. No need to box. | 1909 // Environments can accomodate any representation. No need to box. |
| 1910 return value()->definition(); | 1910 return value()->definition(); |
| 1911 } | 1911 } |
| 1912 | 1912 |
| 1913 // Fold away BoxDouble(UnboxDouble(v)) if value is known to be double. | 1913 // Fold away Box<rep>(Unbox<rep>(v)) if value is known to be of the |
| 1914 UnboxDoubleInstr* defn = value()->definition()->AsUnboxDouble(); | 1914 // right class. |
| 1915 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kDoubleCid)) { | 1915 UnboxInstr* unbox_defn = value()->definition()->AsUnbox(); |
| 1916 return defn->value()->definition(); | 1916 if ((unbox_defn != NULL) && |
| 1917 (unbox_defn->representation() == from_representation()) && |
| 1918 (unbox_defn->value()->Type()->ToCid() == Type()->ToCid())) { |
| 1919 return unbox_defn->value()->definition(); |
| 1917 } | 1920 } |
| 1918 | 1921 |
| 1919 return this; | 1922 return this; |
| 1920 } | 1923 } |
| 1921 | 1924 |
| 1922 | 1925 |
| 1923 bool BoxIntNInstr::ValueFitsSmi() const { | 1926 bool BoxIntegerInstr::ValueFitsSmi() const { |
| 1924 Range* range = value()->definition()->range(); | 1927 Range* range = value()->definition()->range(); |
| 1925 return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi); | 1928 return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi); |
| 1926 } | 1929 } |
| 1927 | 1930 |
| 1928 | 1931 |
| 1929 Definition* BoxIntNInstr::Canonicalize(FlowGraph* flow_graph) { | 1932 Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1930 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { | 1933 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { |
| 1931 // Environments can accomodate any representation. No need to box. | 1934 // Environments can accomodate any representation. No need to box. |
| 1932 return value()->definition(); | 1935 return value()->definition(); |
| 1933 } | 1936 } |
| 1934 | 1937 |
| 1935 return this; | 1938 return this; |
| 1936 } | 1939 } |
| 1937 | 1940 |
| 1938 | 1941 |
| 1939 Definition* UnboxIntNInstr::Canonicalize(FlowGraph* flow_graph) { | 1942 Definition* BoxInt64Instr::Canonicalize(FlowGraph* flow_graph) { |
| 1940 if (!HasUses()) return NULL; | 1943 Definition* replacement = BoxIntegerInstr::Canonicalize(flow_graph); |
| 1941 | |
| 1942 // Fold away UnboxInt<N>Instr(BoxInt<N>Instr(v)). | |
| 1943 BoxIntNInstr* box_defn = value()->definition()->AsBoxIntN(); | |
| 1944 if (box_defn != NULL) { | |
| 1945 if (box_defn->value()->definition()->representation() == representation()) { | |
| 1946 return box_defn->value()->definition(); | |
| 1947 } else { | |
| 1948 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( | |
| 1949 box_defn->value()->definition()->representation(), | |
| 1950 representation(), | |
| 1951 box_defn->value()->CopyWithType(), | |
| 1952 (representation() == kUnboxedInt32) ? | |
| 1953 GetDeoptId() : Isolate::kNoDeoptId); | |
| 1954 if ((representation() == kUnboxedInt32) && is_truncating()) { | |
| 1955 converter->mark_truncating(); | |
| 1956 } | |
| 1957 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); | |
| 1958 return converter; | |
| 1959 } | |
| 1960 } | |
| 1961 | |
| 1962 return this; | |
| 1963 } | |
| 1964 | |
| 1965 | |
| 1966 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { | |
| 1967 if (!HasUses()) return NULL; | |
| 1968 | |
| 1969 UnboxedIntConverterInstr* box_defn = | |
| 1970 value()->definition()->AsUnboxedIntConverter(); | |
| 1971 if ((box_defn != NULL) && (box_defn->representation() == from())) { | |
| 1972 if (box_defn->from() == to()) { | |
| 1973 return box_defn->value()->definition(); | |
| 1974 } | |
| 1975 | |
| 1976 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( | |
| 1977 box_defn->from(), | |
| 1978 representation(), | |
| 1979 box_defn->value()->CopyWithType(), | |
| 1980 (to() == kUnboxedInt32) ? GetDeoptId() : Isolate::kNoDeoptId); | |
| 1981 if ((representation() == kUnboxedInt32) && is_truncating()) { | |
| 1982 converter->mark_truncating(); | |
| 1983 } | |
| 1984 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); | |
| 1985 return converter; | |
| 1986 } | |
| 1987 | |
| 1988 UnboxIntegerInstr* unbox_defn = value()->definition()->AsUnboxInteger(); | |
| 1989 if (unbox_defn != NULL && | |
| 1990 (from() == kUnboxedMint) && | |
| 1991 (to() == kUnboxedInt32) && | |
| 1992 unbox_defn->HasOnlyInputUse(value())) { | |
| 1993 // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter | |
| 1994 // and code path that unboxes Mint into Int32. We should just schedule | |
| 1995 // these instructions close to each other instead of fusing them. | |
| 1996 Definition* replacement = | |
| 1997 new UnboxInt32Instr(unbox_defn->value()->CopyWithType(), GetDeoptId()); | |
| 1998 if (is_truncating()) { | |
| 1999 replacement->AsUnboxInt32()->mark_truncating(); | |
| 2000 } | |
| 2001 flow_graph->InsertBefore(this, | |
| 2002 replacement, | |
| 2003 env(), | |
| 2004 FlowGraph::kValue); | |
| 2005 return replacement; | |
| 2006 } | |
| 2007 | |
| 2008 return this; | |
| 2009 } | |
| 2010 | |
| 2011 | |
| 2012 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) { | |
| 2013 Definition* replacement = UnboxIntNInstr::Canonicalize(flow_graph); | |
| 2014 if (replacement != this) { | 1944 if (replacement != this) { |
| 2015 return replacement; | 1945 return replacement; |
| 2016 } | 1946 } |
| 2017 | 1947 |
| 2018 ConstantInstr* c = value()->definition()->AsConstant(); | |
| 2019 if ((c != NULL) && c->value().IsSmi()) { | |
| 2020 if (!is_truncating() && (kSmiBits > 32)) { | |
| 2021 // Check that constant fits into 32-bit integer. | |
| 2022 const int64_t value = | |
| 2023 static_cast<int64_t>(Smi::Cast(c->value()).Value()); | |
| 2024 if (!Utils::IsInt(32, value)) { | |
| 2025 return this; | |
| 2026 } | |
| 2027 } | |
| 2028 | |
| 2029 UnboxedConstantInstr* uc = | |
| 2030 new UnboxedConstantInstr(c->value(), kUnboxedInt32); | |
| 2031 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); | |
| 2032 return uc; | |
| 2033 } | |
| 2034 | |
| 2035 return this; | |
| 2036 } | |
| 2037 | |
| 2038 | |
| 2039 Definition* UnboxDoubleInstr::Canonicalize(FlowGraph* flow_graph) { | |
| 2040 if (!HasUses()) return NULL; | |
| 2041 // Fold away UnboxDouble(BoxDouble(v)). | |
| 2042 BoxDoubleInstr* box_defn = value()->definition()->AsBoxDouble(); | |
| 2043 if (box_defn != NULL) { | |
| 2044 return box_defn->value()->definition(); | |
| 2045 } | |
| 2046 | |
| 2047 ConstantInstr* c = value()->definition()->AsConstant(); | |
| 2048 if ((c != NULL) && c->value().IsDouble()) { | |
| 2049 UnboxedConstantInstr* uc = | |
| 2050 new UnboxedConstantInstr(c->value(), kUnboxedDouble); | |
| 2051 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); | |
| 2052 return uc; | |
| 2053 } | |
| 2054 | |
| 2055 return this; | |
| 2056 } | |
| 2057 | |
| 2058 | |
| 2059 Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { | |
| 2060 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { | |
| 2061 // Environments can accomodate any representation. No need to box. | |
| 2062 return value()->definition(); | |
| 2063 } | |
| 2064 | |
| 2065 UnboxedIntConverterInstr* conv = | 1948 UnboxedIntConverterInstr* conv = |
| 2066 value()->definition()->AsUnboxedIntConverter(); | 1949 value()->definition()->AsUnboxedIntConverter(); |
| 2067 if (conv != NULL) { | 1950 if (conv != NULL) { |
| 2068 Definition* replacement = this; | 1951 Definition* replacement = this; |
| 2069 | 1952 |
| 2070 switch (conv->from()) { | 1953 switch (conv->from()) { |
| 2071 case kUnboxedInt32: | 1954 case kUnboxedInt32: |
| 2072 replacement = new BoxInt32Instr(conv->value()->CopyWithType()); | 1955 replacement = new BoxInt32Instr(conv->value()->CopyWithType()); |
| 2073 break; | 1956 break; |
| 2074 case kUnboxedUint32: | 1957 case kUnboxedUint32: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2086 FlowGraph::kValue); | 1969 FlowGraph::kValue); |
| 2087 } | 1970 } |
| 2088 | 1971 |
| 2089 return replacement; | 1972 return replacement; |
| 2090 } | 1973 } |
| 2091 | 1974 |
| 2092 return this; | 1975 return this; |
| 2093 } | 1976 } |
| 2094 | 1977 |
| 2095 | 1978 |
| 2096 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { | 1979 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2097 if (!HasUses()) return NULL; | 1980 if (!HasUses()) return NULL; |
| 2098 return this; | |
| 2099 } | |
| 2100 | 1981 |
| 2101 | 1982 // Fold away Unbox<rep>(Box<rep>(v)). |
| 2102 Definition* BoxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) { | 1983 BoxInstr* box_defn = value()->definition()->AsBox(); |
| 2103 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { | 1984 if ((box_defn != NULL) && |
| 2104 // Environments can accomodate any representation. No need to box. | 1985 (box_defn->from_representation() == representation())) { |
| 2105 return value()->definition(); | 1986 return box_defn->value()->definition(); |
| 2106 } | 1987 } |
| 2107 | 1988 |
| 2108 // Fold away BoxFloat32x4(UnboxFloat32x4(v)). | 1989 if ((representation() == kUnboxedDouble) && value()->BindsToConstant()) { |
| 2109 UnboxFloat32x4Instr* defn = value()->definition()->AsUnboxFloat32x4(); | 1990 UnboxedConstantInstr* uc = NULL; |
| 2110 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat32x4Cid)) { | 1991 |
| 2111 return defn->value()->definition(); | 1992 const Object& val = value()->BoundConstant(); |
| 1993 if (val.IsSmi()) { |
| 1994 const Double& double_val = Double::ZoneHandle(flow_graph->isolate(), |
| 1995 Double::NewCanonical(Smi::Cast(val).AsDoubleValue())); |
| 1996 uc = new UnboxedConstantInstr(double_val, kUnboxedDouble); |
| 1997 } else if (val.IsDouble()) { |
| 1998 uc = new UnboxedConstantInstr(val, kUnboxedDouble); |
| 1999 } |
| 2000 |
| 2001 if (uc != NULL) { |
| 2002 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); |
| 2003 return uc; |
| 2004 } |
| 2112 } | 2005 } |
| 2113 | 2006 |
| 2114 return this; | 2007 return this; |
| 2115 } | 2008 } |
| 2116 | 2009 |
| 2117 | 2010 |
| 2118 Definition* UnboxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) { | 2011 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2119 // Fold away UnboxFloat32x4(BoxFloat32x4(v)). | 2012 if (!HasUses()) return NULL; |
| 2120 BoxFloat32x4Instr* defn = value()->definition()->AsBoxFloat32x4(); | |
| 2121 return (defn != NULL) ? defn->value()->definition() : this; | |
| 2122 } | |
| 2123 | 2013 |
| 2124 | 2014 // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)). |
| 2125 Definition* BoxFloat64x2Instr::Canonicalize(FlowGraph* flow_graph) { | 2015 BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger(); |
| 2126 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { | 2016 if (box_defn != NULL) { |
| 2127 // Environments can accomodate any representation. No need to box. | 2017 if (box_defn->value()->definition()->representation() == representation()) { |
| 2128 return value()->definition(); | 2018 return box_defn->value()->definition(); |
| 2129 } | 2019 } else { |
| 2130 | 2020 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( |
| 2131 // Fold away BoxFloat64x2(UnboxFloat64x2(v)). | 2021 box_defn->value()->definition()->representation(), |
| 2132 UnboxFloat64x2Instr* defn = value()->definition()->AsUnboxFloat64x2(); | 2022 representation(), |
| 2133 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat64x2Cid)) { | 2023 box_defn->value()->CopyWithType(), |
| 2134 return defn->value()->definition(); | 2024 (representation() == kUnboxedInt32) ? |
| 2025 GetDeoptId() : Isolate::kNoDeoptId); |
| 2026 if ((representation() == kUnboxedInt32) && is_truncating()) { |
| 2027 converter->mark_truncating(); |
| 2028 } |
| 2029 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); |
| 2030 return converter; |
| 2031 } |
| 2135 } | 2032 } |
| 2136 | 2033 |
| 2137 return this; | 2034 return this; |
| 2138 } | 2035 } |
| 2139 | 2036 |
| 2140 | 2037 |
| 2141 Definition* UnboxFloat64x2Instr::Canonicalize(FlowGraph* flow_graph) { | 2038 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) { |
| 2142 // Fold away UnboxFloat64x2(BoxFloat64x2(v)). | 2039 Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph); |
| 2143 BoxFloat64x2Instr* defn = value()->definition()->AsBoxFloat64x2(); | 2040 if (replacement != this) { |
| 2144 return (defn != NULL) ? defn->value()->definition() : this; | 2041 return replacement; |
| 2145 } | |
| 2146 | |
| 2147 | |
| 2148 | |
| 2149 Definition* BoxInt32x4Instr::Canonicalize(FlowGraph* flow_graph) { | |
| 2150 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { | |
| 2151 // Environments can accomodate any representation. No need to box. | |
| 2152 return value()->definition(); | |
| 2153 } | 2042 } |
| 2154 | 2043 |
| 2155 // Fold away BoxInt32x4(UnboxInt32x4(v)). | 2044 ConstantInstr* c = value()->definition()->AsConstant(); |
| 2156 UnboxInt32x4Instr* defn = value()->definition()->AsUnboxInt32x4(); | 2045 if ((c != NULL) && c->value().IsSmi()) { |
| 2157 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kInt32x4Cid)) { | 2046 if (!is_truncating() && (kSmiBits > 32)) { |
| 2158 return defn->value()->definition(); | 2047 // Check that constant fits into 32-bit integer. |
| 2048 const int64_t value = |
| 2049 static_cast<int64_t>(Smi::Cast(c->value()).Value()); |
| 2050 if (!Utils::IsInt(32, value)) { |
| 2051 return this; |
| 2052 } |
| 2053 } |
| 2054 |
| 2055 UnboxedConstantInstr* uc = |
| 2056 new UnboxedConstantInstr(c->value(), kUnboxedInt32); |
| 2057 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); |
| 2058 return uc; |
| 2159 } | 2059 } |
| 2160 | 2060 |
| 2161 return this; | 2061 return this; |
| 2162 } | 2062 } |
| 2163 | 2063 |
| 2164 | 2064 |
| 2165 Definition* UnboxInt32x4Instr::Canonicalize(FlowGraph* flow_graph) { | 2065 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2166 // Fold away UnboxInt32x4(BoxInt32x4(v)). | 2066 if (!HasUses()) return NULL; |
| 2167 BoxInt32x4Instr* defn = value()->definition()->AsBoxInt32x4(); | 2067 |
| 2168 return (defn != NULL) ? defn->value()->definition() : this; | 2068 UnboxedIntConverterInstr* box_defn = |
| 2069 value()->definition()->AsUnboxedIntConverter(); |
| 2070 if ((box_defn != NULL) && (box_defn->representation() == from())) { |
| 2071 if (box_defn->from() == to()) { |
| 2072 return box_defn->value()->definition(); |
| 2073 } |
| 2074 |
| 2075 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr( |
| 2076 box_defn->from(), |
| 2077 representation(), |
| 2078 box_defn->value()->CopyWithType(), |
| 2079 (to() == kUnboxedInt32) ? GetDeoptId() : Isolate::kNoDeoptId); |
| 2080 if ((representation() == kUnboxedInt32) && is_truncating()) { |
| 2081 converter->mark_truncating(); |
| 2082 } |
| 2083 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); |
| 2084 return converter; |
| 2085 } |
| 2086 |
| 2087 UnboxInt64Instr* unbox_defn = value()->definition()->AsUnboxInt64(); |
| 2088 if (unbox_defn != NULL && |
| 2089 (from() == kUnboxedMint) && |
| 2090 (to() == kUnboxedInt32) && |
| 2091 unbox_defn->HasOnlyInputUse(value())) { |
| 2092 // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter |
| 2093 // and code path that unboxes Mint into Int32. We should just schedule |
| 2094 // these instructions close to each other instead of fusing them. |
| 2095 Definition* replacement = |
| 2096 new UnboxInt32Instr(is_truncating() ? UnboxInt32Instr::kTruncate |
| 2097 : UnboxInt32Instr::kNoTruncation, |
| 2098 unbox_defn->value()->CopyWithType(), |
| 2099 GetDeoptId()); |
| 2100 flow_graph->InsertBefore(this, |
| 2101 replacement, |
| 2102 env(), |
| 2103 FlowGraph::kValue); |
| 2104 return replacement; |
| 2105 } |
| 2106 |
| 2107 return this; |
| 2169 } | 2108 } |
| 2170 | 2109 |
| 2171 | 2110 |
| 2172 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { | 2111 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2173 Definition* defn = value()->definition(); | 2112 Definition* defn = value()->definition(); |
| 2174 if (defn->IsComparison() && defn->HasOnlyUse(value())) { | 2113 if (defn->IsComparison() && defn->HasOnlyUse(value())) { |
| 2175 // Comparisons always have a bool result. | 2114 // Comparisons always have a bool result. |
| 2176 ASSERT(value()->Type()->ToCid() == kBoolCid); | 2115 ASSERT(value()->Type()->ToCid() == kBoolCid); |
| 2177 defn->AsComparison()->NegateComparison(); | 2116 defn->AsComparison()->NegateComparison(); |
| 2178 return defn; | 2117 return defn; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2453 | 2392 |
| 2454 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) { | 2393 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2455 if ((left()->Type()->ToCid() == kDoubleCid) || | 2394 if ((left()->Type()->ToCid() == kDoubleCid) || |
| 2456 (right()->Type()->ToCid() == kDoubleCid)) { | 2395 (right()->Type()->ToCid() == kDoubleCid)) { |
| 2457 return NULL; // Remove from the graph. | 2396 return NULL; // Remove from the graph. |
| 2458 } | 2397 } |
| 2459 return this; | 2398 return this; |
| 2460 } | 2399 } |
| 2461 | 2400 |
| 2462 | 2401 |
| 2402 BoxInstr* BoxInstr::Create(Representation from, Value* value) { |
| 2403 switch (from) { |
| 2404 case kUnboxedInt32: |
| 2405 return new BoxInt32Instr(value); |
| 2406 |
| 2407 case kUnboxedUint32: |
| 2408 return new BoxUint32Instr(value); |
| 2409 |
| 2410 case kUnboxedMint: |
| 2411 return new BoxInt64Instr(value); |
| 2412 |
| 2413 case kUnboxedDouble: |
| 2414 case kUnboxedFloat32x4: |
| 2415 case kUnboxedFloat64x2: |
| 2416 case kUnboxedInt32x4: |
| 2417 return new BoxInstr(from, value); |
| 2418 |
| 2419 default: |
| 2420 UNREACHABLE(); |
| 2421 return NULL; |
| 2422 } |
| 2423 } |
| 2424 |
| 2425 |
| 2426 UnboxInstr* UnboxInstr::Create(Representation to, |
| 2427 Value* value, |
| 2428 intptr_t deopt_id) { |
| 2429 switch (to) { |
| 2430 case kUnboxedInt32: |
| 2431 return new UnboxInt32Instr( |
| 2432 UnboxInt32Instr::kNoTruncation, value, deopt_id); |
| 2433 |
| 2434 case kUnboxedUint32: |
| 2435 return new UnboxUint32Instr(value, deopt_id); |
| 2436 |
| 2437 case kUnboxedMint: |
| 2438 return new UnboxInt64Instr(value, deopt_id); |
| 2439 |
| 2440 case kUnboxedDouble: |
| 2441 case kUnboxedFloat32x4: |
| 2442 case kUnboxedFloat64x2: |
| 2443 case kUnboxedInt32x4: |
| 2444 return new UnboxInstr(to, value, deopt_id); |
| 2445 |
| 2446 default: |
| 2447 UNREACHABLE(); |
| 2448 return NULL; |
| 2449 } |
| 2450 } |
| 2451 |
| 2452 |
| 2453 bool UnboxInstr::CanConvertSmi() const { |
| 2454 switch (representation()) { |
| 2455 case kUnboxedDouble: |
| 2456 case kUnboxedMint: |
| 2457 return true; |
| 2458 |
| 2459 case kUnboxedFloat32x4: |
| 2460 case kUnboxedFloat64x2: |
| 2461 case kUnboxedInt32x4: |
| 2462 return false; |
| 2463 |
| 2464 default: |
| 2465 UNREACHABLE(); |
| 2466 return false; |
| 2467 } |
| 2468 } |
| 2469 |
| 2470 |
| 2463 // Shared code generation methods (EmitNativeCode and | 2471 // Shared code generation methods (EmitNativeCode and |
| 2464 // MakeLocationSummary). Only assembly code that can be shared across all | 2472 // MakeLocationSummary). Only assembly code that can be shared across all |
| 2465 // architectures can be used. Machine specific register allocation and code | 2473 // architectures can be used. Machine specific register allocation and code |
| 2466 // generation is located in intermediate_language_<arch>.cc | 2474 // generation is located in intermediate_language_<arch>.cc |
| 2467 | 2475 |
| 2468 #define __ compiler->assembler()-> | 2476 #define __ compiler->assembler()-> |
| 2469 | 2477 |
| 2470 LocationSummary* GraphEntryInstr::MakeLocationSummary(Isolate* isolate, | 2478 LocationSummary* GraphEntryInstr::MakeLocationSummary(Isolate* isolate, |
| 2471 bool optimizing) const { | 2479 bool optimizing) const { |
| 2472 UNREACHABLE(); | 2480 UNREACHABLE(); |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3358 case Token::kTRUNCDIV: return 0; | 3366 case Token::kTRUNCDIV: return 0; |
| 3359 case Token::kMOD: return 1; | 3367 case Token::kMOD: return 1; |
| 3360 default: UNIMPLEMENTED(); return -1; | 3368 default: UNIMPLEMENTED(); return -1; |
| 3361 } | 3369 } |
| 3362 } | 3370 } |
| 3363 | 3371 |
| 3364 | 3372 |
| 3365 #undef __ | 3373 #undef __ |
| 3366 | 3374 |
| 3367 } // namespace dart | 3375 } // namespace dart |
| OLD | NEW |