OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 2109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2120 Object* obj; | 2120 Object* obj; |
2121 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2121 { MaybeObject* maybe_obj = GenerateMissBranch(); |
2122 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2122 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
2123 } | 2123 } |
2124 | 2124 |
2125 // Return the generated code. | 2125 // Return the generated code. |
2126 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2126 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
2127 } | 2127 } |
2128 | 2128 |
2129 | 2129 |
| 2130 MaybeObject* CallStubCompiler::CompileFastApiCall( |
| 2131 const CallOptimization& optimization, |
| 2132 Object* object, |
| 2133 JSObject* holder, |
| 2134 JSGlobalPropertyCell* cell, |
| 2135 JSFunction* function, |
| 2136 String* name) { |
| 2137 ASSERT(optimization.is_simple_api_call()); |
| 2138 // Bail out if object is a global object as we don't want to |
| 2139 // repatch it to global receiver. |
| 2140 if (object->IsGlobalObject()) return Heap::undefined_value(); |
| 2141 if (cell != NULL) return Heap::undefined_value(); |
| 2142 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2143 JSObject::cast(object), holder); |
| 2144 if (depth == kInvalidProtoDepth) return Heap::undefined_value(); |
| 2145 |
| 2146 Label miss, miss_before_stack_reserved; |
| 2147 |
| 2148 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2149 |
| 2150 // Get the receiver from the stack. |
| 2151 const int argc = arguments().immediate(); |
| 2152 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2153 |
| 2154 // Check that the receiver isn't a smi. |
| 2155 __ test(edx, Immediate(kSmiTagMask)); |
| 2156 __ j(zero, &miss_before_stack_reserved, not_taken); |
| 2157 |
| 2158 __ IncrementCounter(&Counters::call_const, 1); |
| 2159 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
| 2160 |
| 2161 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2162 // before calling any runtime function. |
| 2163 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
| 2164 |
| 2165 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2166 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2167 ebx, eax, edi, name, depth, &miss); |
| 2168 |
| 2169 // Move the return address on top of the stack. |
| 2170 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
| 2171 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 2172 |
| 2173 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2174 // duplicate of return address and will be overwritten. |
| 2175 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); |
| 2176 if (result->IsFailure()) return result; |
| 2177 |
| 2178 __ bind(&miss); |
| 2179 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
| 2180 |
| 2181 __ bind(&miss_before_stack_reserved); |
| 2182 Object* obj; |
| 2183 { MaybeObject* maybe_obj = GenerateMissBranch(); |
| 2184 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2185 } |
| 2186 |
| 2187 // Return the generated code. |
| 2188 return GetCode(function); |
| 2189 } |
| 2190 |
| 2191 |
2130 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2192 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, |
2131 JSObject* holder, | 2193 JSObject* holder, |
2132 JSFunction* function, | 2194 JSFunction* function, |
2133 String* name, | 2195 String* name, |
2134 CheckType check) { | 2196 CheckType check) { |
2135 // ----------- S t a t e ------------- | 2197 // ----------- S t a t e ------------- |
2136 // -- ecx : name | 2198 // -- ecx : name |
2137 // -- esp[0] : return address | 2199 // -- esp[0] : return address |
2138 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2200 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2139 // -- ... | 2201 // -- ... |
2140 // -- esp[(argc + 1) * 4] : receiver | 2202 // -- esp[(argc + 1) * 4] : receiver |
2141 // ----------------------------------- | 2203 // ----------------------------------- |
2142 | 2204 |
2143 SharedFunctionInfo* function_info = function->shared(); | 2205 if (HasCustomCallGenerator(function)) { |
2144 if (function_info->HasBuiltinFunctionId()) { | |
2145 BuiltinFunctionId id = function_info->builtin_function_id(); | |
2146 MaybeObject* maybe_result = CompileCustomCall( | 2206 MaybeObject* maybe_result = CompileCustomCall( |
2147 id, object, holder, NULL, function, name); | 2207 object, holder, NULL, function, name); |
2148 Object* result; | 2208 Object* result; |
2149 if (!maybe_result->ToObject(&result)) return maybe_result; | 2209 if (!maybe_result->ToObject(&result)) return maybe_result; |
2150 // undefined means bail out to regular compiler. | 2210 // undefined means bail out to regular compiler. |
2151 if (!result->IsUndefined()) return result; | 2211 if (!result->IsUndefined()) return result; |
2152 } | 2212 } |
2153 | 2213 |
2154 Label miss_in_smi_check; | 2214 Label miss; |
2155 | 2215 |
2156 GenerateNameCheck(name, &miss_in_smi_check); | 2216 GenerateNameCheck(name, &miss); |
2157 | 2217 |
2158 // Get the receiver from the stack. | 2218 // Get the receiver from the stack. |
2159 const int argc = arguments().immediate(); | 2219 const int argc = arguments().immediate(); |
2160 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2220 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2161 | 2221 |
2162 // Check that the receiver isn't a smi. | 2222 // Check that the receiver isn't a smi. |
2163 if (check != NUMBER_CHECK) { | 2223 if (check != NUMBER_CHECK) { |
2164 __ test(edx, Immediate(kSmiTagMask)); | 2224 __ test(edx, Immediate(kSmiTagMask)); |
2165 __ j(zero, &miss_in_smi_check, not_taken); | 2225 __ j(zero, &miss, not_taken); |
2166 } | 2226 } |
2167 | 2227 |
2168 // Make sure that it's okay not to patch the on stack receiver | 2228 // Make sure that it's okay not to patch the on stack receiver |
2169 // unless we're doing a receiver map check. | 2229 // unless we're doing a receiver map check. |
2170 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2230 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2171 | 2231 |
2172 CallOptimization optimization(function); | 2232 SharedFunctionInfo* function_info = function->shared(); |
2173 int depth = kInvalidProtoDepth; | |
2174 Label miss; | |
2175 | |
2176 switch (check) { | 2233 switch (check) { |
2177 case RECEIVER_MAP_CHECK: | 2234 case RECEIVER_MAP_CHECK: |
2178 __ IncrementCounter(&Counters::call_const, 1); | 2235 __ IncrementCounter(&Counters::call_const, 1); |
2179 | 2236 |
2180 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { | |
2181 depth = optimization.GetPrototypeDepthOfExpectedType( | |
2182 JSObject::cast(object), holder); | |
2183 } | |
2184 | |
2185 if (depth != kInvalidProtoDepth) { | |
2186 __ IncrementCounter(&Counters::call_const_fast_api, 1); | |
2187 | |
2188 // Allocate space for v8::Arguments implicit values. Must be initialized | |
2189 // before to call any runtime function. | |
2190 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | |
2191 } | |
2192 | |
2193 // Check that the maps haven't changed. | 2237 // Check that the maps haven't changed. |
2194 CheckPrototypes(JSObject::cast(object), edx, holder, | 2238 CheckPrototypes(JSObject::cast(object), edx, holder, |
2195 ebx, eax, edi, name, depth, &miss); | 2239 ebx, eax, edi, name, &miss); |
2196 | 2240 |
2197 // Patch the receiver on the stack with the global proxy if | 2241 // Patch the receiver on the stack with the global proxy if |
2198 // necessary. | 2242 // necessary. |
2199 if (object->IsGlobalObject()) { | 2243 if (object->IsGlobalObject()) { |
2200 ASSERT(depth == kInvalidProtoDepth); | |
2201 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2244 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2202 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2245 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2203 } | 2246 } |
2204 break; | 2247 break; |
2205 | 2248 |
2206 case STRING_CHECK: | 2249 case STRING_CHECK: |
2207 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2250 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2208 // Calling non-strict non-builtins with a value as the receiver | 2251 // Calling non-strict non-builtins with a value as the receiver |
2209 // requires boxing. | 2252 // requires boxing. |
2210 __ jmp(&miss); | 2253 __ jmp(&miss); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2304 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2262 ebx, edx, edi, name, &miss); | 2305 ebx, edx, edi, name, &miss); |
2263 } | 2306 } |
2264 break; | 2307 break; |
2265 } | 2308 } |
2266 | 2309 |
2267 default: | 2310 default: |
2268 UNREACHABLE(); | 2311 UNREACHABLE(); |
2269 } | 2312 } |
2270 | 2313 |
2271 if (depth != kInvalidProtoDepth) { | 2314 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
2272 // Move the return address on top of the stack. | |
2273 __ mov(eax, Operand(esp, 3 * kPointerSize)); | |
2274 __ mov(Operand(esp, 0 * kPointerSize), eax); | |
2275 | |
2276 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | |
2277 // duplicate of return address and will be overwritten. | |
2278 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | |
2279 if (result->IsFailure()) return result; | |
2280 } else { | |
2281 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
2282 } | |
2283 | 2315 |
2284 // Handle call cache miss. | 2316 // Handle call cache miss. |
2285 __ bind(&miss); | 2317 __ bind(&miss); |
2286 if (depth != kInvalidProtoDepth) { | |
2287 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | |
2288 } | |
2289 __ bind(&miss_in_smi_check); | |
2290 Object* obj; | 2318 Object* obj; |
2291 { MaybeObject* maybe_obj = GenerateMissBranch(); | 2319 { MaybeObject* maybe_obj = GenerateMissBranch(); |
2292 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2320 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
2293 } | 2321 } |
2294 | 2322 |
2295 // Return the generated code. | 2323 // Return the generated code. |
2296 return GetCode(function); | 2324 return GetCode(function); |
2297 } | 2325 } |
2298 | 2326 |
2299 | 2327 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2371 JSFunction* function, | 2399 JSFunction* function, |
2372 String* name) { | 2400 String* name) { |
2373 // ----------- S t a t e ------------- | 2401 // ----------- S t a t e ------------- |
2374 // -- ecx : name | 2402 // -- ecx : name |
2375 // -- esp[0] : return address | 2403 // -- esp[0] : return address |
2376 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2404 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2377 // -- ... | 2405 // -- ... |
2378 // -- esp[(argc + 1) * 4] : receiver | 2406 // -- esp[(argc + 1) * 4] : receiver |
2379 // ----------------------------------- | 2407 // ----------------------------------- |
2380 | 2408 |
2381 SharedFunctionInfo* function_info = function->shared(); | 2409 if (HasCustomCallGenerator(function)) { |
2382 if (function_info->HasBuiltinFunctionId()) { | |
2383 BuiltinFunctionId id = function_info->builtin_function_id(); | |
2384 MaybeObject* maybe_result = CompileCustomCall( | 2410 MaybeObject* maybe_result = CompileCustomCall( |
2385 id, object, holder, cell, function, name); | 2411 object, holder, cell, function, name); |
2386 Object* result; | 2412 Object* result; |
2387 if (!maybe_result->ToObject(&result)) return maybe_result; | 2413 if (!maybe_result->ToObject(&result)) return maybe_result; |
2388 // undefined means bail out to regular compiler. | 2414 // undefined means bail out to regular compiler. |
2389 if (!result->IsUndefined()) return result; | 2415 if (!result->IsUndefined()) return result; |
2390 } | 2416 } |
2391 | 2417 |
2392 Label miss; | 2418 Label miss; |
2393 | 2419 |
2394 GenerateNameCheck(name, &miss); | 2420 GenerateNameCheck(name, &miss); |
2395 | 2421 |
(...skipping 1257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3653 | 3679 |
3654 return GetCode(flags); | 3680 return GetCode(flags); |
3655 } | 3681 } |
3656 | 3682 |
3657 | 3683 |
3658 #undef __ | 3684 #undef __ |
3659 | 3685 |
3660 } } // namespace v8::internal | 3686 } } // namespace v8::internal |
3661 | 3687 |
3662 #endif // V8_TARGET_ARCH_IA32 | 3688 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |