OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1984 __ Integer32ToSmi(second, smi_result); | 1984 __ Integer32ToSmi(second, smi_result); |
1985 if (on_success != NULL) { | 1985 if (on_success != NULL) { |
1986 __ jmp(on_success); | 1986 __ jmp(on_success); |
1987 } else { | 1987 } else { |
1988 __ bind(&done); | 1988 __ bind(&done); |
1989 } | 1989 } |
1990 } | 1990 } |
1991 | 1991 |
1992 | 1992 |
1993 void MathPowStub::Generate(MacroAssembler* masm) { | 1993 void MathPowStub::Generate(MacroAssembler* masm) { |
1994 // Registers are used as follows: | 1994 // Choose register conforming to calling convention (when bailing out). |
1995 // rdx = base | 1995 #ifdef _WIN64 |
1996 // rax = exponent | 1996 const Register exponent = rdx; |
1997 // rcx = temporary, result | 1997 #else |
1998 | 1998 const Register exponent = rdi; |
1999 Label allocate_return, call_runtime; | 1999 #endif |
2000 | 2000 const Register base = rax; |
2001 // Load input parameters. | 2001 const Register scratch = rcx; |
2002 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2002 const XMMRegister double_result = xmm3; |
2003 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 2003 const XMMRegister double_base = xmm2; |
2004 | 2004 const XMMRegister double_exponent = xmm1; |
2005 // Save 1 in xmm3 - we need this several times later on. | 2005 const XMMRegister double_scratch = xmm4; |
2006 __ Set(rcx, 1); | 2006 |
2007 __ cvtlsi2sd(xmm3, rcx); | 2007 Label double_int_runtime, generic_runtime, done; |
2008 | 2008 Label exponent_not_smi, int_exponent; |
2009 Label exponent_nonsmi; | 2009 |
2010 Label base_nonsmi; | 2010 // Save 1 in double_result - we need this several times later on. |
2011 // If the exponent is a heap number go to that specific case. | 2011 __ mov(scratch, Immediate(1)); |
2012 __ JumpIfNotSmi(rax, &exponent_nonsmi); | 2012 __ cvtlsi2sd(double_result, scratch); |
2013 __ JumpIfNotSmi(rdx, &base_nonsmi); | 2013 |
2014 | 2014 if (exponent_type_ == ON_STACK) { |
2015 // Optimized version when both exponent and base are smis. | 2015 Label base_is_smi, unpack_exponent; |
2016 Label powi; | 2016 // The exponent and base are supplied as arguments on the stack. |
2017 __ SmiToInteger32(rdx, rdx); | 2017 // This can only happen if the stub is called from non-optimized code. |
2018 __ cvtlsi2sd(xmm0, rdx); | 2018 // Load input parameters from stack. |
2019 __ jmp(&powi); | 2019 __ movq(base, Operand(rsp, 2 * kPointerSize)); |
2020 // Exponent is a smi and base is a heapnumber. | 2020 __ movq(exponent, Operand(rsp, 1 * kPointerSize)); |
2021 __ bind(&base_nonsmi); | 2021 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
2022 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset), | 2022 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), |
2023 Heap::kHeapNumberMapRootIndex); | 2023 Heap::kHeapNumberMapRootIndex); |
2024 __ j(not_equal, &call_runtime); | 2024 __ j(not_equal, &generic_runtime); |
2025 | 2025 |
2026 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | 2026 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
2027 | 2027 __ jmp(&unpack_exponent, Label::kNear); |
2028 // Optimized version of pow if exponent is a smi. | 2028 |
2029 // xmm0 contains the base. | 2029 __ bind(&base_is_smi); |
2030 __ bind(&powi); | 2030 __ SmiToInteger32(base, base); |
2031 __ SmiToInteger32(rax, rax); | 2031 __ cvtlsi2sd(double_base, base); |
2032 | 2032 __ bind(&unpack_exponent); |
2033 // Save exponent in base as we need to check if exponent is negative later. | 2033 |
2034 // We know that base and exponent are in different registers. | 2034 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
2035 __ movq(rdx, rax); | 2035 __ SmiToInteger32(exponent, exponent); |
| 2036 __ jmp(&int_exponent); |
| 2037 |
| 2038 __ bind(&exponent_not_smi); |
| 2039 __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset), |
| 2040 Heap::kHeapNumberMapRootIndex); |
| 2041 __ j(not_equal, &generic_runtime); |
| 2042 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); |
| 2043 } else if (exponent_type_ == TAGGED) { |
| 2044 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
| 2045 __ SmiToInteger32(exponent, exponent); |
| 2046 __ jmp(&int_exponent); |
| 2047 |
| 2048 __ bind(&exponent_not_smi); |
| 2049 __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset)); |
| 2050 } |
| 2051 |
| 2052 if (exponent_type_ != INTEGER) { |
| 2053 Label fast_power; |
| 2054 // Detect integer exponents stored as double. |
| 2055 __ cvttsd2si(exponent, double_exponent); |
| 2056 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
| 2057 __ cmpl(exponent, Immediate(0x80000000u)); |
| 2058 __ j(equal, &generic_runtime); |
| 2059 __ cvtlsi2sd(double_scratch, exponent); |
| 2060 // Already ruled out NaNs for exponent. |
| 2061 __ ucomisd(double_exponent, double_scratch); |
| 2062 __ j(equal, &int_exponent); |
| 2063 |
| 2064 if (exponent_type_ == ON_STACK) { |
| 2065 // Detect square root case. Crankshaft detects constant +/-0.5 at |
| 2066 // compile time and uses DoMathPowHalf instead. We then skip this check |
| 2067 // for non-constant cases of +/-0.5 as these hardly occur. |
| 2068 Label continue_sqrt, continue_rsqrt, not_plus_half; |
| 2069 // Test for 0.5. |
| 2070 // Load double_scratch with 0.5. |
| 2071 __ movq(scratch, V8_UINT64_C(0x3FE0000000000000), RelocInfo::NONE); |
| 2072 __ movq(double_scratch, scratch); |
| 2073 // Already ruled out NaNs for exponent. |
| 2074 __ ucomisd(double_scratch, double_exponent); |
| 2075 __ j(not_equal, ¬_plus_half, Label::kNear); |
| 2076 |
| 2077 // Calculates square root of base. Check for the special case of |
| 2078 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). |
| 2079 // According to IEEE-754, double-precision -Infinity has the highest |
| 2080 // 12 bits set and the lowest 52 bits cleared. |
| 2081 __ movq(scratch, V8_UINT64_C(0xFFF0000000000000), RelocInfo::NONE); |
| 2082 __ movq(double_scratch, scratch); |
| 2083 __ ucomisd(double_scratch, double_base); |
| 2084 // Comparing -Infinity with NaN results in "unordered", which sets the |
| 2085 // zero flag as if both were equal. However, it also sets the carry flag. |
| 2086 __ j(not_equal, &continue_sqrt, Label::kNear); |
| 2087 __ j(carry, &continue_sqrt, Label::kNear); |
| 2088 |
| 2089 // Set result to Infinity in the special case. |
| 2090 __ xorps(double_result, double_result); |
| 2091 __ subsd(double_result, double_scratch); |
| 2092 __ jmp(&done); |
| 2093 |
| 2094 __ bind(&continue_sqrt); |
| 2095 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 2096 __ xorps(double_scratch, double_scratch); |
| 2097 __ addsd(double_scratch, double_base); // Convert -0 to 0. |
| 2098 __ sqrtsd(double_result, double_scratch); |
| 2099 __ jmp(&done); |
| 2100 |
| 2101 // Test for -0.5. |
| 2102 __ bind(¬_plus_half); |
| 2103 // Load double_scratch with -0.5 by substracting 1. |
| 2104 __ subsd(double_scratch, double_result); |
| 2105 // Already ruled out NaNs for exponent. |
| 2106 __ ucomisd(double_scratch, double_exponent); |
| 2107 __ j(not_equal, &fast_power, Label::kNear); |
| 2108 |
| 2109 // Calculates reciprocal of square root of base. Check for the special |
| 2110 // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). |
| 2111 // According to IEEE-754, double-precision -Infinity has the highest |
| 2112 // 12 bits set and the lowest 52 bits cleared. |
| 2113 __ movq(scratch, V8_UINT64_C(0xFFF0000000000000), RelocInfo::NONE); |
| 2114 __ movq(double_scratch, scratch); |
| 2115 __ ucomisd(double_scratch, double_base); |
| 2116 // Comparing -Infinity with NaN results in "unordered", which sets the |
| 2117 // zero flag as if both were equal. However, it also sets the carry flag. |
| 2118 __ j(not_equal, &continue_rsqrt, Label::kNear); |
| 2119 __ j(carry, &continue_rsqrt, Label::kNear); |
| 2120 |
| 2121 // Set result to 0 in the special case. |
| 2122 __ xorps(double_result, double_result); |
| 2123 __ jmp(&done); |
| 2124 |
| 2125 __ bind(&continue_rsqrt); |
| 2126 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 2127 __ xorps(double_exponent, double_exponent); |
| 2128 __ addsd(double_exponent, double_base); // Convert -0 to +0. |
| 2129 __ sqrtsd(double_exponent, double_exponent); |
| 2130 __ divsd(double_result, double_exponent); |
| 2131 __ jmp(&done); |
| 2132 } |
| 2133 |
| 2134 // Using FPU instructions to calculate power. |
| 2135 Label fast_power_failed; |
| 2136 __ bind(&fast_power); |
| 2137 __ fnclex(); // Clear flags to catch exceptions later. |
| 2138 // Transfer (B)ase and (E)xponent onto the FPU register stack. |
| 2139 __ subq(rsp, Immediate(kDoubleSize)); |
| 2140 __ movsd(Operand(rsp, 0), double_exponent); |
| 2141 __ fld_d(Operand(rsp, 0)); // E |
| 2142 __ movsd(Operand(rsp, 0), double_base); |
| 2143 __ fld_d(Operand(rsp, 0)); // B, E |
| 2144 |
| 2145 // Exponent is in st(1) and base is in st(0) |
| 2146 // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B) |
| 2147 // FYL2X calculates st(1) * log2(st(0)) |
| 2148 __ fyl2x(); // X |
| 2149 __ fld(0); // X, X |
| 2150 __ frndint(); // rnd(X), X |
| 2151 __ fsub(1); // rnd(X), X-rnd(X) |
| 2152 __ fxch(1); // X - rnd(X), rnd(X) |
| 2153 // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1 |
| 2154 __ f2xm1(); // 2^(X-rnd(X)) - 1, rnd(X) |
| 2155 __ fld1(); // 1, 2^(X-rnd(X)) - 1, rnd(X) |
| 2156 __ faddp(1); // 1, 2^(X-rnd(X)), rnd(X) |
| 2157 // FSCALE calculates st(0) * 2^st(1) |
| 2158 __ fscale(); // 2^X, rnd(X) |
| 2159 __ fstp(1); |
| 2160 // Bail out to runtime in case of exceptions in the status word. |
| 2161 __ fnstsw_ax(); |
| 2162 __ testb(rax, Immediate(0x5F)); // Check for all but precision exception. |
| 2163 __ j(not_zero, &fast_power_failed, Label::kNear); |
| 2164 __ fstp_d(Operand(rsp, 0)); |
| 2165 __ movsd(double_result, Operand(rsp, 0)); |
| 2166 __ addq(rsp, Immediate(kDoubleSize)); |
| 2167 __ jmp(&done); |
| 2168 |
| 2169 __ bind(&fast_power_failed); |
| 2170 __ fninit(); |
| 2171 __ addq(rsp, Immediate(kDoubleSize)); |
| 2172 __ jmp(&generic_runtime); |
| 2173 } |
| 2174 |
| 2175 // Calculate power with integer exponent. |
| 2176 __ bind(&int_exponent); |
| 2177 const XMMRegister double_scratch2 = double_exponent; |
| 2178 // Back up exponent as we need to check if exponent is negative later. |
| 2179 __ movq(scratch, exponent); // Back up exponent. |
| 2180 __ movsd(double_scratch, double_base); // Back up base. |
| 2181 __ movsd(double_scratch2, double_result); // Load double_exponent with 1. |
2036 | 2182 |
2037 // Get absolute value of exponent. | 2183 // Get absolute value of exponent. |
2038 Label no_neg; | 2184 Label no_neg, while_true, no_multiply; |
2039 __ cmpl(rax, Immediate(0)); | 2185 __ cmpl(scratch, Immediate(0)); |
2040 __ j(greater_equal, &no_neg, Label::kNear); | 2186 __ j(positive, &no_neg, Label::kNear); |
2041 __ negl(rax); | 2187 __ negl(scratch); |
2042 __ bind(&no_neg); | 2188 __ bind(&no_neg); |
2043 | 2189 |
2044 // Load xmm1 with 1. | |
2045 __ movaps(xmm1, xmm3); | |
2046 Label while_true; | |
2047 Label no_multiply; | |
2048 | |
2049 __ bind(&while_true); | 2190 __ bind(&while_true); |
2050 __ shrl(rax, Immediate(1)); | 2191 __ shrl(scratch, Immediate(1)); |
2051 __ j(not_carry, &no_multiply, Label::kNear); | 2192 __ j(not_carry, &no_multiply, Label::kNear); |
2052 __ mulsd(xmm1, xmm0); | 2193 __ mulsd(double_result, double_scratch); |
2053 __ bind(&no_multiply); | 2194 __ bind(&no_multiply); |
2054 __ mulsd(xmm0, xmm0); | 2195 |
| 2196 __ mulsd(double_scratch, double_scratch); |
2055 __ j(not_zero, &while_true); | 2197 __ j(not_zero, &while_true); |
2056 | 2198 |
2057 // Base has the original value of the exponent - if the exponent is | 2199 // scratch has the original value of the exponent - if the exponent is |
2058 // negative return 1/result. | 2200 // negative, return 1/result. |
2059 __ testl(rdx, rdx); | 2201 __ testl(exponent, exponent); |
2060 __ j(positive, &allocate_return); | 2202 __ j(greater, &done); |
2061 // Special case if xmm1 has reached infinity. | 2203 __ divsd(double_scratch2, double_result); |
2062 __ divsd(xmm3, xmm1); | 2204 __ movsd(double_result, double_scratch2); |
2063 __ movaps(xmm1, xmm3); | 2205 // Test whether result is zero. Bail out to check for subnormal result. |
2064 __ xorps(xmm0, xmm0); | 2206 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
2065 __ ucomisd(xmm0, xmm1); | 2207 __ xorps(double_scratch2, double_scratch2); |
2066 __ j(equal, &call_runtime); | 2208 __ ucomisd(double_scratch2, double_result); |
2067 | 2209 __ j(equal, &double_int_runtime); |
2068 __ jmp(&allocate_return); | 2210 |
2069 | 2211 // Returning or bailing out. |
2070 // Exponent (or both) is a heapnumber - no matter what we should now work | 2212 if (exponent_type_ == ON_STACK) { |
2071 // on doubles. | 2213 // The stub is called from non-optimized code, which expects the result |
2072 __ bind(&exponent_nonsmi); | 2214 // as heap number in eax. |
2073 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | 2215 __ bind(&done); |
2074 Heap::kHeapNumberMapRootIndex); | 2216 __ AllocateHeapNumber(rax, rcx, &generic_runtime); |
2075 __ j(not_equal, &call_runtime); | 2217 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result); |
2076 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | 2218 __ ret(2 * kPointerSize); |
2077 // Test if exponent is nan. | 2219 |
2078 __ ucomisd(xmm1, xmm1); | 2220 // The arguments are still on the stack. |
2079 __ j(parity_even, &call_runtime); | 2221 __ bind(&generic_runtime); |
2080 | 2222 __ bind(&double_int_runtime); |
2081 Label base_not_smi, handle_special_cases; | 2223 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
2082 __ JumpIfNotSmi(rdx, &base_not_smi, Label::kNear); | 2224 } else { |
2083 __ SmiToInteger32(rdx, rdx); | 2225 __ jmp(&done); |
2084 __ cvtlsi2sd(xmm0, rdx); | 2226 |
2085 __ jmp(&handle_special_cases, Label::kNear); | 2227 Label return_from_runtime; |
2086 | 2228 StubRuntimeCallHelper callhelper; |
2087 __ bind(&base_not_smi); | 2229 __ bind(&generic_runtime); |
2088 __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset), | 2230 // Move base to the correct argument register. Exponent is already in xmm1. |
2089 Heap::kHeapNumberMapRootIndex); | 2231 __ movsd(xmm0, double_base); |
2090 __ j(not_equal, &call_runtime); | 2232 ASSERT(exponent.is(xmm1)); |
2091 __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset)); | 2233 { |
2092 __ andl(rcx, Immediate(HeapNumber::kExponentMask)); | 2234 AllowExternalCallThatCantCauseGC scope(masm); |
2093 __ cmpl(rcx, Immediate(HeapNumber::kExponentMask)); | 2235 __ PrepareCallCFunction(2); |
2094 // base is NaN or +/-Infinity | 2236 __ CallCFunction( |
2095 __ j(greater_equal, &call_runtime); | 2237 ExternalReference::power_double_double_function(masm->isolate()), 2); |
2096 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | 2238 } |
2097 | 2239 __ jmp(&return_from_runtime, Label::kNear); |
2098 // base is in xmm0 and exponent is in xmm1. | 2240 |
2099 __ bind(&handle_special_cases); | 2241 __ bind(&double_int_runtime); |
2100 Label not_minus_half; | 2242 // Move base to the correct argument register. |
2101 // Test for -0.5. | 2243 __ movsd(xmm0, double_base); |
2102 // Load xmm2 with -0.5. | 2244 // Exponent is already in the correct argument register: |
2103 __ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE); | 2245 // edi (not rdi) on Linux and edx on Windows. |
2104 __ movq(xmm2, rcx); | 2246 { |
2105 // xmm2 now has -0.5. | 2247 AllowExternalCallThatCantCauseGC scope(masm); |
2106 __ ucomisd(xmm2, xmm1); | 2248 __ PrepareCallCFunction(2); |
2107 __ j(not_equal, ¬_minus_half, Label::kNear); | 2249 __ CallCFunction( |
2108 | 2250 ExternalReference::power_double_int_function(masm->isolate()), 2); |
2109 // Calculates reciprocal of square root. | 2251 } |
2110 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | 2252 |
2111 __ xorps(xmm1, xmm1); | 2253 __ bind(&return_from_runtime); |
2112 __ addsd(xmm1, xmm0); | 2254 // Return value is in xmm0. |
2113 __ sqrtsd(xmm1, xmm1); | 2255 __ movsd(double_result, xmm0); |
2114 __ divsd(xmm3, xmm1); | 2256 // Restore context register. |
2115 __ movaps(xmm1, xmm3); | 2257 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2116 __ jmp(&allocate_return); | 2258 |
2117 | 2259 __ bind(&done); |
2118 // Test for 0.5. | 2260 __ ret(0); |
2119 __ bind(¬_minus_half); | 2261 } |
2120 // Load xmm2 with 0.5. | |
2121 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3. | |
2122 __ addsd(xmm2, xmm3); | |
2123 // xmm2 now has 0.5. | |
2124 __ ucomisd(xmm2, xmm1); | |
2125 __ j(not_equal, &call_runtime); | |
2126 // Calculates square root. | |
2127 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | |
2128 __ xorps(xmm1, xmm1); | |
2129 __ addsd(xmm1, xmm0); // Convert -0 to 0. | |
2130 __ sqrtsd(xmm1, xmm1); | |
2131 | |
2132 __ bind(&allocate_return); | |
2133 __ AllocateHeapNumber(rcx, rax, &call_runtime); | |
2134 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm1); | |
2135 __ movq(rax, rcx); | |
2136 __ ret(2 * kPointerSize); | |
2137 | |
2138 __ bind(&call_runtime); | |
2139 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | |
2140 } | 2262 } |
2141 | 2263 |
2142 | 2264 |
2143 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 2265 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
2144 // The key is in rdx and the parameter count is in rax. | 2266 // The key is in rdx and the parameter count is in rax. |
2145 | 2267 |
2146 // The displacement is used for skipping the frame pointer on the | 2268 // The displacement is used for skipping the frame pointer on the |
2147 // stack. It is the offset of the last parameter (if any) relative | 2269 // stack. It is the offset of the last parameter (if any) relative |
2148 // to the frame pointer. | 2270 // to the frame pointer. |
2149 static const int kDisplacement = 1 * kPointerSize; | 2271 static const int kDisplacement = 1 * kPointerSize; |
(...skipping 3943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6093 xmm0, | 6215 xmm0, |
6094 &slow_elements); | 6216 &slow_elements); |
6095 __ ret(0); | 6217 __ ret(0); |
6096 } | 6218 } |
6097 | 6219 |
6098 #undef __ | 6220 #undef __ |
6099 | 6221 |
6100 } } // namespace v8::internal | 6222 } } // namespace v8::internal |
6101 | 6223 |
6102 #endif // V8_TARGET_ARCH_X64 | 6224 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |