| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 &StubCode::CallNativeCFunctionLabel(), | 938 &StubCode::CallNativeCFunctionLabel(), |
| 939 PcDescriptors::kOther, | 939 PcDescriptors::kOther, |
| 940 locs()); | 940 locs()); |
| 941 __ popq(result); | 941 __ popq(result); |
| 942 } | 942 } |
| 943 | 943 |
| 944 | 944 |
| 945 static bool CanBeImmediateIndex(Value* index) { | 945 static bool CanBeImmediateIndex(Value* index) { |
| 946 if (!index->definition()->IsConstant()) return false; | 946 if (!index->definition()->IsConstant()) return false; |
| 947 const Object& constant = index->definition()->AsConstant()->value(); | 947 const Object& constant = index->definition()->AsConstant()->value(); |
| 948 if (!constant.IsSmi()) return false; |
| 948 const Smi& smi_const = Smi::Cast(constant); | 949 const Smi& smi_const = Smi::Cast(constant); |
| 949 int64_t disp = smi_const.AsInt64Value() * kWordSize + sizeof(RawArray); | 950 int64_t disp = smi_const.AsInt64Value() * kWordSize + sizeof(RawArray); |
| 950 return Utils::IsInt(32, disp); | 951 return Utils::IsInt(32, disp); |
| 951 } | 952 } |
| 952 | 953 |
| 953 | 954 |
| 955 LocationSummary* StringCharCodeAtInstr::MakeLocationSummary() const { |
| 956 const intptr_t kNumInputs = 2; |
| 957 const intptr_t kNumTemps = 0; |
| 958 LocationSummary* locs = |
| 959 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 960 locs->set_in(0, Location::RequiresRegister()); |
| 961 // TODO(fschneider): Allow immediate operands for the index. |
| 962 locs->set_in(1, Location::RequiresRegister()); |
| 963 locs->set_out(Location::RequiresRegister()); |
| 964 return locs; |
| 965 } |
| 966 |
| 967 |
| 968 void StringCharCodeAtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 969 Register str = locs()->in(0).reg(); |
| 970 Register index = locs()->in(1).reg(); |
| 971 Register result = locs()->out().reg(); |
| 972 |
| 973 ASSERT((class_id() == kOneByteStringCid) || |
| 974 (class_id() == kTwoByteStringCid)); |
| 975 if (class_id() == kOneByteStringCid) { |
| 976 __ SmiUntag(index); |
| 977 __ movzxb(result, FieldAddress(str, |
| 978 index, |
| 979 TIMES_1, |
| 980 OneByteString::data_offset())); |
| 981 __ SmiTag(index); // Retag index. |
| 982 __ SmiTag(result); |
| 983 } else { |
| 984 // Don't untag smi-index and use TIMES_1 for two byte strings. |
| 985 __ movzxw(result, FieldAddress(str, |
| 986 index, |
| 987 TIMES_1, |
| 988 TwoByteString::data_offset())); |
| 989 __ SmiTag(result); |
| 990 } |
| 991 } |
| 992 |
| 993 |
| 954 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { | 994 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
| 955 const intptr_t kNumInputs = 2; | 995 const intptr_t kNumInputs = 2; |
| 956 const intptr_t kNumTemps = 0; | 996 const intptr_t kNumTemps = 0; |
| 957 LocationSummary* locs = | 997 LocationSummary* locs = |
| 958 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 998 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 959 locs->set_in(0, Location::RequiresRegister()); | 999 locs->set_in(0, Location::RequiresRegister()); |
| 960 locs->set_in(1, CanBeImmediateIndex(index()) | 1000 locs->set_in(1, CanBeImmediateIndex(index()) |
| 961 ? Location::RegisterOrConstant(index()) | 1001 ? Location::RegisterOrConstant(index()) |
| 962 : Location::RequiresRegister()); | 1002 : Location::RequiresRegister()); |
| 963 if (representation() == kUnboxedDouble) { | 1003 if (representation() == kUnboxedDouble) { |
| (...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2224 const intptr_t kNumTemps = 0; | 2264 const intptr_t kNumTemps = 0; |
| 2225 LocationSummary* locs = | 2265 LocationSummary* locs = |
| 2226 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2266 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2227 locs->set_in(0, Location::RequiresRegister()); | 2267 locs->set_in(0, Location::RequiresRegister()); |
| 2228 locs->set_in(1, Location::RegisterOrConstant(index())); | 2268 locs->set_in(1, Location::RegisterOrConstant(index())); |
| 2229 return locs; | 2269 return locs; |
| 2230 } | 2270 } |
| 2231 | 2271 |
| 2232 | 2272 |
| 2233 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2273 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2234 const DeoptReasonId deopt_reason = | |
| 2235 (array_type() == kGrowableObjectArrayCid) ? | |
| 2236 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | |
| 2237 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2274 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2238 deopt_reason); | 2275 kDeoptCheckArrayBound); |
| 2239 ASSERT((array_type() == kArrayCid) || | 2276 if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) { |
| 2240 (array_type() == kImmutableArrayCid) || | 2277 // Unconditionally deoptimize for constant bounds checks because they |
| 2241 (array_type() == kGrowableObjectArrayCid) || | 2278 // only occur only when index is out-of-bounds. |
| 2242 (array_type() == kFloat64ArrayCid) || | 2279 __ jmp(deopt); |
| 2243 (array_type() == kFloat32ArrayCid)); | 2280 return; |
| 2244 intptr_t length_offset = -1; | |
| 2245 if (array_type() == kGrowableObjectArrayCid) { | |
| 2246 length_offset = GrowableObjectArray::length_offset(); | |
| 2247 } else if (array_type() == kFloat64ArrayCid) { | |
| 2248 length_offset = Float64Array::length_offset(); | |
| 2249 } else if (array_type() == kFloat32ArrayCid) { | |
| 2250 length_offset = Float32Array::length_offset(); | |
| 2251 } else { | |
| 2252 length_offset = Array::length_offset(); | |
| 2253 } | 2281 } |
| 2254 | 2282 |
| 2255 // This case should not have created a bound check instruction. | |
| 2256 ASSERT(!(locs()->in(0).IsConstant() && locs()->in(1).IsConstant())); | |
| 2257 | 2283 |
| 2284 intptr_t length_offset = LengthOffsetFor(array_type()); |
| 2258 if (locs()->in(1).IsConstant()) { | 2285 if (locs()->in(1).IsConstant()) { |
| 2259 Register receiver = locs()->in(0).reg(); | 2286 Register receiver = locs()->in(0).reg(); |
| 2260 const Object& constant = locs()->in(1).constant(); | 2287 const Object& constant = locs()->in(1).constant(); |
| 2261 ASSERT(constant.IsSmi()); | 2288 ASSERT(constant.IsSmi()); |
| 2262 const int64_t imm = | 2289 const int64_t imm = |
| 2263 reinterpret_cast<int64_t>(constant.raw()); | 2290 reinterpret_cast<int64_t>(constant.raw()); |
| 2264 __ cmpq(FieldAddress(receiver, length_offset), Immediate(imm)); | 2291 __ cmpq(FieldAddress(receiver, length_offset), Immediate(imm)); |
| 2265 __ j(BELOW_EQUAL, deopt); | 2292 __ j(BELOW_EQUAL, deopt); |
| 2266 } else if (locs()->in(0).IsConstant()) { | 2293 } else if (locs()->in(0).IsConstant()) { |
| 2267 const Object& constant = locs()->in(0).constant(); | 2294 ASSERT(locs()->in(0).constant().IsArray() || |
| 2268 ASSERT(constant.IsArray()); | 2295 locs()->in(0).constant().IsString()); |
| 2269 const Array& array = Array::Cast(constant); | 2296 intptr_t length = locs()->in(0).constant().IsArray() |
| 2297 ? Array::Cast(locs()->in(0).constant()).Length() |
| 2298 : String::Cast(locs()->in(0).constant()).Length(); |
| 2270 Register index = locs()->in(1).reg(); | 2299 Register index = locs()->in(1).reg(); |
| 2271 __ cmpq(index, | 2300 __ cmpq(index, |
| 2272 Immediate(reinterpret_cast<int64_t>(Smi::New(array.Length())))); | 2301 Immediate(reinterpret_cast<int64_t>(Smi::New(length)))); |
| 2273 __ j(ABOVE_EQUAL, deopt); | 2302 __ j(ABOVE_EQUAL, deopt); |
| 2274 } else { | 2303 } else { |
| 2275 Register receiver = locs()->in(0).reg(); | 2304 Register receiver = locs()->in(0).reg(); |
| 2276 Register index = locs()->in(1).reg(); | 2305 Register index = locs()->in(1).reg(); |
| 2277 __ cmpq(index, FieldAddress(receiver, length_offset)); | 2306 __ cmpq(index, FieldAddress(receiver, length_offset)); |
| 2278 __ j(ABOVE_EQUAL, deopt); | 2307 __ j(ABOVE_EQUAL, deopt); |
| 2279 } | 2308 } |
| 2280 } | 2309 } |
| 2281 | 2310 |
| 2282 | 2311 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2332 | 2361 |
| 2333 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2362 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2334 UNIMPLEMENTED(); | 2363 UNIMPLEMENTED(); |
| 2335 } | 2364 } |
| 2336 | 2365 |
| 2337 } // namespace dart | 2366 } // namespace dart |
| 2338 | 2367 |
| 2339 #undef __ | 2368 #undef __ |
| 2340 | 2369 |
| 2341 #endif // defined TARGET_ARCH_X64 | 2370 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |