| 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 1923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1934 // it. | 1934 // it. |
| 1935 GenerateJumpFunctionIgnoreReceiver(function); | 1935 GenerateJumpFunctionIgnoreReceiver(function); |
| 1936 | 1936 |
| 1937 HandlerFrontendFooter(&miss); | 1937 HandlerFrontendFooter(&miss); |
| 1938 | 1938 |
| 1939 // Return the generated code. | 1939 // Return the generated code. |
| 1940 return GetCode(type, name); | 1940 return GetCode(type, name); |
| 1941 } | 1941 } |
| 1942 | 1942 |
| 1943 | 1943 |
| 1944 Handle<Code> CallStubCompiler::CompileMathFloorCall( | |
| 1945 Handle<Object> object, | |
| 1946 Handle<JSObject> holder, | |
| 1947 Handle<Cell> cell, | |
| 1948 Handle<JSFunction> function, | |
| 1949 Handle<String> name, | |
| 1950 Code::StubType type) { | |
| 1951 const int argc = arguments().immediate(); | |
| 1952 // If the object is not a JSObject or we got an unexpected number of | |
| 1953 // arguments, bail out to the regular call. | |
| 1954 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | |
| 1955 | |
| 1956 Label miss, slow; | |
| 1957 | |
| 1958 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 1959 if (!cell.is_null()) { | |
| 1960 ASSERT(cell->value() == *function); | |
| 1961 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 1962 } | |
| 1963 | |
| 1964 // Load the (only) argument into r0. | |
| 1965 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | |
| 1966 | |
| 1967 // If the argument is a smi, just return. | |
| 1968 __ SmiTst(r0); | |
| 1969 __ Drop(argc + 1, eq); | |
| 1970 __ Ret(eq); | |
| 1971 | |
| 1972 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); | |
| 1973 | |
| 1974 Label smi_check, just_return; | |
| 1975 | |
| 1976 // Load the HeapNumber value. | |
| 1977 // We will need access to the value in the core registers, so we load it | |
| 1978 // with ldrd and move it to the fpu. It also spares a sub instruction for | |
| 1979 // updating the HeapNumber value address, as vldr expects a multiple | |
| 1980 // of 4 offset. | |
| 1981 __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset)); | |
| 1982 __ vmov(d1, r4, r5); | |
| 1983 | |
| 1984 // Check for NaN, Infinities and -0. | |
| 1985 // They are invariant through a Math.Floor call, so just | |
| 1986 // return the original argument. | |
| 1987 __ Sbfx(r3, r5, HeapNumber::kExponentShift, HeapNumber::kExponentBits); | |
| 1988 __ cmp(r3, Operand(-1)); | |
| 1989 __ b(eq, &just_return); | |
| 1990 __ eor(r3, r5, Operand(0x80000000u)); | |
| 1991 __ orr(r3, r3, r4, SetCC); | |
| 1992 __ b(eq, &just_return); | |
| 1993 // Test for values that can be exactly represented as a | |
| 1994 // signed 32-bit integer. | |
| 1995 __ TryDoubleToInt32Exact(r0, d1, d2); | |
| 1996 // If exact, check smi | |
| 1997 __ b(eq, &smi_check); | |
| 1998 __ cmp(r5, Operand(0)); | |
| 1999 | |
| 2000 // If input is in ]+0, +inf[, the cmp has cleared overflow and negative | |
| 2001 // (V=0 and N=0), the two following instructions won't execute and | |
| 2002 // we fall through smi_check to check if the result can fit into a smi. | |
| 2003 | |
| 2004 // If input is in ]-inf, -0[, sub one and, go to slow if we have | |
| 2005 // an overflow. Else we fall through smi check. | |
| 2006 // Hint: if x is a negative, non integer number, | |
| 2007 // floor(x) <=> round_to_zero(x) - 1. | |
| 2008 __ sub(r0, r0, Operand(1), SetCC, mi); | |
| 2009 __ b(vs, &slow); | |
| 2010 | |
| 2011 __ bind(&smi_check); | |
| 2012 // Check if the result can fit into an smi. If we had an overflow, | |
| 2013 // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi. | |
| 2014 // If result doesn't fit into an smi, branch to slow. | |
| 2015 __ SmiTag(r0, SetCC); | |
| 2016 __ b(vs, &slow); | |
| 2017 | |
| 2018 __ bind(&just_return); | |
| 2019 __ Drop(argc + 1); | |
| 2020 __ Ret(); | |
| 2021 | |
| 2022 __ bind(&slow); | |
| 2023 // We do not have to patch the receiver because the function makes no use of | |
| 2024 // it. | |
| 2025 GenerateJumpFunctionIgnoreReceiver(function); | |
| 2026 | |
| 2027 HandlerFrontendFooter(&miss); | |
| 2028 | |
| 2029 // Return the generated code. | |
| 2030 return GetCode(type, name); | |
| 2031 } | |
| 2032 | |
| 2033 | |
| 2034 Handle<Code> CallStubCompiler::CompileMathAbsCall( | |
| 2035 Handle<Object> object, | |
| 2036 Handle<JSObject> holder, | |
| 2037 Handle<Cell> cell, | |
| 2038 Handle<JSFunction> function, | |
| 2039 Handle<String> name, | |
| 2040 Code::StubType type) { | |
| 2041 const int argc = arguments().immediate(); | |
| 2042 // If the object is not a JSObject or we got an unexpected number of | |
| 2043 // arguments, bail out to the regular call. | |
| 2044 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | |
| 2045 | |
| 2046 Label miss; | |
| 2047 | |
| 2048 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | |
| 2049 if (!cell.is_null()) { | |
| 2050 ASSERT(cell->value() == *function); | |
| 2051 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 2052 } | |
| 2053 | |
| 2054 // Load the (only) argument into r0. | |
| 2055 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | |
| 2056 | |
| 2057 // Check if the argument is a smi. | |
| 2058 Label not_smi; | |
| 2059 __ JumpIfNotSmi(r0, ¬_smi); | |
| 2060 | |
| 2061 // Do bitwise not or do nothing depending on the sign of the | |
| 2062 // argument. | |
| 2063 __ eor(r1, r0, Operand(r0, ASR, kBitsPerInt - 1)); | |
| 2064 | |
| 2065 // Add 1 or do nothing depending on the sign of the argument. | |
| 2066 __ sub(r0, r1, Operand(r0, ASR, kBitsPerInt - 1), SetCC); | |
| 2067 | |
| 2068 // If the result is still negative, go to the slow case. | |
| 2069 // This only happens for the most negative smi. | |
| 2070 Label slow; | |
| 2071 __ b(mi, &slow); | |
| 2072 | |
| 2073 // Smi case done. | |
| 2074 __ Drop(argc + 1); | |
| 2075 __ Ret(); | |
| 2076 | |
| 2077 // Check if the argument is a heap number and load its exponent and | |
| 2078 // sign. | |
| 2079 __ bind(¬_smi); | |
| 2080 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); | |
| 2081 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | |
| 2082 | |
| 2083 // Check the sign of the argument. If the argument is positive, | |
| 2084 // just return it. | |
| 2085 Label negative_sign; | |
| 2086 __ tst(r1, Operand(HeapNumber::kSignMask)); | |
| 2087 __ b(ne, &negative_sign); | |
| 2088 __ Drop(argc + 1); | |
| 2089 __ Ret(); | |
| 2090 | |
| 2091 // If the argument is negative, clear the sign, and return a new | |
| 2092 // number. | |
| 2093 __ bind(&negative_sign); | |
| 2094 __ eor(r1, r1, Operand(HeapNumber::kSignMask)); | |
| 2095 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | |
| 2096 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); | |
| 2097 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); | |
| 2098 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | |
| 2099 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | |
| 2100 __ Drop(argc + 1); | |
| 2101 __ Ret(); | |
| 2102 | |
| 2103 __ bind(&slow); | |
| 2104 // We do not have to patch the receiver because the function makes no use of | |
| 2105 // it. | |
| 2106 GenerateJumpFunctionIgnoreReceiver(function); | |
| 2107 | |
| 2108 HandlerFrontendFooter(&miss); | |
| 2109 | |
| 2110 // Return the generated code. | |
| 2111 return GetCode(type, name); | |
| 2112 } | |
| 2113 | |
| 2114 | |
| 2115 Handle<Code> CallStubCompiler::CompileFastApiCall( | 1944 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2116 const CallOptimization& optimization, | 1945 const CallOptimization& optimization, |
| 2117 Handle<Object> object, | 1946 Handle<Object> object, |
| 2118 Handle<JSObject> holder, | 1947 Handle<JSObject> holder, |
| 2119 Handle<Cell> cell, | 1948 Handle<Cell> cell, |
| 2120 Handle<JSFunction> function, | 1949 Handle<JSFunction> function, |
| 2121 Handle<String> name) { | 1950 Handle<String> name) { |
| 2122 Counters* counters = isolate()->counters(); | 1951 Counters* counters = isolate()->counters(); |
| 2123 | 1952 |
| 2124 ASSERT(optimization.is_simple_api_call()); | 1953 ASSERT(optimization.is_simple_api_call()); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2726 // ----------------------------------- | 2555 // ----------------------------------- |
| 2727 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2556 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 2728 } | 2557 } |
| 2729 | 2558 |
| 2730 | 2559 |
| 2731 #undef __ | 2560 #undef __ |
| 2732 | 2561 |
| 2733 } } // namespace v8::internal | 2562 } } // namespace v8::internal |
| 2734 | 2563 |
| 2735 #endif // V8_TARGET_ARCH_ARM | 2564 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |