| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 operand->IsUsedAtStart()); | 84 operand->IsUsedAtStart()); |
| 85 } | 85 } |
| 86 for (TempIterator it(this); !it.Done(); it.Advance()) { | 86 for (TempIterator it(this); !it.Done(); it.Advance()) { |
| 87 LUnallocated* operand = LUnallocated::cast(it.Current()); | 87 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 88 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); | 88 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 #endif | 91 #endif |
| 92 | 92 |
| 93 | 93 |
| 94 bool LInstruction::HasDoubleRegisterResult() { |
| 95 return HasResult() && result()->IsDoubleRegister(); |
| 96 } |
| 97 |
| 98 |
| 99 bool LInstruction::HasDoubleRegisterInput() { |
| 100 for (int i = 0; i < InputCount(); i++) { |
| 101 LOperand* op = InputAt(i); |
| 102 if (op->IsDoubleRegister()) { |
| 103 return true; |
| 104 } |
| 105 } |
| 106 return false; |
| 107 } |
| 108 |
| 109 |
| 94 void LInstruction::PrintTo(StringStream* stream) { | 110 void LInstruction::PrintTo(StringStream* stream) { |
| 95 stream->Add("%s ", this->Mnemonic()); | 111 stream->Add("%s ", this->Mnemonic()); |
| 96 | 112 |
| 97 PrintOutputOperandTo(stream); | 113 PrintOutputOperandTo(stream); |
| 98 | 114 |
| 99 PrintDataTo(stream); | 115 PrintDataTo(stream); |
| 100 | 116 |
| 101 if (HasEnvironment()) { | 117 if (HasEnvironment()) { |
| 102 stream->Add(" "); | 118 stream->Add(" "); |
| 103 environment()->PrintTo(stream); | 119 environment()->PrintTo(stream); |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) { | 551 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) { |
| 536 return Use(value, ToUnallocated(fixed_register)); | 552 return Use(value, ToUnallocated(fixed_register)); |
| 537 } | 553 } |
| 538 | 554 |
| 539 | 555 |
| 540 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) { | 556 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) { |
| 541 return Use(value, ToUnallocated(reg)); | 557 return Use(value, ToUnallocated(reg)); |
| 542 } | 558 } |
| 543 | 559 |
| 544 | 560 |
| 561 LOperand* LChunkBuilder::UseX87TopOfStack(HValue* value) { |
| 562 return Use(value, ToUnallocated(x87tos)); |
| 563 } |
| 564 |
| 565 |
| 545 LOperand* LChunkBuilder::UseRegister(HValue* value) { | 566 LOperand* LChunkBuilder::UseRegister(HValue* value) { |
| 546 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 567 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
| 547 } | 568 } |
| 548 | 569 |
| 549 | 570 |
| 550 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { | 571 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { |
| 551 return Use(value, | 572 return Use(value, |
| 552 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, | 573 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, |
| 553 LUnallocated::USED_AT_START)); | 574 LUnallocated::USED_AT_START)); |
| 554 } | 575 } |
| (...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1854 // building a stack frame. | 1875 // building a stack frame. |
| 1855 if (from.IsTagged()) { | 1876 if (from.IsTagged()) { |
| 1856 if (to.IsDouble()) { | 1877 if (to.IsDouble()) { |
| 1857 info()->MarkAsDeferredCalling(); | 1878 info()->MarkAsDeferredCalling(); |
| 1858 LOperand* value = UseRegister(instr->value()); | 1879 LOperand* value = UseRegister(instr->value()); |
| 1859 // Temp register only necessary for minus zero check. | 1880 // Temp register only necessary for minus zero check. |
| 1860 LOperand* temp = instr->deoptimize_on_minus_zero() | 1881 LOperand* temp = instr->deoptimize_on_minus_zero() |
| 1861 ? TempRegister() | 1882 ? TempRegister() |
| 1862 : NULL; | 1883 : NULL; |
| 1863 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); | 1884 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); |
| 1864 return AssignEnvironment(DefineAsRegister(res)); | 1885 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 1886 return AssignEnvironment(DefineAsRegister(res)); |
| 1887 } else { |
| 1888 return AssignEnvironment(DefineX87TOS(res)); |
| 1889 } |
| 1865 } else { | 1890 } else { |
| 1866 ASSERT(to.IsInteger32()); | 1891 ASSERT(to.IsInteger32()); |
| 1867 LOperand* value = UseRegister(instr->value()); | |
| 1868 if (instr->value()->type().IsSmi()) { | 1892 if (instr->value()->type().IsSmi()) { |
| 1893 LOperand* value = UseRegister(instr->value()); |
| 1869 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); | 1894 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); |
| 1870 } else { | 1895 } else { |
| 1871 bool truncating = instr->CanTruncateToInt32(); | 1896 bool truncating = instr->CanTruncateToInt32(); |
| 1872 LOperand* xmm_temp = | 1897 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 1873 (truncating && CpuFeatures::IsSupported(SSE3)) | 1898 LOperand* value = UseRegister(instr->value()); |
| 1874 ? NULL | 1899 LOperand* xmm_temp = |
| 1875 : FixedTemp(xmm1); | 1900 (truncating && CpuFeatures::IsSupported(SSE3)) |
| 1876 LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp); | 1901 ? NULL |
| 1877 return AssignEnvironment(DefineSameAsFirst(res)); | 1902 : FixedTemp(xmm1); |
| 1903 LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp); |
| 1904 return AssignEnvironment(DefineSameAsFirst(res)); |
| 1905 } else { |
| 1906 LOperand* value = UseFixed(instr->value(), ecx); |
| 1907 LTaggedToINoSSE2* res = |
| 1908 new(zone()) LTaggedToINoSSE2(value, TempRegister(), |
| 1909 TempRegister(), TempRegister()); |
| 1910 return AssignEnvironment(DefineFixed(res, ecx)); |
| 1911 } |
| 1878 } | 1912 } |
| 1879 } | 1913 } |
| 1880 } else if (from.IsDouble()) { | 1914 } else if (from.IsDouble()) { |
| 1881 if (to.IsTagged()) { | 1915 if (to.IsTagged()) { |
| 1882 info()->MarkAsDeferredCalling(); | 1916 info()->MarkAsDeferredCalling(); |
| 1883 LOperand* value = CpuFeatures::IsSupported(SSE2) | 1917 LOperand* value = CpuFeatures::IsSupported(SSE2) |
| 1884 ? UseRegisterAtStart(instr->value()) | 1918 ? UseRegisterAtStart(instr->value()) |
| 1885 : UseAtStart(instr->value()); | 1919 : UseAtStart(instr->value()); |
| 1886 LOperand* temp = FLAG_inline_new ? TempRegister() : NULL; | 1920 LOperand* temp = FLAG_inline_new ? TempRegister() : NULL; |
| 1887 | 1921 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 HValue* value = instr->value(); | 2019 HValue* value = instr->value(); |
| 1986 Representation input_rep = value->representation(); | 2020 Representation input_rep = value->representation(); |
| 1987 if (input_rep.IsDouble()) { | 2021 if (input_rep.IsDouble()) { |
| 1988 LOperand* reg = UseRegister(value); | 2022 LOperand* reg = UseRegister(value); |
| 1989 return DefineFixed(new(zone()) LClampDToUint8(reg), eax); | 2023 return DefineFixed(new(zone()) LClampDToUint8(reg), eax); |
| 1990 } else if (input_rep.IsInteger32()) { | 2024 } else if (input_rep.IsInteger32()) { |
| 1991 LOperand* reg = UseFixed(value, eax); | 2025 LOperand* reg = UseFixed(value, eax); |
| 1992 return DefineFixed(new(zone()) LClampIToUint8(reg), eax); | 2026 return DefineFixed(new(zone()) LClampIToUint8(reg), eax); |
| 1993 } else { | 2027 } else { |
| 1994 ASSERT(input_rep.IsTagged()); | 2028 ASSERT(input_rep.IsTagged()); |
| 1995 LOperand* reg = UseFixed(value, eax); | 2029 if (CpuFeatures::IsSupported(SSE2)) { |
| 1996 // Register allocator doesn't (yet) support allocation of double | 2030 LOperand* reg = UseFixed(value, eax); |
| 1997 // temps. Reserve xmm1 explicitly. | 2031 // Register allocator doesn't (yet) support allocation of double |
| 1998 LOperand* temp = FixedTemp(xmm1); | 2032 // temps. Reserve xmm1 explicitly. |
| 1999 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, temp); | 2033 LOperand* temp = FixedTemp(xmm1); |
| 2000 return AssignEnvironment(DefineFixed(result, eax)); | 2034 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, temp); |
| 2035 return AssignEnvironment(DefineFixed(result, eax)); |
| 2036 } else { |
| 2037 LOperand* value = UseRegister(instr->value()); |
| 2038 LClampTToUint8NoSSE2* res = |
| 2039 new(zone()) LClampTToUint8NoSSE2(value, TempRegister(), |
| 2040 TempRegister(), TempRegister()); |
| 2041 return AssignEnvironment(DefineFixed(res, ecx)); |
| 2042 } |
| 2001 } | 2043 } |
| 2002 } | 2044 } |
| 2003 | 2045 |
| 2004 | 2046 |
| 2005 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 2047 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 2006 LOperand* context = info()->IsStub() | 2048 LOperand* context = info()->IsStub() |
| 2007 ? UseFixed(instr->context(), esi) | 2049 ? UseFixed(instr->context(), esi) |
| 2008 : NULL; | 2050 : NULL; |
| 2009 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); | 2051 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); |
| 2010 return new(zone()) LReturn(UseFixed(instr->value(), eax), context, | 2052 return new(zone()) LReturn(UseFixed(instr->value(), eax), context, |
| 2011 parameter_count); | 2053 parameter_count); |
| 2012 } | 2054 } |
| 2013 | 2055 |
| 2014 | 2056 |
| 2015 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 2057 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 2016 Representation r = instr->representation(); | 2058 Representation r = instr->representation(); |
| 2017 if (r.IsInteger32()) { | 2059 if (r.IsInteger32()) { |
| 2018 return DefineAsRegister(new(zone()) LConstantI); | 2060 return DefineAsRegister(new(zone()) LConstantI); |
| 2019 } else if (r.IsDouble()) { | 2061 } else if (r.IsDouble()) { |
| 2020 double value = instr->DoubleValue(); | 2062 double value = instr->DoubleValue(); |
| 2021 LOperand* temp = (BitCast<uint64_t, double>(value) != 0) | 2063 bool value_is_zero = BitCast<uint64_t, double>(value) == 0; |
| 2022 ? TempRegister() | 2064 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 2023 : NULL; | 2065 LOperand* temp = value_is_zero ? NULL : TempRegister(); |
| 2024 return DefineAsRegister(new(zone()) LConstantD(temp)); | 2066 return DefineAsRegister(new(zone()) LConstantD(temp)); |
| 2067 } else { |
| 2068 return DefineX87TOS(new(zone()) LConstantD(NULL)); |
| 2069 } |
| 2025 } else if (r.IsTagged()) { | 2070 } else if (r.IsTagged()) { |
| 2026 return DefineAsRegister(new(zone()) LConstantT); | 2071 return DefineAsRegister(new(zone()) LConstantT); |
| 2027 } else { | 2072 } else { |
| 2028 UNREACHABLE(); | 2073 UNREACHABLE(); |
| 2029 return NULL; | 2074 return NULL; |
| 2030 } | 2075 } |
| 2031 } | 2076 } |
| 2032 | 2077 |
| 2033 | 2078 |
| 2034 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) { | 2079 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2183 LOperand* context = UseFixed(instr->context(), esi); | 2228 LOperand* context = UseFixed(instr->context(), esi); |
| 2184 LOperand* object = UseFixed(instr->object(), edx); | 2229 LOperand* object = UseFixed(instr->object(), edx); |
| 2185 LOperand* key = UseFixed(instr->key(), ecx); | 2230 LOperand* key = UseFixed(instr->key(), ecx); |
| 2186 | 2231 |
| 2187 LLoadKeyedGeneric* result = | 2232 LLoadKeyedGeneric* result = |
| 2188 new(zone()) LLoadKeyedGeneric(context, object, key); | 2233 new(zone()) LLoadKeyedGeneric(context, object, key); |
| 2189 return MarkAsCall(DefineFixed(result, eax), instr); | 2234 return MarkAsCall(DefineFixed(result, eax), instr); |
| 2190 } | 2235 } |
| 2191 | 2236 |
| 2192 | 2237 |
| 2238 LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) { |
| 2239 ElementsKind elements_kind = instr->elements_kind(); |
| 2240 |
| 2241 // Determine if we need a byte register in this case for the value. |
| 2242 bool val_is_fixed_register = |
| 2243 elements_kind == EXTERNAL_BYTE_ELEMENTS || |
| 2244 elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || |
| 2245 elements_kind == EXTERNAL_PIXEL_ELEMENTS; |
| 2246 if (val_is_fixed_register) { |
| 2247 return UseFixed(instr->value(), eax); |
| 2248 } |
| 2249 |
| 2250 if (!CpuFeatures::IsSafeForSnapshot(SSE2) && |
| 2251 IsDoubleOrFloatElementsKind(elements_kind)) { |
| 2252 return UseRegisterAtStart(instr->value()); |
| 2253 } |
| 2254 |
| 2255 return UseRegister(instr->value()); |
| 2256 } |
| 2257 |
| 2258 |
| 2193 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { | 2259 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
| 2194 if (!instr->is_external()) { | 2260 if (!instr->is_external()) { |
| 2195 ASSERT(instr->elements()->representation().IsTagged()); | 2261 ASSERT(instr->elements()->representation().IsTagged()); |
| 2196 ASSERT(instr->key()->representation().IsInteger32() || | 2262 ASSERT(instr->key()->representation().IsInteger32() || |
| 2197 instr->key()->representation().IsTagged()); | 2263 instr->key()->representation().IsTagged()); |
| 2198 | 2264 |
| 2199 if (instr->value()->representation().IsDouble()) { | 2265 if (instr->value()->representation().IsDouble()) { |
| 2200 LOperand* object = UseRegisterAtStart(instr->elements()); | 2266 LOperand* object = UseRegisterAtStart(instr->elements()); |
| 2201 LOperand* val = UseTempRegister(instr->value()); | 2267 LOperand* val = NULL; |
| 2268 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 2269 val = UseRegisterAtStart(instr->value()); |
| 2270 } else if (!instr->IsConstantHoleStore()) { |
| 2271 val = UseX87TopOfStack(instr->value()); |
| 2272 } |
| 2202 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2273 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2203 | 2274 |
| 2204 return new(zone()) LStoreKeyed(object, key, val); | 2275 return new(zone()) LStoreKeyed(object, key, val); |
| 2205 } else { | 2276 } else { |
| 2206 ASSERT(instr->value()->representation().IsTagged()); | 2277 ASSERT(instr->value()->representation().IsTagged()); |
| 2207 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2278 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 2208 | 2279 |
| 2209 LOperand* obj = UseRegister(instr->elements()); | 2280 LOperand* obj = UseRegister(instr->elements()); |
| 2210 LOperand* val = needs_write_barrier | 2281 LOperand* val = needs_write_barrier |
| 2211 ? UseTempRegister(instr->value()) | 2282 ? UseTempRegister(instr->value()) |
| 2212 : UseRegisterAtStart(instr->value()); | 2283 : UseRegisterAtStart(instr->value()); |
| 2213 LOperand* key = needs_write_barrier | 2284 LOperand* key = needs_write_barrier |
| 2214 ? UseTempRegister(instr->key()) | 2285 ? UseTempRegister(instr->key()) |
| 2215 : UseRegisterOrConstantAtStart(instr->key()); | 2286 : UseRegisterOrConstantAtStart(instr->key()); |
| 2216 return new(zone()) LStoreKeyed(obj, key, val); | 2287 return new(zone()) LStoreKeyed(obj, key, val); |
| 2217 } | 2288 } |
| 2218 } | 2289 } |
| 2219 | 2290 |
| 2220 ElementsKind elements_kind = instr->elements_kind(); | 2291 ElementsKind elements_kind = instr->elements_kind(); |
| 2221 ASSERT( | 2292 ASSERT( |
| 2222 (instr->value()->representation().IsInteger32() && | 2293 (instr->value()->representation().IsInteger32() && |
| 2223 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && | 2294 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && |
| 2224 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || | 2295 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || |
| 2225 (instr->value()->representation().IsDouble() && | 2296 (instr->value()->representation().IsDouble() && |
| 2226 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || | 2297 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || |
| 2227 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); | 2298 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); |
| 2228 ASSERT(instr->elements()->representation().IsExternal()); | 2299 ASSERT(instr->elements()->representation().IsExternal()); |
| 2229 | 2300 |
| 2230 LOperand* external_pointer = UseRegister(instr->elements()); | 2301 LOperand* external_pointer = UseRegister(instr->elements()); |
| 2231 // Determine if we need a byte register in this case for the value. | 2302 LOperand* val = GetStoreKeyedValueOperand(instr); |
| 2232 bool val_is_fixed_register = | |
| 2233 elements_kind == EXTERNAL_BYTE_ELEMENTS || | |
| 2234 elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || | |
| 2235 elements_kind == EXTERNAL_PIXEL_ELEMENTS; | |
| 2236 | |
| 2237 LOperand* val = val_is_fixed_register | |
| 2238 ? UseFixed(instr->value(), eax) | |
| 2239 : UseRegister(instr->value()); | |
| 2240 bool clobbers_key = ExternalArrayOpRequiresTemp( | 2303 bool clobbers_key = ExternalArrayOpRequiresTemp( |
| 2241 instr->key()->representation(), elements_kind); | 2304 instr->key()->representation(), elements_kind); |
| 2242 LOperand* key = clobbers_key | 2305 LOperand* key = clobbers_key |
| 2243 ? UseTempRegister(instr->key()) | 2306 ? UseTempRegister(instr->key()) |
| 2244 : UseRegisterOrConstantAtStart(instr->key()); | 2307 : UseRegisterOrConstantAtStart(instr->key()); |
| 2245 return new(zone()) LStoreKeyed(external_pointer, | 2308 return new(zone()) LStoreKeyed(external_pointer, |
| 2246 key, | 2309 key, |
| 2247 val); | 2310 val); |
| 2248 } | 2311 } |
| 2249 | 2312 |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2648 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2711 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2649 LOperand* object = UseRegister(instr->object()); | 2712 LOperand* object = UseRegister(instr->object()); |
| 2650 LOperand* index = UseTempRegister(instr->index()); | 2713 LOperand* index = UseTempRegister(instr->index()); |
| 2651 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2714 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
| 2652 } | 2715 } |
| 2653 | 2716 |
| 2654 | 2717 |
| 2655 } } // namespace v8::internal | 2718 } } // namespace v8::internal |
| 2656 | 2719 |
| 2657 #endif // V8_TARGET_ARCH_IA32 | 2720 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |