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 1964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1975 Object* obj; | 1975 Object* obj; |
1976 { MaybeObject* maybe_obj = GenerateMissBranch(); | 1976 { MaybeObject* maybe_obj = GenerateMissBranch(); |
1977 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1977 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1978 } | 1978 } |
1979 | 1979 |
1980 // Return the generated code. | 1980 // Return the generated code. |
1981 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 1981 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
1982 } | 1982 } |
1983 | 1983 |
1984 | 1984 |
| 1985 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 1986 const CallOptimization& optimization, |
| 1987 Object* object, |
| 1988 JSObject* holder, |
| 1989 JSGlobalPropertyCell* cell, |
| 1990 JSFunction* function, |
| 1991 String* name) { |
| 1992 ASSERT(optimization.is_simple_api_call()); |
| 1993 // Bail out if object is a global object as we don't want to |
| 1994 // repatch it to global receiver. |
| 1995 if (object->IsGlobalObject()) return Heap::undefined_value(); |
| 1996 if (cell != NULL) return Heap::undefined_value(); |
| 1997 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 1998 JSObject::cast(object), holder); |
| 1999 if (depth == kInvalidProtoDepth) return Heap::undefined_value(); |
| 2000 |
| 2001 Label miss, miss_before_stack_reserved; |
| 2002 |
| 2003 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2004 |
| 2005 // Get the receiver from the stack. |
| 2006 const int argc = arguments().immediate(); |
| 2007 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2008 |
| 2009 // Check that the receiver isn't a smi. |
| 2010 __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
| 2011 |
| 2012 __ IncrementCounter(&Counters::call_const, 1); |
| 2013 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
| 2014 |
| 2015 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2016 // before calling any runtime function. |
| 2017 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2018 |
| 2019 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2020 CheckPrototypes(JSObject::cast(object), rdx, holder, |
| 2021 rbx, rax, rdi, name, depth, &miss); |
| 2022 |
| 2023 // Move the return address on top of the stack. |
| 2024 __ movq(rax, Operand(rsp, 3 * kPointerSize)); |
| 2025 __ movq(Operand(rsp, 0 * kPointerSize), rax); |
| 2026 |
| 2027 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2028 if (result->IsFailure()) return result; |
| 2029 |
| 2030 __ bind(&miss); |
| 2031 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2032 |
| 2033 __ bind(&miss_before_stack_reserved); |
| 2034 Object* obj; |
| 2035 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2036 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2037 } |
| 2038 |
| 2039 // Return the generated code. |
| 2040 return GetCode(function); |
| 2041 } |
| 2042 |
| 2043 |
1985 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2044 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
1986 JSObject* holder, | 2045 JSObject* holder, |
1987 JSFunction* function, | 2046 JSFunction* function, |
1988 String* name, | 2047 String* name, |
1989 CheckType check) { | 2048 CheckType check) { |
1990 // ----------- S t a t e ------------- | 2049 // ----------- S t a t e ------------- |
1991 // rcx : function name | 2050 // rcx : function name |
1992 // rsp[0] : return address | 2051 // rsp[0] : return address |
1993 // rsp[8] : argument argc | 2052 // rsp[8] : argument argc |
1994 // rsp[16] : argument argc - 1 | 2053 // rsp[16] : argument argc - 1 |
1995 // ... | 2054 // ... |
1996 // rsp[argc * 8] : argument 1 | 2055 // rsp[argc * 8] : argument 1 |
1997 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2056 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1998 // ----------------------------------- | 2057 // ----------------------------------- |
1999 | 2058 |
2000 SharedFunctionInfo* function_info = function->shared(); | 2059 if (HasCustomCallGenerator(function)) { |
2001 if (function_info->HasBuiltinFunctionId()) { | |
2002 BuiltinFunctionId id = function_info->builtin_function_id(); | |
2003 MaybeObject* maybe_result = CompileCustomCall( | 2060 MaybeObject* maybe_result = CompileCustomCall( |
2004 id, object, holder, NULL, function, name); | 2061 object, holder, NULL, function, name); |
2005 Object* result; | 2062 Object* result; |
2006 if (!maybe_result->ToObject(&result)) return maybe_result; | 2063 if (!maybe_result->ToObject(&result)) return maybe_result; |
2007 // undefined means bail out to regular compiler. | 2064 // undefined means bail out to regular compiler. |
2008 if (!result->IsUndefined()) return result; | 2065 if (!result->IsUndefined()) return result; |
2009 } | 2066 } |
2010 | 2067 |
2011 Label miss_in_smi_check; | 2068 Label miss; |
2012 | 2069 |
2013 GenerateNameCheck(name, &miss_in_smi_check); | 2070 GenerateNameCheck(name, &miss); |
2014 | 2071 |
2015 // Get the receiver from the stack. | 2072 // Get the receiver from the stack. |
2016 const int argc = arguments().immediate(); | 2073 const int argc = arguments().immediate(); |
2017 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2074 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
2018 | 2075 |
2019 // Check that the receiver isn't a smi. | 2076 // Check that the receiver isn't a smi. |
2020 if (check != NUMBER_CHECK) { | 2077 if (check != NUMBER_CHECK) { |
2021 __ JumpIfSmi(rdx, &miss_in_smi_check); | 2078 __ JumpIfSmi(rdx, &miss); |
2022 } | 2079 } |
2023 | 2080 |
2024 // Make sure that it's okay not to patch the on stack receiver | 2081 // Make sure that it's okay not to patch the on stack receiver |
2025 // unless we're doing a receiver map check. | 2082 // unless we're doing a receiver map check. |
2026 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2083 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2027 | 2084 |
2028 CallOptimization optimization(function); | 2085 SharedFunctionInfo* function_info = function->shared(); |
2029 int depth = kInvalidProtoDepth; | |
2030 Label miss; | |
2031 | |
2032 switch (check) { | 2086 switch (check) { |
2033 case RECEIVER_MAP_CHECK: | 2087 case RECEIVER_MAP_CHECK: |
2034 __ IncrementCounter(&Counters::call_const, 1); | 2088 __ IncrementCounter(&Counters::call_const, 1); |
2035 | 2089 |
2036 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { | |
2037 depth = optimization.GetPrototypeDepthOfExpectedType( | |
2038 JSObject::cast(object), holder); | |
2039 } | |
2040 | |
2041 if (depth != kInvalidProtoDepth) { | |
2042 __ IncrementCounter(&Counters::call_const_fast_api, 1); | |
2043 | |
2044 // Allocate space for v8::Arguments implicit values. Must be initialized | |
2045 // before to call any runtime function. | |
2046 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | |
2047 } | |
2048 | |
2049 // Check that the maps haven't changed. | 2090 // Check that the maps haven't changed. |
2050 CheckPrototypes(JSObject::cast(object), rdx, holder, | 2091 CheckPrototypes(JSObject::cast(object), rdx, holder, |
2051 rbx, rax, rdi, name, depth, &miss); | 2092 rbx, rax, rdi, name, &miss); |
2052 | 2093 |
2053 // Patch the receiver on the stack with the global proxy if | 2094 // Patch the receiver on the stack with the global proxy if |
2054 // necessary. | 2095 // necessary. |
2055 if (object->IsGlobalObject()) { | 2096 if (object->IsGlobalObject()) { |
2056 ASSERT(depth == kInvalidProtoDepth); | |
2057 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2097 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
2058 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2098 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
2059 } | 2099 } |
2060 break; | 2100 break; |
2061 | 2101 |
2062 case STRING_CHECK: | 2102 case STRING_CHECK: |
2063 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2103 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2064 // Calling non-strict non-builtins with a value as the receiver | 2104 // Calling non-strict non-builtins with a value as the receiver |
2065 // requires boxing. | 2105 // requires boxing. |
2066 __ jmp(&miss); | 2106 __ jmp(&miss); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2116 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2156 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
2117 rbx, rdx, rdi, name, &miss); | 2157 rbx, rdx, rdi, name, &miss); |
2118 } | 2158 } |
2119 break; | 2159 break; |
2120 } | 2160 } |
2121 | 2161 |
2122 default: | 2162 default: |
2123 UNREACHABLE(); | 2163 UNREACHABLE(); |
2124 } | 2164 } |
2125 | 2165 |
2126 if (depth != kInvalidProtoDepth) { | 2166 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
2127 // Move the return address on top of the stack. | |
2128 __ movq(rax, Operand(rsp, 3 * kPointerSize)); | |
2129 __ movq(Operand(rsp, 0 * kPointerSize), rax); | |
2130 | |
2131 // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains | |
2132 // duplicate of return address and will be overwritten. | |
2133 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | |
2134 if (result->IsFailure()) return result; | |
2135 } else { | |
2136 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
2137 } | |
2138 | 2167 |
2139 // Handle call cache miss. | 2168 // Handle call cache miss. |
2140 __ bind(&miss); | 2169 __ bind(&miss); |
2141 if (depth != kInvalidProtoDepth) { | |
2142 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | |
2143 } | |
2144 | |
2145 // Handle call cache miss. | |
2146 __ bind(&miss_in_smi_check); | |
2147 Object* obj; | 2170 Object* obj; |
2148 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2171 { MaybeObject* maybe_obj = GenerateMissBranch(); |
2149 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2172 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
2150 } | 2173 } |
2151 | 2174 |
2152 // Return the generated code. | 2175 // Return the generated code. |
2153 return GetCode(function); | 2176 return GetCode(function); |
2154 } | 2177 } |
2155 | 2178 |
2156 | 2179 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 // ----------- S t a t e ------------- | 2254 // ----------- S t a t e ------------- |
2232 // rcx : function name | 2255 // rcx : function name |
2233 // rsp[0] : return address | 2256 // rsp[0] : return address |
2234 // rsp[8] : argument argc | 2257 // rsp[8] : argument argc |
2235 // rsp[16] : argument argc - 1 | 2258 // rsp[16] : argument argc - 1 |
2236 // ... | 2259 // ... |
2237 // rsp[argc * 8] : argument 1 | 2260 // rsp[argc * 8] : argument 1 |
2238 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2261 // rsp[(argc + 1) * 8] : argument 0 = receiver |
2239 // ----------------------------------- | 2262 // ----------------------------------- |
2240 | 2263 |
2241 SharedFunctionInfo* function_info = function->shared(); | 2264 if (HasCustomCallGenerator(function)) { |
2242 if (function_info->HasBuiltinFunctionId()) { | |
2243 BuiltinFunctionId id = function_info->builtin_function_id(); | |
2244 MaybeObject* maybe_result = CompileCustomCall( | 2265 MaybeObject* maybe_result = CompileCustomCall( |
2245 id, object, holder, cell, function, name); | 2266 object, holder, cell, function, name); |
2246 Object* result; | 2267 Object* result; |
2247 if (!maybe_result->ToObject(&result)) return maybe_result; | 2268 if (!maybe_result->ToObject(&result)) return maybe_result; |
2248 // undefined means bail out to regular compiler. | 2269 // undefined means bail out to regular compiler. |
2249 if (!result->IsUndefined()) return result; | 2270 if (!result->IsUndefined()) return result; |
2250 } | 2271 } |
2251 | 2272 |
2252 Label miss; | 2273 Label miss; |
2253 | 2274 |
2254 GenerateNameCheck(name, &miss); | 2275 GenerateNameCheck(name, &miss); |
2255 | 2276 |
(...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2953 | 2974 |
2954 // Return the generated code. | 2975 // Return the generated code. |
2955 return GetCode(CALLBACKS, name); | 2976 return GetCode(CALLBACKS, name); |
2956 } | 2977 } |
2957 | 2978 |
2958 | 2979 |
2959 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 2980 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
2960 // ----------- S t a t e ------------- | 2981 // ----------- S t a t e ------------- |
2961 // -- rax : key | 2982 // -- rax : key |
2962 // -- rdx : receiver | 2983 // -- rdx : receiver |
2963 // -- esp[0] : return address | 2984 // -- rsp[0] : return address |
2964 // ----------------------------------- | 2985 // ----------------------------------- |
2965 Label miss; | 2986 Label miss; |
2966 | 2987 |
2967 // Check that the receiver isn't a smi. | 2988 // Check that the receiver isn't a smi. |
2968 __ JumpIfSmi(rdx, &miss); | 2989 __ JumpIfSmi(rdx, &miss); |
2969 | 2990 |
2970 // Check that the map matches. | 2991 // Check that the map matches. |
2971 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 2992 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), |
2972 Handle<Map>(receiver->map())); | 2993 Handle<Map>(receiver->map())); |
2973 __ j(not_equal, &miss); | 2994 __ j(not_equal, &miss); |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3423 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); | 3444 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
3424 | 3445 |
3425 return GetCode(flags); | 3446 return GetCode(flags); |
3426 } | 3447 } |
3427 | 3448 |
3428 #undef __ | 3449 #undef __ |
3429 | 3450 |
3430 } } // namespace v8::internal | 3451 } } // namespace v8::internal |
3431 | 3452 |
3432 #endif // V8_TARGET_ARCH_X64 | 3453 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |