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 |