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 |