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