| OLD | NEW |
| 1 // Copyright (c) 2013, 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/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 return NULL; | 852 return NULL; |
| 853 } | 853 } |
| 854 | 854 |
| 855 | 855 |
| 856 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 856 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 857 UNIMPLEMENTED(); | 857 UNIMPLEMENTED(); |
| 858 } | 858 } |
| 859 | 859 |
| 860 | 860 |
| 861 CompileType LoadIndexedInstr::ComputeType() const { | 861 CompileType LoadIndexedInstr::ComputeType() const { |
| 862 UNIMPLEMENTED(); | 862 switch (class_id_) { |
| 863 return CompileType::Dynamic(); | 863 case kArrayCid: |
| 864 case kImmutableArrayCid: |
| 865 return CompileType::Dynamic(); |
| 866 |
| 867 case kTypedDataFloat32ArrayCid: |
| 868 case kTypedDataFloat64ArrayCid: |
| 869 return CompileType::FromCid(kDoubleCid); |
| 870 case kTypedDataFloat32x4ArrayCid: |
| 871 return CompileType::FromCid(kFloat32x4Cid); |
| 872 |
| 873 case kTypedDataInt8ArrayCid: |
| 874 case kTypedDataUint8ArrayCid: |
| 875 case kTypedDataUint8ClampedArrayCid: |
| 876 case kExternalTypedDataUint8ArrayCid: |
| 877 case kExternalTypedDataUint8ClampedArrayCid: |
| 878 case kTypedDataInt16ArrayCid: |
| 879 case kTypedDataUint16ArrayCid: |
| 880 case kOneByteStringCid: |
| 881 case kTwoByteStringCid: |
| 882 return CompileType::FromCid(kSmiCid); |
| 883 |
| 884 case kTypedDataInt32ArrayCid: |
| 885 case kTypedDataUint32ArrayCid: |
| 886 // Result can be Smi or Mint when boxed. |
| 887 // Instruction can deoptimize if we optimistically assumed that the result |
| 888 // fits into Smi. |
| 889 return CanDeoptimize() ? CompileType::FromCid(kSmiCid) |
| 890 : CompileType::Int(); |
| 891 |
| 892 default: |
| 893 UNIMPLEMENTED(); |
| 894 return CompileType::Dynamic(); |
| 895 } |
| 864 } | 896 } |
| 865 | 897 |
| 866 | 898 |
| 867 Representation LoadIndexedInstr::representation() const { | 899 Representation LoadIndexedInstr::representation() const { |
| 868 UNIMPLEMENTED(); | 900 switch (class_id_) { |
| 869 return kTagged; | 901 case kArrayCid: |
| 902 case kImmutableArrayCid: |
| 903 case kTypedDataInt8ArrayCid: |
| 904 case kTypedDataUint8ArrayCid: |
| 905 case kTypedDataUint8ClampedArrayCid: |
| 906 case kExternalTypedDataUint8ArrayCid: |
| 907 case kExternalTypedDataUint8ClampedArrayCid: |
| 908 case kTypedDataInt16ArrayCid: |
| 909 case kTypedDataUint16ArrayCid: |
| 910 case kOneByteStringCid: |
| 911 case kTwoByteStringCid: |
| 912 return kTagged; |
| 913 case kTypedDataInt32ArrayCid: |
| 914 case kTypedDataUint32ArrayCid: |
| 915 // Instruction can deoptimize if we optimistically assumed that the result |
| 916 // fits into Smi. |
| 917 return CanDeoptimize() ? kTagged : kUnboxedMint; |
| 918 case kTypedDataFloat32ArrayCid: |
| 919 case kTypedDataFloat64ArrayCid: |
| 920 return kUnboxedDouble; |
| 921 case kTypedDataFloat32x4ArrayCid: |
| 922 return kUnboxedFloat32x4; |
| 923 default: |
| 924 UNIMPLEMENTED(); |
| 925 return kTagged; |
| 926 } |
| 870 } | 927 } |
| 871 | 928 |
| 872 | 929 |
| 873 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { | 930 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const { |
| 874 UNIMPLEMENTED(); | 931 const intptr_t kNumInputs = 2; |
| 875 return NULL; | 932 const intptr_t kNumTemps = 0; |
| 933 LocationSummary* locs = |
| 934 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 935 locs->set_in(0, Location::RequiresRegister()); |
| 936 // The smi index is either untagged (element size == 1), or it is left smi |
| 937 // tagged (for all element sizes > 1). |
| 938 // TODO(regis): Revisit and see if the index can be immediate. |
| 939 locs->set_in(1, Location::WritableRegister()); |
| 940 if (representation() == kUnboxedDouble) { |
| 941 locs->set_out(Location::RequiresFpuRegister()); |
| 942 } else { |
| 943 locs->set_out(Location::RequiresRegister()); |
| 944 } |
| 945 return locs; |
| 876 } | 946 } |
| 877 | 947 |
| 878 | 948 |
| 879 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 949 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 880 UNIMPLEMENTED(); | 950 Register array = locs()->in(0).reg(); |
| 951 Location index = locs()->in(1); |
| 952 |
| 953 Address element_address(kNoRegister, 0); |
| 954 if (IsExternal()) { |
| 955 UNIMPLEMENTED(); |
| 956 } else { |
| 957 ASSERT(this->array()->definition()->representation() == kTagged); |
| 958 ASSERT(index.IsRegister()); // TODO(regis): Revisit. |
| 959 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays |
| 960 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the |
| 961 // index is expected to be untagged before accessing. |
| 962 ASSERT(kSmiTagShift == 1); |
| 963 switch (index_scale()) { |
| 964 case 1: { |
| 965 __ SmiUntag(index.reg()); |
| 966 break; |
| 967 } |
| 968 case 2: { |
| 969 break; |
| 970 } |
| 971 case 4: { |
| 972 __ sll(index.reg(), index.reg(), 1); |
| 973 break; |
| 974 } |
| 975 case 8: { |
| 976 __ sll(index.reg(), index.reg(), 2); |
| 977 break; |
| 978 } |
| 979 case 16: { |
| 980 __ sll(index.reg(), index.reg(), 3); |
| 981 break; |
| 982 } |
| 983 default: |
| 984 UNREACHABLE(); |
| 985 } |
| 986 __ AddImmediate(index.reg(), |
| 987 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
| 988 element_address = Address(array, index.reg()); |
| 989 } |
| 990 |
| 991 if ((representation() == kUnboxedDouble) || |
| 992 (representation() == kUnboxedMint) || |
| 993 (representation() == kUnboxedFloat32x4)) { |
| 994 UNIMPLEMENTED(); |
| 995 } |
| 996 |
| 997 Register result = locs()->out().reg(); |
| 998 if ((index_scale() == 1) && index.IsRegister()) { |
| 999 __ SmiUntag(index.reg()); |
| 1000 } |
| 1001 switch (class_id()) { |
| 1002 case kTypedDataInt8ArrayCid: |
| 1003 ASSERT(index_scale() == 1); |
| 1004 __ lb(result, element_address); |
| 1005 __ SmiTag(result); |
| 1006 break; |
| 1007 case kTypedDataUint8ArrayCid: |
| 1008 case kTypedDataUint8ClampedArrayCid: |
| 1009 case kExternalTypedDataUint8ArrayCid: |
| 1010 case kExternalTypedDataUint8ClampedArrayCid: |
| 1011 case kOneByteStringCid: |
| 1012 ASSERT(index_scale() == 1); |
| 1013 __ lbu(result, element_address); |
| 1014 __ SmiTag(result); |
| 1015 break; |
| 1016 case kTypedDataInt16ArrayCid: |
| 1017 __ lh(result, element_address); |
| 1018 __ SmiTag(result); |
| 1019 break; |
| 1020 case kTypedDataUint16ArrayCid: |
| 1021 case kTwoByteStringCid: |
| 1022 __ lhu(result, element_address); |
| 1023 __ SmiTag(result); |
| 1024 break; |
| 1025 case kTypedDataInt32ArrayCid: { |
| 1026 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load); |
| 1027 __ lw(result, element_address); |
| 1028 // Verify that the signed value in 'result' can fit inside a Smi. |
| 1029 __ BranchLess(result, 0xC0000000, deopt); |
| 1030 __ SmiTag(result); |
| 1031 } |
| 1032 break; |
| 1033 case kTypedDataUint32ArrayCid: { |
| 1034 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load); |
| 1035 __ lw(result, element_address); |
| 1036 // Verify that the unsigned value in 'result' can fit inside a Smi. |
| 1037 __ LoadImmediate(TMP1, 0xC0000000); |
| 1038 __ and_(CMPRES, result, TMP1); |
| 1039 __ bne(CMPRES, ZR, deopt); |
| 1040 __ SmiTag(result); |
| 1041 } |
| 1042 break; |
| 1043 default: |
| 1044 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1045 __ lw(result, element_address); |
| 1046 break; |
| 1047 } |
| 881 } | 1048 } |
| 882 | 1049 |
| 883 | 1050 |
| 884 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1051 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 885 intptr_t idx) const { | 1052 intptr_t idx) const { |
| 886 UNIMPLEMENTED(); | 1053 UNIMPLEMENTED(); |
| 887 return kTagged; | 1054 return kTagged; |
| 888 } | 1055 } |
| 889 | 1056 |
| 890 | 1057 |
| (...skipping 1136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 } | 2194 } |
| 2028 | 2195 |
| 2029 | 2196 |
| 2030 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2197 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2031 __ TraceSimMsg("BranchInstr"); | 2198 __ TraceSimMsg("BranchInstr"); |
| 2032 comparison()->EmitBranchCode(compiler, this); | 2199 comparison()->EmitBranchCode(compiler, this); |
| 2033 } | 2200 } |
| 2034 | 2201 |
| 2035 | 2202 |
| 2036 LocationSummary* CheckClassInstr::MakeLocationSummary() const { | 2203 LocationSummary* CheckClassInstr::MakeLocationSummary() const { |
| 2037 UNIMPLEMENTED(); | 2204 const intptr_t kNumInputs = 1; |
| 2038 return NULL; | 2205 const intptr_t kNumTemps = 0; |
| 2206 LocationSummary* summary = |
| 2207 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2208 summary->set_in(0, Location::RequiresRegister()); |
| 2209 if (!null_check()) { |
| 2210 summary->AddTemp(Location::RequiresRegister()); |
| 2211 } |
| 2212 return summary; |
| 2039 } | 2213 } |
| 2040 | 2214 |
| 2041 | 2215 |
| 2042 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2216 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2043 UNIMPLEMENTED(); | 2217 if (null_check()) { |
| 2218 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2219 kDeoptCheckClass); |
| 2220 __ BranchEqual(locs()->in(0).reg(), |
| 2221 reinterpret_cast<intptr_t>(Object::null()), deopt); |
| 2222 return; |
| 2223 } |
| 2224 |
| 2225 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 2226 (unary_checks().NumberOfChecks() > 1)); |
| 2227 Register value = locs()->in(0).reg(); |
| 2228 Register temp = locs()->temp(0).reg(); |
| 2229 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2230 kDeoptCheckClass); |
| 2231 Label is_ok; |
| 2232 intptr_t cix = 0; |
| 2233 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { |
| 2234 __ andi(CMPRES, value, Immediate(kSmiTagMask)); |
| 2235 __ beq(CMPRES, ZR, &is_ok); |
| 2236 cix++; // Skip first check. |
| 2237 } else { |
| 2238 __ andi(CMPRES, value, Immediate(kSmiTagMask)); |
| 2239 __ beq(CMPRES, ZR, deopt); |
| 2240 } |
| 2241 __ LoadClassId(temp, value); |
| 2242 const intptr_t num_checks = unary_checks().NumberOfChecks(); |
| 2243 for (intptr_t i = cix; i < num_checks; i++) { |
| 2244 ASSERT(unary_checks().GetReceiverClassIdAt(i) != kSmiCid); |
| 2245 __ LoadImmediate(TMP1, unary_checks().GetReceiverClassIdAt(i)); |
| 2246 __ subu(CMPRES, temp, TMP1); |
| 2247 if (i == (num_checks - 1)) { |
| 2248 __ bne(CMPRES, ZR, deopt); |
| 2249 } else { |
| 2250 __ beq(CMPRES, ZR, &is_ok); |
| 2251 } |
| 2252 } |
| 2253 __ Bind(&is_ok); |
| 2044 } | 2254 } |
| 2045 | 2255 |
| 2046 | 2256 |
| 2047 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { | 2257 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { |
| 2048 const intptr_t kNumInputs = 1; | 2258 const intptr_t kNumInputs = 1; |
| 2049 const intptr_t kNumTemps = 0; | 2259 const intptr_t kNumTemps = 0; |
| 2050 LocationSummary* summary = | 2260 LocationSummary* summary = |
| 2051 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2052 summary->set_in(0, Location::RequiresRegister()); | 2262 summary->set_in(0, Location::RequiresRegister()); |
| 2053 return summary; | 2263 return summary; |
| 2054 } | 2264 } |
| 2055 | 2265 |
| 2056 | 2266 |
| 2057 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2267 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2058 __ TraceSimMsg("CheckSmiInstr"); | 2268 __ TraceSimMsg("CheckSmiInstr"); |
| 2059 Register value = locs()->in(0).reg(); | 2269 Register value = locs()->in(0).reg(); |
| 2060 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2270 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2061 kDeoptCheckSmi); | 2271 kDeoptCheckSmi); |
| 2062 __ andi(TMP1, value, Immediate(kSmiTagMask)); | 2272 __ andi(TMP1, value, Immediate(kSmiTagMask)); |
| 2063 __ bne(TMP1, ZR, deopt); | 2273 __ bne(TMP1, ZR, deopt); |
| 2064 } | 2274 } |
| 2065 | 2275 |
| 2066 | 2276 |
| 2067 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { | 2277 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { |
| 2068 UNIMPLEMENTED(); | 2278 const intptr_t kNumInputs = 2; |
| 2069 return NULL; | 2279 const intptr_t kNumTemps = 0; |
| 2280 LocationSummary* locs = |
| 2281 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2282 locs->set_in(0, Location::RegisterOrSmiConstant(length())); |
| 2283 locs->set_in(1, Location::RegisterOrSmiConstant(index())); |
| 2284 return locs; |
| 2070 } | 2285 } |
| 2071 | 2286 |
| 2072 | 2287 |
| 2073 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2288 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2074 UNIMPLEMENTED(); | 2289 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2290 kDeoptCheckArrayBound); |
| 2291 if (locs()->in(0).IsConstant() && locs()->in(1).IsConstant()) { |
| 2292 // Unconditionally deoptimize for constant bounds checks because they |
| 2293 // only occur only when index is out-of-bounds. |
| 2294 __ b(deopt); |
| 2295 return; |
| 2296 } |
| 2297 |
| 2298 if (locs()->in(1).IsConstant()) { |
| 2299 Register length = locs()->in(0).reg(); |
| 2300 const Object& constant = locs()->in(1).constant(); |
| 2301 ASSERT(constant.IsSmi()); |
| 2302 __ BranchLessEqual(length, reinterpret_cast<int32_t>(constant.raw()), |
| 2303 deopt); |
| 2304 } else if (locs()->in(0).IsConstant()) { |
| 2305 ASSERT(locs()->in(0).constant().IsSmi()); |
| 2306 const Smi& smi_const = Smi::Cast(locs()->in(0).constant()); |
| 2307 Register index = locs()->in(1).reg(); |
| 2308 __ BranchGreaterEqual(index, reinterpret_cast<int32_t>(smi_const.raw()), |
| 2309 deopt); |
| 2310 } else { |
| 2311 Register length = locs()->in(0).reg(); |
| 2312 Register index = locs()->in(1).reg(); |
| 2313 __ BranchGreaterEqual(index, length, deopt); |
| 2314 } |
| 2075 } | 2315 } |
| 2076 | 2316 |
| 2077 | 2317 |
| 2078 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { | 2318 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const { |
| 2079 UNIMPLEMENTED(); | 2319 UNIMPLEMENTED(); |
| 2080 return NULL; | 2320 return NULL; |
| 2081 } | 2321 } |
| 2082 | 2322 |
| 2083 | 2323 |
| 2084 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2324 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2452 &label, | 2692 &label, |
| 2453 PcDescriptors::kOther, | 2693 PcDescriptors::kOther, |
| 2454 locs()); | 2694 locs()); |
| 2455 __ Drop(2); // Discard type arguments and receiver. | 2695 __ Drop(2); // Discard type arguments and receiver. |
| 2456 } | 2696 } |
| 2457 | 2697 |
| 2458 } // namespace dart | 2698 } // namespace dart |
| 2459 | 2699 |
| 2460 #endif // defined TARGET_ARCH_MIPS | 2700 #endif // defined TARGET_ARCH_MIPS |
| 2461 | 2701 |
| OLD | NEW |