| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 void ToNumberStub::InitializeInterfaceDescriptor( | 53 void ToNumberStub::InitializeInterfaceDescriptor( |
| 54 Isolate* isolate, | 54 Isolate* isolate, |
| 55 CodeStubInterfaceDescriptor* descriptor) { | 55 CodeStubInterfaceDescriptor* descriptor) { |
| 56 static Register registers[] = { rax }; | 56 static Register registers[] = { rax }; |
| 57 descriptor->register_param_count_ = 1; | 57 descriptor->register_param_count_ = 1; |
| 58 descriptor->register_params_ = registers; | 58 descriptor->register_params_ = registers; |
| 59 descriptor->deoptimization_handler_ = NULL; | 59 descriptor->deoptimization_handler_ = NULL; |
| 60 } | 60 } |
| 61 | 61 |
| 62 | 62 |
| 63 void NumberToStringStub::InitializeInterfaceDescriptor( |
| 64 Isolate* isolate, |
| 65 CodeStubInterfaceDescriptor* descriptor) { |
| 66 static Register registers[] = { rax }; |
| 67 descriptor->register_param_count_ = 1; |
| 68 descriptor->register_params_ = registers; |
| 69 descriptor->deoptimization_handler_ = NULL; |
| 70 } |
| 71 |
| 72 |
| 63 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( | 73 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( |
| 64 Isolate* isolate, | 74 Isolate* isolate, |
| 65 CodeStubInterfaceDescriptor* descriptor) { | 75 CodeStubInterfaceDescriptor* descriptor) { |
| 66 static Register registers[] = { rax, rbx, rcx }; | 76 static Register registers[] = { rax, rbx, rcx }; |
| 67 descriptor->register_param_count_ = 3; | 77 descriptor->register_param_count_ = 3; |
| 68 descriptor->register_params_ = registers; | 78 descriptor->register_params_ = registers; |
| 69 descriptor->deoptimization_handler_ = | 79 descriptor->deoptimization_handler_ = |
| 70 Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry; | 80 Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry; |
| 71 } | 81 } |
| 72 | 82 |
| (...skipping 2829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2902 __ jmp(&loop); | 2912 __ jmp(&loop); |
| 2903 | 2913 |
| 2904 __ bind(&done); | 2914 __ bind(&done); |
| 2905 __ ret(3 * kPointerSize); | 2915 __ ret(3 * kPointerSize); |
| 2906 | 2916 |
| 2907 __ bind(&slowcase); | 2917 __ bind(&slowcase); |
| 2908 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); | 2918 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); |
| 2909 } | 2919 } |
| 2910 | 2920 |
| 2911 | 2921 |
| 2912 void NumberToStringStub::Generate(MacroAssembler* masm) { | |
| 2913 Label runtime; | |
| 2914 | |
| 2915 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); | |
| 2916 __ movq(rbx, args.GetArgumentOperand(0)); | |
| 2917 | |
| 2918 // Generate code to lookup number in the number string cache. | |
| 2919 __ LookupNumberStringCache(rbx, rax, r8, r9, &runtime); | |
| 2920 __ ret(1 * kPointerSize); | |
| 2921 | |
| 2922 __ bind(&runtime); | |
| 2923 // Handle number to string in the runtime system if not found in the cache. | |
| 2924 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); | |
| 2925 } | |
| 2926 | |
| 2927 | |
| 2928 static int NegativeComparisonResult(Condition cc) { | 2922 static int NegativeComparisonResult(Condition cc) { |
| 2929 ASSERT(cc != equal); | 2923 ASSERT(cc != equal); |
| 2930 ASSERT((cc == less) || (cc == less_equal) | 2924 ASSERT((cc == less) || (cc == less_equal) |
| 2931 || (cc == greater) || (cc == greater_equal)); | 2925 || (cc == greater) || (cc == greater_equal)); |
| 2932 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 2926 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
| 2933 } | 2927 } |
| 2934 | 2928 |
| 2935 | 2929 |
| 2936 static void CheckInputType(MacroAssembler* masm, | 2930 static void CheckInputType(MacroAssembler* masm, |
| 2937 Register input, | 2931 Register input, |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3224 | 3218 |
| 3225 __ bind(&miss); | 3219 __ bind(&miss); |
| 3226 GenerateMiss(masm); | 3220 GenerateMiss(masm); |
| 3227 } | 3221 } |
| 3228 | 3222 |
| 3229 | 3223 |
| 3230 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 3224 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
| 3231 // Cache the called function in a global property cell. Cache states | 3225 // Cache the called function in a global property cell. Cache states |
| 3232 // are uninitialized, monomorphic (indicated by a JSFunction), and | 3226 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 3233 // megamorphic. | 3227 // megamorphic. |
| 3228 // rax : number of arguments to the construct function |
| 3234 // rbx : cache cell for call target | 3229 // rbx : cache cell for call target |
| 3235 // rdi : the function to call | 3230 // rdi : the function to call |
| 3236 Isolate* isolate = masm->isolate(); | 3231 Isolate* isolate = masm->isolate(); |
| 3237 Label initialize, done, miss, megamorphic, not_array_function; | 3232 Label initialize, done, miss, megamorphic, not_array_function; |
| 3238 | 3233 |
| 3239 // Load the cache state into rcx. | 3234 // Load the cache state into rcx. |
| 3240 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); | 3235 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); |
| 3241 | 3236 |
| 3242 // A monomorphic cache hit or an already megamorphic state: invoke the | 3237 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 3243 // function without changing the state. | 3238 // function without changing the state. |
| 3244 __ cmpq(rcx, rdi); | 3239 __ cmpq(rcx, rdi); |
| 3245 __ j(equal, &done); | 3240 __ j(equal, &done); |
| 3246 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); | 3241 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 3247 __ j(equal, &done); | 3242 __ j(equal, &done); |
| 3248 | 3243 |
| 3249 // If we came here, we need to see if we are the array function. | 3244 // If we came here, we need to see if we are the array function. |
| 3250 // If we didn't have a matching function, and we didn't find the megamorph | 3245 // If we didn't have a matching function, and we didn't find the megamorph |
| 3251 // sentinel, then we have in the cell either some other function or an | 3246 // sentinel, then we have in the cell either some other function or an |
| 3252 // AllocationSite. Do a map check on the object in rcx. | 3247 // AllocationSite. Do a map check on the object in rcx. |
| 3253 Handle<Map> allocation_site_map( | 3248 Handle<Map> allocation_site_map = |
| 3254 masm->isolate()->heap()->allocation_site_map(), | 3249 masm->isolate()->factory()->allocation_site_map(); |
| 3255 masm->isolate()); | |
| 3256 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); | 3250 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); |
| 3257 __ j(not_equal, &miss); | 3251 __ j(not_equal, &miss); |
| 3258 | 3252 |
| 3259 // Make sure the function is the Array() function | 3253 // Make sure the function is the Array() function |
| 3260 __ LoadArrayFunction(rcx); | 3254 __ LoadArrayFunction(rcx); |
| 3261 __ cmpq(rdi, rcx); | 3255 __ cmpq(rdi, rcx); |
| 3262 __ j(not_equal, &megamorphic); | 3256 __ j(not_equal, &megamorphic); |
| 3263 __ jmp(&done); | 3257 __ jmp(&done); |
| 3264 | 3258 |
| 3265 __ bind(&miss); | 3259 __ bind(&miss); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3281 // Make sure the function is the Array() function | 3275 // Make sure the function is the Array() function |
| 3282 __ LoadArrayFunction(rcx); | 3276 __ LoadArrayFunction(rcx); |
| 3283 __ cmpq(rdi, rcx); | 3277 __ cmpq(rdi, rcx); |
| 3284 __ j(not_equal, ¬_array_function); | 3278 __ j(not_equal, ¬_array_function); |
| 3285 | 3279 |
| 3286 // The target function is the Array constructor, | 3280 // The target function is the Array constructor, |
| 3287 // Create an AllocationSite if we don't already have it, store it in the cell | 3281 // Create an AllocationSite if we don't already have it, store it in the cell |
| 3288 { | 3282 { |
| 3289 FrameScope scope(masm, StackFrame::INTERNAL); | 3283 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3290 | 3284 |
| 3285 // Arguments register must be smi-tagged to call out. |
| 3291 __ Integer32ToSmi(rax, rax); | 3286 __ Integer32ToSmi(rax, rax); |
| 3292 __ push(rax); | 3287 __ push(rax); |
| 3293 __ push(rdi); | 3288 __ push(rdi); |
| 3294 __ push(rbx); | 3289 __ push(rbx); |
| 3295 | 3290 |
| 3296 CreateAllocationSiteStub create_stub; | 3291 CreateAllocationSiteStub create_stub; |
| 3297 __ CallStub(&create_stub); | 3292 __ CallStub(&create_stub); |
| 3298 | 3293 |
| 3299 __ pop(rbx); | 3294 __ pop(rbx); |
| 3300 __ pop(rdi); | 3295 __ pop(rdi); |
| (...skipping 2989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6290 ArraySingleArgumentConstructorStub stub(initial, | 6285 ArraySingleArgumentConstructorStub stub(initial, |
| 6291 CONTEXT_CHECK_REQUIRED, | 6286 CONTEXT_CHECK_REQUIRED, |
| 6292 DISABLE_ALLOCATION_SITES); | 6287 DISABLE_ALLOCATION_SITES); |
| 6293 __ TailCallStub(&stub); | 6288 __ TailCallStub(&stub); |
| 6294 } else if (mode == DONT_OVERRIDE) { | 6289 } else if (mode == DONT_OVERRIDE) { |
| 6295 // We are going to create a holey array, but our kind is non-holey. | 6290 // We are going to create a holey array, but our kind is non-holey. |
| 6296 // Fix kind and retry (only if we have an allocation site in the cell). | 6291 // Fix kind and retry (only if we have an allocation site in the cell). |
| 6297 __ incl(rdx); | 6292 __ incl(rdx); |
| 6298 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); | 6293 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); |
| 6299 if (FLAG_debug_code) { | 6294 if (FLAG_debug_code) { |
| 6300 Handle<Map> allocation_site_map( | 6295 Handle<Map> allocation_site_map = |
| 6301 masm->isolate()->heap()->allocation_site_map(), | 6296 masm->isolate()->factory()->allocation_site_map(); |
| 6302 masm->isolate()); | |
| 6303 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); | 6297 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); |
| 6304 __ Assert(equal, kExpectedAllocationSiteInCell); | 6298 __ Assert(equal, kExpectedAllocationSiteInCell); |
| 6305 } | 6299 } |
| 6306 | 6300 |
| 6307 // Save the resulting elements kind in type info | 6301 // Save the resulting elements kind in type info |
| 6308 __ Integer32ToSmi(rdx, rdx); | 6302 __ Integer32ToSmi(rdx, rdx); |
| 6309 __ movq(FieldOperand(rcx, AllocationSite::kTransitionInfoOffset), rdx); | 6303 __ movq(FieldOperand(rcx, AllocationSite::kTransitionInfoOffset), rdx); |
| 6310 __ SmiToInteger32(rdx, rdx); | 6304 __ SmiToInteger32(rdx, rdx); |
| 6311 | 6305 |
| 6312 __ bind(&normal_sequence); | 6306 __ bind(&normal_sequence); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6439 __ bind(&okay_here); | 6433 __ bind(&okay_here); |
| 6440 } | 6434 } |
| 6441 | 6435 |
| 6442 Label no_info; | 6436 Label no_info; |
| 6443 // If the type cell is undefined, or contains anything other than an | 6437 // If the type cell is undefined, or contains anything other than an |
| 6444 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 6438 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
| 6445 __ Cmp(rbx, undefined_sentinel); | 6439 __ Cmp(rbx, undefined_sentinel); |
| 6446 __ j(equal, &no_info); | 6440 __ j(equal, &no_info); |
| 6447 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset)); | 6441 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset)); |
| 6448 __ Cmp(FieldOperand(rdx, 0), | 6442 __ Cmp(FieldOperand(rdx, 0), |
| 6449 Handle<Map>(masm->isolate()->heap()->allocation_site_map())); | 6443 masm->isolate()->factory()->allocation_site_map()); |
| 6450 __ j(not_equal, &no_info); | 6444 __ j(not_equal, &no_info); |
| 6451 | 6445 |
| 6452 __ movq(rdx, FieldOperand(rdx, AllocationSite::kTransitionInfoOffset)); | 6446 __ movq(rdx, FieldOperand(rdx, AllocationSite::kTransitionInfoOffset)); |
| 6453 __ SmiToInteger32(rdx, rdx); | 6447 __ SmiToInteger32(rdx, rdx); |
| 6454 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 6448 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 6455 | 6449 |
| 6456 __ bind(&no_info); | 6450 __ bind(&no_info); |
| 6457 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); | 6451 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
| 6458 } | 6452 } |
| 6459 | 6453 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6546 __ bind(&fast_elements_case); | 6540 __ bind(&fast_elements_case); |
| 6547 GenerateCase(masm, FAST_ELEMENTS); | 6541 GenerateCase(masm, FAST_ELEMENTS); |
| 6548 } | 6542 } |
| 6549 | 6543 |
| 6550 | 6544 |
| 6551 #undef __ | 6545 #undef __ |
| 6552 | 6546 |
| 6553 } } // namespace v8::internal | 6547 } } // namespace v8::internal |
| 6554 | 6548 |
| 6555 #endif // V8_TARGET_ARCH_X64 | 6549 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |