| OLD | NEW |
| 1 // Copyright (c) 2012, 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/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| (...skipping 1870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1882 LocationSummary* ConstraintInstr::MakeLocationSummary() const { | 1882 LocationSummary* ConstraintInstr::MakeLocationSummary() const { |
| 1883 UNREACHABLE(); | 1883 UNREACHABLE(); |
| 1884 return NULL; | 1884 return NULL; |
| 1885 } | 1885 } |
| 1886 | 1886 |
| 1887 | 1887 |
| 1888 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1888 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1889 UNREACHABLE(); | 1889 UNREACHABLE(); |
| 1890 } | 1890 } |
| 1891 | 1891 |
| 1892 LocationSummary* ThrowInstr::MakeLocationSummary() const { | |
| 1893 return new LocationSummary(0, 0, LocationSummary::kCall); | |
| 1894 } | |
| 1895 | |
| 1896 | |
| 1897 | |
| 1898 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1899 compiler->GenerateCallRuntime(token_pos(), | |
| 1900 kThrowRuntimeEntry, | |
| 1901 locs()); | |
| 1902 __ int3(); | |
| 1903 } | |
| 1904 | |
| 1905 | |
| 1906 LocationSummary* ReThrowInstr::MakeLocationSummary() const { | |
| 1907 return new LocationSummary(0, 0, LocationSummary::kCall); | |
| 1908 } | |
| 1909 | |
| 1910 | |
| 1911 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1912 compiler->GenerateCallRuntime(token_pos(), | |
| 1913 kReThrowRuntimeEntry, | |
| 1914 locs()); | |
| 1915 __ int3(); | |
| 1916 } | |
| 1917 | |
| 1918 | |
| 1919 LocationSummary* GotoInstr::MakeLocationSummary() const { | |
| 1920 return new LocationSummary(0, 0, LocationSummary::kNoCall); | |
| 1921 } | |
| 1922 | |
| 1923 | |
| 1924 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1925 // Add deoptimization descriptor for deoptimizing instructions | |
| 1926 // that may be inserted before this instruction. | |
| 1927 if (!compiler->is_optimizing()) { | |
| 1928 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, | |
| 1929 GetDeoptId(), | |
| 1930 0); // No token position. | |
| 1931 } | |
| 1932 | |
| 1933 if (HasParallelMove()) { | |
| 1934 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | |
| 1935 } | |
| 1936 | |
| 1937 // We can fall through if the successor is the next block in the list. | |
| 1938 // Otherwise, we need a jump. | |
| 1939 if (!compiler->IsNextBlock(successor())) { | |
| 1940 __ jmp(compiler->GetBlockLabel(successor())); | |
| 1941 } | |
| 1942 } | |
| 1943 | |
| 1944 | |
| 1945 static Condition NegateCondition(Condition condition) { | |
| 1946 switch (condition) { | |
| 1947 case EQUAL: return NOT_EQUAL; | |
| 1948 case NOT_EQUAL: return EQUAL; | |
| 1949 case LESS: return GREATER_EQUAL; | |
| 1950 case LESS_EQUAL: return GREATER; | |
| 1951 case GREATER: return LESS_EQUAL; | |
| 1952 case GREATER_EQUAL: return LESS; | |
| 1953 case BELOW: return ABOVE_EQUAL; | |
| 1954 case BELOW_EQUAL: return ABOVE; | |
| 1955 case ABOVE: return BELOW_EQUAL; | |
| 1956 case ABOVE_EQUAL: return BELOW; | |
| 1957 default: | |
| 1958 OS::Print("Error %d\n", condition); | |
| 1959 UNIMPLEMENTED(); | |
| 1960 return EQUAL; | |
| 1961 } | |
| 1962 } | |
| 1963 | |
| 1964 | |
| 1965 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, | |
| 1966 bool value) { | |
| 1967 if (value && compiler->IsNextBlock(false_successor())) { | |
| 1968 __ jmp(compiler->GetBlockLabel(true_successor())); | |
| 1969 } else if (!value && compiler->IsNextBlock(true_successor())) { | |
| 1970 __ jmp(compiler->GetBlockLabel(false_successor())); | |
| 1971 } | |
| 1972 } | |
| 1973 | |
| 1974 | |
| 1975 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, | |
| 1976 Condition true_condition) { | |
| 1977 if (compiler->IsNextBlock(false_successor())) { | |
| 1978 // If the next block is the false successor we will fall through to it. | |
| 1979 __ j(true_condition, compiler->GetBlockLabel(true_successor())); | |
| 1980 } else { | |
| 1981 // If the next block is the true successor we negate comparison and fall | |
| 1982 // through to it. | |
| 1983 ASSERT(compiler->IsNextBlock(true_successor())); | |
| 1984 Condition false_condition = NegateCondition(true_condition); | |
| 1985 __ j(false_condition, compiler->GetBlockLabel(false_successor())); | |
| 1986 } | |
| 1987 } | |
| 1988 | |
| 1989 | |
| 1990 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { | |
| 1991 return LocationSummary::Make(0, | |
| 1992 Location::RequiresRegister(), | |
| 1993 LocationSummary::kNoCall); | |
| 1994 } | |
| 1995 | |
| 1996 | |
| 1997 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 1998 __ MoveRegister(locs()->out().reg(), CTX); | |
| 1999 } | |
| 2000 | |
| 2001 | 1892 |
| 2002 LocationSummary* StoreContextInstr::MakeLocationSummary() const { | 1893 LocationSummary* StoreContextInstr::MakeLocationSummary() const { |
| 2003 const intptr_t kNumInputs = 1; | 1894 const intptr_t kNumInputs = 1; |
| 2004 const intptr_t kNumTemps = 0; | 1895 const intptr_t kNumTemps = 0; |
| 2005 LocationSummary* summary = | 1896 LocationSummary* summary = |
| 2006 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1897 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2007 summary->set_in(0, Location::RegisterLocation(CTX)); | 1898 summary->set_in(0, Location::RegisterLocation(CTX)); |
| 2008 return summary; | 1899 return summary; |
| 2009 } | 1900 } |
| 2010 | 1901 |
| 2011 | 1902 |
| 2012 void StoreContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1903 void StoreContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2013 // Nothing to do. Context register were loaded by register allocator. | 1904 // Nothing to do. Context register were loaded by register allocator. |
| 2014 ASSERT(locs()->in(0).reg() == CTX); | 1905 ASSERT(locs()->in(0).reg() == CTX); |
| 2015 } | 1906 } |
| 2016 | 1907 |
| 2017 | 1908 |
| 2018 StrictCompareInstr::StrictCompareInstr(Token::Kind kind, | 1909 StrictCompareInstr::StrictCompareInstr(Token::Kind kind, |
| 2019 Value* left, | 1910 Value* left, |
| 2020 Value* right) | 1911 Value* right) |
| 2021 : ComparisonInstr(kind, left, right), | 1912 : ComparisonInstr(kind, left, right), |
| 2022 needs_number_check_(FLAG_new_identity_spec) { | 1913 needs_number_check_(FLAG_new_identity_spec) { |
| 2023 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); | 1914 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); |
| 2024 } | 1915 } |
| 2025 | 1916 |
| 2026 | 1917 |
| 2027 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { | |
| 2028 const intptr_t kNumInputs = 2; | |
| 2029 const intptr_t kNumTemps = 0; | |
| 2030 LocationSummary* locs = | |
| 2031 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 2032 locs->set_in(0, Location::RegisterOrConstant(left())); | |
| 2033 locs->set_in(1, Location::RegisterOrConstant(right())); | |
| 2034 locs->set_out(Location::RequiresRegister()); | |
| 2035 return locs; | |
| 2036 } | |
| 2037 | |
| 2038 | |
| 2039 // Special code for numbers (compare values instead of references.) | |
| 2040 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2041 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | |
| 2042 Location left = locs()->in(0); | |
| 2043 Location right = locs()->in(1); | |
| 2044 if (left.IsConstant() && right.IsConstant()) { | |
| 2045 // TODO(vegorov): should be eliminated earlier by constant propagation. | |
| 2046 const bool result = (kind() == Token::kEQ_STRICT) ? | |
| 2047 left.constant().raw() == right.constant().raw() : | |
| 2048 left.constant().raw() != right.constant().raw(); | |
| 2049 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); | |
| 2050 return; | |
| 2051 } | |
| 2052 if (left.IsConstant()) { | |
| 2053 compiler->EmitEqualityRegConstCompare(right.reg(), | |
| 2054 left.constant(), | |
| 2055 needs_number_check()); | |
| 2056 } else if (right.IsConstant()) { | |
| 2057 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 2058 right.constant(), | |
| 2059 needs_number_check()); | |
| 2060 } else { | |
| 2061 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 2062 right.reg(), | |
| 2063 needs_number_check()); | |
| 2064 } | |
| 2065 | |
| 2066 Register result = locs()->out().reg(); | |
| 2067 Label load_true, done; | |
| 2068 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | |
| 2069 __ j(true_condition, &load_true, Assembler::kNearJump); | |
| 2070 __ LoadObject(result, Bool::False()); | |
| 2071 __ jmp(&done, Assembler::kNearJump); | |
| 2072 __ Bind(&load_true); | |
| 2073 __ LoadObject(result, Bool::True()); | |
| 2074 __ Bind(&done); | |
| 2075 } | |
| 2076 | |
| 2077 | |
| 2078 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | |
| 2079 BranchInstr* branch) { | |
| 2080 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | |
| 2081 Location left = locs()->in(0); | |
| 2082 Location right = locs()->in(1); | |
| 2083 if (left.IsConstant() && right.IsConstant()) { | |
| 2084 // TODO(vegorov): should be eliminated earlier by constant propagation. | |
| 2085 const bool result = (kind() == Token::kEQ_STRICT) ? | |
| 2086 left.constant().raw() == right.constant().raw() : | |
| 2087 left.constant().raw() != right.constant().raw(); | |
| 2088 branch->EmitBranchOnValue(compiler, result); | |
| 2089 return; | |
| 2090 } | |
| 2091 if (left.IsConstant()) { | |
| 2092 compiler->EmitEqualityRegConstCompare(right.reg(), | |
| 2093 left.constant(), | |
| 2094 needs_number_check()); | |
| 2095 } else if (right.IsConstant()) { | |
| 2096 compiler->EmitEqualityRegConstCompare(left.reg(), | |
| 2097 right.constant(), | |
| 2098 needs_number_check()); | |
| 2099 } else { | |
| 2100 compiler->EmitEqualityRegRegCompare(left.reg(), | |
| 2101 right.reg(), | |
| 2102 needs_number_check()); | |
| 2103 } | |
| 2104 | |
| 2105 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | |
| 2106 branch->EmitBranchOnCondition(compiler, true_condition); | |
| 2107 } | |
| 2108 | |
| 2109 | |
| 2110 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2111 // The arguments to the stub include the closure, as does the arguments | |
| 2112 // descriptor. | |
| 2113 Register temp_reg = locs()->temp(0).reg(); | |
| 2114 int argument_count = ArgumentCount(); | |
| 2115 const Array& arguments_descriptor = | |
| 2116 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | |
| 2117 argument_names())); | |
| 2118 __ LoadObject(temp_reg, arguments_descriptor); | |
| 2119 compiler->GenerateDartCall(deopt_id(), | |
| 2120 token_pos(), | |
| 2121 &StubCode::CallClosureFunctionLabel(), | |
| 2122 PcDescriptors::kOther, | |
| 2123 locs()); | |
| 2124 __ Drop(argument_count); | |
| 2125 } | |
| 2126 | |
| 2127 | |
| 2128 LocationSummary* InstanceCallInstr::MakeLocationSummary() const { | 1918 LocationSummary* InstanceCallInstr::MakeLocationSummary() const { |
| 2129 return MakeCallSummary(); | 1919 return MakeCallSummary(); |
| 2130 } | 1920 } |
| 2131 | 1921 |
| 2132 | 1922 |
| 2133 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1923 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2134 ICData& call_ic_data = ICData::ZoneHandle(ic_data()->raw()); | 1924 ICData& call_ic_data = ICData::ZoneHandle(ic_data()->raw()); |
| 2135 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { | 1925 if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) { |
| 2136 call_ic_data = ICData::New(compiler->parsed_function().function(), | 1926 call_ic_data = ICData::New(compiler->parsed_function().function(), |
| 2137 function_name(), | 1927 function_name(), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2205 if (!is_eliminated()) { | 1995 if (!is_eliminated()) { |
| 2206 compiler->GenerateAssertAssignable(token_pos(), | 1996 compiler->GenerateAssertAssignable(token_pos(), |
| 2207 dst_type(), | 1997 dst_type(), |
| 2208 dst_name(), | 1998 dst_name(), |
| 2209 locs()); | 1999 locs()); |
| 2210 } | 2000 } |
| 2211 ASSERT(locs()->in(0).reg() == locs()->out().reg()); | 2001 ASSERT(locs()->in(0).reg() == locs()->out().reg()); |
| 2212 } | 2002 } |
| 2213 | 2003 |
| 2214 | 2004 |
| 2215 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { | |
| 2216 return LocationSummary::Make(1, | |
| 2217 Location::RequiresRegister(), | |
| 2218 LocationSummary::kNoCall); | |
| 2219 } | |
| 2220 | |
| 2221 | |
| 2222 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2223 Register value = locs()->in(0).reg(); | |
| 2224 Register result = locs()->out().reg(); | |
| 2225 | |
| 2226 Label done; | |
| 2227 __ LoadObject(result, Bool::True()); | |
| 2228 __ CompareRegisters(result, value); | |
| 2229 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | |
| 2230 __ LoadObject(result, Bool::False()); | |
| 2231 __ Bind(&done); | |
| 2232 } | |
| 2233 | |
| 2234 | |
| 2235 LocationSummary* ChainContextInstr::MakeLocationSummary() const { | |
| 2236 return LocationSummary::Make(1, | |
| 2237 Location::NoLocation(), | |
| 2238 LocationSummary::kNoCall); | |
| 2239 } | |
| 2240 | |
| 2241 | |
| 2242 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2243 Register context_value = locs()->in(0).reg(); | |
| 2244 | |
| 2245 // Chain the new context in context_value to its parent in CTX. | |
| 2246 __ StoreIntoObject(context_value, | |
| 2247 FieldAddress(context_value, Context::parent_offset()), | |
| 2248 CTX); | |
| 2249 // Set new context as current context. | |
| 2250 __ MoveRegister(CTX, context_value); | |
| 2251 } | |
| 2252 | |
| 2253 | |
| 2254 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { | |
| 2255 const intptr_t kNumInputs = 2; | |
| 2256 const intptr_t kNumTemps = 0; | |
| 2257 LocationSummary* locs = | |
| 2258 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 2259 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | |
| 2260 : Location::RequiresRegister()); | |
| 2261 locs->set_in(1, Location::RequiresRegister()); | |
| 2262 return locs; | |
| 2263 } | |
| 2264 | |
| 2265 | |
| 2266 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2267 Register value_reg = locs()->in(0).reg(); | |
| 2268 Register dest_reg = locs()->in(1).reg(); | |
| 2269 | |
| 2270 if (value()->NeedsStoreBuffer()) { | |
| 2271 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), | |
| 2272 value_reg); | |
| 2273 } else { | |
| 2274 __ StoreIntoObjectNoBarrier( | |
| 2275 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); | |
| 2276 } | |
| 2277 } | |
| 2278 | |
| 2279 | |
| 2280 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { | |
| 2281 return MakeCallSummary(); | |
| 2282 } | |
| 2283 | |
| 2284 | |
| 2285 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2286 const Class& cls = Class::ZoneHandle(constructor().Owner()); | |
| 2287 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | |
| 2288 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | |
| 2289 compiler->GenerateCall(token_pos(), | |
| 2290 &label, | |
| 2291 PcDescriptors::kOther, | |
| 2292 locs()); | |
| 2293 __ Drop(ArgumentCount()); // Discard arguments. | |
| 2294 } | |
| 2295 | |
| 2296 | |
| 2297 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { | |
| 2298 return MakeCallSummary(); | |
| 2299 } | |
| 2300 | |
| 2301 | |
| 2302 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 2303 const Function& closure_function = function(); | |
| 2304 ASSERT(!closure_function.IsImplicitStaticClosureFunction()); | |
| 2305 const Code& stub = Code::Handle( | |
| 2306 StubCode::GetAllocationStubForClosure(closure_function)); | |
| 2307 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); | |
| 2308 compiler->GenerateCall(token_pos(), | |
| 2309 &label, | |
| 2310 PcDescriptors::kOther, | |
| 2311 locs()); | |
| 2312 __ Drop(2); // Discard type arguments and receiver. | |
| 2313 } | |
| 2314 | |
| 2315 | |
| 2316 Environment* Environment::From(const GrowableArray<Definition*>& definitions, | 2005 Environment* Environment::From(const GrowableArray<Definition*>& definitions, |
| 2317 intptr_t fixed_parameter_count, | 2006 intptr_t fixed_parameter_count, |
| 2318 const Function& function) { | 2007 const Function& function) { |
| 2319 Environment* env = | 2008 Environment* env = |
| 2320 new Environment(definitions.length(), | 2009 new Environment(definitions.length(), |
| 2321 fixed_parameter_count, | 2010 fixed_parameter_count, |
| 2322 Isolate::kNoDeoptId, | 2011 Isolate::kNoDeoptId, |
| 2323 function, | 2012 function, |
| 2324 NULL); | 2013 NULL); |
| 2325 for (intptr_t i = 0; i < definitions.length(); ++i) { | 2014 for (intptr_t i = 0; i < definitions.length(); ++i) { |
| (...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2973 case kFloat64ArrayCid: | 2662 case kFloat64ArrayCid: |
| 2974 case kFloat32ArrayCid: | 2663 case kFloat32ArrayCid: |
| 2975 case kExternalUint8ArrayCid: | 2664 case kExternalUint8ArrayCid: |
| 2976 return ByteArray::length_offset(); | 2665 return ByteArray::length_offset(); |
| 2977 default: | 2666 default: |
| 2978 UNREACHABLE(); | 2667 UNREACHABLE(); |
| 2979 return -1; | 2668 return -1; |
| 2980 } | 2669 } |
| 2981 } | 2670 } |
| 2982 | 2671 |
| 2983 | |
| 2984 #undef __ | 2672 #undef __ |
| 2985 | 2673 |
| 2986 } // namespace dart | 2674 } // namespace dart |
| OLD | NEW |