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 |