| 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 2017 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 // it. | 2028 // it. |
| 2029 GenerateJumpFunctionIgnoreReceiver(function); | 2029 GenerateJumpFunctionIgnoreReceiver(function); |
| 2030 | 2030 |
| 2031 HandlerFrontendFooter(&miss); | 2031 HandlerFrontendFooter(&miss); |
| 2032 | 2032 |
| 2033 // Return the generated code. | 2033 // Return the generated code. |
| 2034 return GetCode(type, name); | 2034 return GetCode(type, name); |
| 2035 } | 2035 } |
| 2036 | 2036 |
| 2037 | 2037 |
| 2038 Handle<Code> CallStubCompiler::CompileMathFloorCall( | |
| 2039 Handle<Object> object, | |
| 2040 Handle<JSObject> holder, | |
| 2041 Handle<Cell> cell, | |
| 2042 Handle<JSFunction> function, | |
| 2043 Handle<String> name, | |
| 2044 Code::StubType type) { | |
| 2045 if (!CpuFeatures::IsSupported(SSE2)) { | |
| 2046 return Handle<Code>::null(); | |
| 2047 } | |
| 2048 | |
| 2049 CpuFeatureScope use_sse2(masm(), SSE2); | |
| 2050 | |
| 2051 const int argc = arguments().immediate(); | |
| 2052 | |
| 2053 // If the object is not a JSObject or we got an unexpected number of | |
| 2054 // arguments, bail out to the regular call. | |
| 2055 if (!object->IsJSObject() || argc != 1) { | |
| 2056 return Handle<Code>::null(); | |
| 2057 } | |
| 2058 | |
| 2059 Label miss; | |
| 2060 | |
| 2061 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 2062 if (!cell.is_null()) { | |
| 2063 ASSERT(cell->value() == *function); | |
| 2064 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 2065 } | |
| 2066 | |
| 2067 // Load the (only) argument into eax. | |
| 2068 __ mov(eax, Operand(esp, 1 * kPointerSize)); | |
| 2069 | |
| 2070 // Check if the argument is a smi. | |
| 2071 Label smi; | |
| 2072 STATIC_ASSERT(kSmiTag == 0); | |
| 2073 __ JumpIfSmi(eax, &smi); | |
| 2074 | |
| 2075 // Check if the argument is a heap number and load its value into xmm0. | |
| 2076 Label slow; | |
| 2077 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | |
| 2078 __ movsd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | |
| 2079 | |
| 2080 // Check if the argument is strictly positive. Note this also | |
| 2081 // discards NaN. | |
| 2082 __ xorpd(xmm1, xmm1); | |
| 2083 __ ucomisd(xmm0, xmm1); | |
| 2084 __ j(below_equal, &slow); | |
| 2085 | |
| 2086 // Do a truncating conversion. | |
| 2087 __ cvttsd2si(eax, Operand(xmm0)); | |
| 2088 | |
| 2089 // Check if the result fits into a smi. Note this also checks for | |
| 2090 // 0x80000000 which signals a failed conversion. | |
| 2091 Label wont_fit_into_smi; | |
| 2092 __ test(eax, Immediate(0xc0000000)); | |
| 2093 __ j(not_zero, &wont_fit_into_smi); | |
| 2094 | |
| 2095 // Smi tag and return. | |
| 2096 __ SmiTag(eax); | |
| 2097 __ bind(&smi); | |
| 2098 __ ret(2 * kPointerSize); | |
| 2099 | |
| 2100 // Check if the argument is < 2^kMantissaBits. | |
| 2101 Label already_round; | |
| 2102 __ bind(&wont_fit_into_smi); | |
| 2103 __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits); | |
| 2104 __ ucomisd(xmm0, xmm1); | |
| 2105 __ j(above_equal, &already_round); | |
| 2106 | |
| 2107 // Save a copy of the argument. | |
| 2108 __ movaps(xmm2, xmm0); | |
| 2109 | |
| 2110 // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits. | |
| 2111 __ addsd(xmm0, xmm1); | |
| 2112 __ subsd(xmm0, xmm1); | |
| 2113 | |
| 2114 // Compare the argument and the tentative result to get the right mask: | |
| 2115 // if xmm2 < xmm0: | |
| 2116 // xmm2 = 1...1 | |
| 2117 // else: | |
| 2118 // xmm2 = 0...0 | |
| 2119 __ cmpltsd(xmm2, xmm0); | |
| 2120 | |
| 2121 // Subtract 1 if the argument was less than the tentative result. | |
| 2122 __ LoadPowerOf2(xmm1, ebx, 0); | |
| 2123 __ andpd(xmm1, xmm2); | |
| 2124 __ subsd(xmm0, xmm1); | |
| 2125 | |
| 2126 // Return a new heap number. | |
| 2127 __ AllocateHeapNumber(eax, ebx, edx, &slow); | |
| 2128 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | |
| 2129 __ ret(2 * kPointerSize); | |
| 2130 | |
| 2131 // Return the argument (when it's an already round heap number). | |
| 2132 __ bind(&already_round); | |
| 2133 __ mov(eax, Operand(esp, 1 * kPointerSize)); | |
| 2134 __ ret(2 * kPointerSize); | |
| 2135 | |
| 2136 __ bind(&slow); | |
| 2137 // We do not have to patch the receiver because the function makes no use of | |
| 2138 // it. | |
| 2139 GenerateJumpFunctionIgnoreReceiver(function); | |
| 2140 | |
| 2141 HandlerFrontendFooter(&miss); | |
| 2142 | |
| 2143 // Return the generated code. | |
| 2144 return GetCode(type, name); | |
| 2145 } | |
| 2146 | |
| 2147 | |
| 2148 Handle<Code> CallStubCompiler::CompileMathAbsCall( | |
| 2149 Handle<Object> object, | |
| 2150 Handle<JSObject> holder, | |
| 2151 Handle<Cell> cell, | |
| 2152 Handle<JSFunction> function, | |
| 2153 Handle<String> name, | |
| 2154 Code::StubType type) { | |
| 2155 const int argc = arguments().immediate(); | |
| 2156 | |
| 2157 // If the object is not a JSObject or we got an unexpected number of | |
| 2158 // arguments, bail out to the regular call. | |
| 2159 if (!object->IsJSObject() || argc != 1) { | |
| 2160 return Handle<Code>::null(); | |
| 2161 } | |
| 2162 | |
| 2163 Label miss; | |
| 2164 | |
| 2165 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 2166 if (!cell.is_null()) { | |
| 2167 ASSERT(cell->value() == *function); | |
| 2168 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 2169 } | |
| 2170 | |
| 2171 // Load the (only) argument into eax. | |
| 2172 __ mov(eax, Operand(esp, 1 * kPointerSize)); | |
| 2173 | |
| 2174 // Check if the argument is a smi. | |
| 2175 Label not_smi; | |
| 2176 STATIC_ASSERT(kSmiTag == 0); | |
| 2177 __ JumpIfNotSmi(eax, ¬_smi); | |
| 2178 | |
| 2179 // Branchless abs implementation, refer to below: | |
| 2180 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs | |
| 2181 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 | |
| 2182 // otherwise. | |
| 2183 __ mov(ebx, eax); | |
| 2184 __ sar(ebx, kBitsPerInt - 1); | |
| 2185 | |
| 2186 // Do bitwise not or do nothing depending on ebx. | |
| 2187 __ xor_(eax, ebx); | |
| 2188 | |
| 2189 // Add 1 or do nothing depending on ebx. | |
| 2190 __ sub(eax, ebx); | |
| 2191 | |
| 2192 // If the result is still negative, go to the slow case. | |
| 2193 // This only happens for the most negative smi. | |
| 2194 Label slow; | |
| 2195 __ j(negative, &slow); | |
| 2196 | |
| 2197 // Smi case done. | |
| 2198 __ ret(2 * kPointerSize); | |
| 2199 | |
| 2200 // Check if the argument is a heap number and load its exponent and | |
| 2201 // sign into ebx. | |
| 2202 __ bind(¬_smi); | |
| 2203 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | |
| 2204 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); | |
| 2205 | |
| 2206 // Check the sign of the argument. If the argument is positive, | |
| 2207 // just return it. | |
| 2208 Label negative_sign; | |
| 2209 __ test(ebx, Immediate(HeapNumber::kSignMask)); | |
| 2210 __ j(not_zero, &negative_sign); | |
| 2211 __ ret(2 * kPointerSize); | |
| 2212 | |
| 2213 // If the argument is negative, clear the sign, and return a new | |
| 2214 // number. | |
| 2215 __ bind(&negative_sign); | |
| 2216 __ and_(ebx, ~HeapNumber::kSignMask); | |
| 2217 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); | |
| 2218 __ AllocateHeapNumber(eax, edi, edx, &slow); | |
| 2219 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); | |
| 2220 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | |
| 2221 __ ret(2 * kPointerSize); | |
| 2222 | |
| 2223 __ bind(&slow); | |
| 2224 // We do not have to patch the receiver because the function makes no use of | |
| 2225 // it. | |
| 2226 GenerateJumpFunctionIgnoreReceiver(function); | |
| 2227 | |
| 2228 HandlerFrontendFooter(&miss); | |
| 2229 | |
| 2230 // Return the generated code. | |
| 2231 return GetCode(type, name); | |
| 2232 } | |
| 2233 | |
| 2234 | |
| 2235 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2038 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2236 const CallOptimization& optimization, | 2039 const CallOptimization& optimization, |
| 2237 Handle<Object> object, | 2040 Handle<Object> object, |
| 2238 Handle<JSObject> holder, | 2041 Handle<JSObject> holder, |
| 2239 Handle<Cell> cell, | 2042 Handle<Cell> cell, |
| 2240 Handle<JSFunction> function, | 2043 Handle<JSFunction> function, |
| 2241 Handle<String> name) { | 2044 Handle<String> name) { |
| 2242 ASSERT(optimization.is_simple_api_call()); | 2045 ASSERT(optimization.is_simple_api_call()); |
| 2243 // Bail out if object is a global object as we don't want to | 2046 // Bail out if object is a global object as we don't want to |
| 2244 // repatch it to global receiver. | 2047 // repatch it to global receiver. |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2826 // ----------------------------------- | 2629 // ----------------------------------- |
| 2827 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2630 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 2828 } | 2631 } |
| 2829 | 2632 |
| 2830 | 2633 |
| 2831 #undef __ | 2634 #undef __ |
| 2832 | 2635 |
| 2833 } } // namespace v8::internal | 2636 } } // namespace v8::internal |
| 2834 | 2637 |
| 2835 #endif // V8_TARGET_ARCH_IA32 | 2638 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |