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 |