OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
(...skipping 2346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2357 | 2357 |
2358 | 2358 |
2359 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { | 2359 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { |
2360 __ movp(vector, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 2360 __ movp(vector, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
2361 __ movp(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 2361 __ movp(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
2362 __ movp(vector, FieldOperand(vector, | 2362 __ movp(vector, FieldOperand(vector, |
2363 SharedFunctionInfo::kFeedbackVectorOffset)); | 2363 SharedFunctionInfo::kFeedbackVectorOffset)); |
2364 } | 2364 } |
2365 | 2365 |
2366 | 2366 |
2367 void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) { | 2367 void CallIC_ArrayStub::Generate(MacroAssembler* masm) { |
2368 // rdi - function | 2368 // rdi - function |
2369 // rbx - feedback vector | |
2370 // rdx - slot id (as integer) | 2369 // rdx - slot id (as integer) |
| 2370 Label miss; |
| 2371 int argc = state_.arg_count(); |
| 2372 ParameterCount actual(argc); |
| 2373 |
| 2374 EmitLoadTypeFeedbackVector(masm, rbx); |
| 2375 __ SmiToInteger32(rdx, rdx); |
| 2376 |
2371 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); | 2377 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx); |
2372 __ cmpq(rdi, rcx); | 2378 __ cmpq(rdi, rcx); |
2373 __ j(not_equal, miss); | 2379 __ j(not_equal, &miss); |
2374 | 2380 |
2375 __ movq(rax, Immediate(arg_count())); | 2381 __ movq(rax, Immediate(arg_count())); |
2376 __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, | 2382 __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size, |
2377 FixedArray::kHeaderSize)); | 2383 FixedArray::kHeaderSize)); |
2378 | 2384 |
2379 // Verify that ecx contains an AllocationSite | 2385 // Verify that ecx contains an AllocationSite |
2380 __ AssertUndefinedOrAllocationSite(rbx); | 2386 __ AssertUndefinedOrAllocationSite(rbx); |
2381 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 2387 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
2382 __ TailCallStub(&stub); | 2388 __ TailCallStub(&stub); |
2383 } | |
2384 | |
2385 | |
2386 void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) { | |
2387 // rdi - function | |
2388 // rbx - feedback vector | |
2389 // rdx - slot id | |
2390 Label miss; | |
2391 | |
2392 __ SmiToInteger32(rdx, rdx); | |
2393 | |
2394 if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) { | |
2395 Generate_MonomorphicArray(masm, &miss); | |
2396 } else { | |
2397 // So far there is only one customer for our custom feedback scheme. | |
2398 UNREACHABLE(); | |
2399 } | |
2400 | 2389 |
2401 __ bind(&miss); | 2390 __ bind(&miss); |
2402 GenerateMiss(masm); | 2391 GenerateMiss(masm, IC::kCallIC_Customization_Miss); |
2403 | 2392 |
2404 // The slow case, we need this no matter what to complete a call after a miss. | 2393 // The slow case, we need this no matter what to complete a call after a miss. |
2405 CallFunctionNoFeedback(masm, | 2394 CallFunctionNoFeedback(masm, |
2406 arg_count(), | 2395 arg_count(), |
2407 true, | 2396 true, |
2408 CallAsMethod()); | 2397 CallAsMethod()); |
2409 | 2398 |
2410 // Unreachable. | 2399 // Unreachable. |
2411 __ int3(); | 2400 __ int3(); |
2412 } | 2401 } |
2413 | 2402 |
2414 | 2403 |
2415 void CallICStub::Generate(MacroAssembler* masm) { | 2404 void CallICStub::Generate(MacroAssembler* masm) { |
2416 // rdi - function | 2405 // rdi - function |
2417 // rbx - vector | 2406 // rbx - vector |
2418 // rdx - slot id | 2407 // rdx - slot id |
2419 Isolate* isolate = masm->isolate(); | 2408 Isolate* isolate = masm->isolate(); |
2420 Label extra_checks_or_miss, slow_start; | 2409 Label extra_checks_or_miss, slow_start; |
2421 Label slow, non_function, wrap, cont; | 2410 Label slow, non_function, wrap, cont; |
2422 Label have_js_function; | 2411 Label have_js_function; |
2423 int argc = state_.arg_count(); | 2412 int argc = state_.arg_count(); |
2424 StackArgumentsAccessor args(rsp, argc); | 2413 StackArgumentsAccessor args(rsp, argc); |
2425 ParameterCount actual(argc); | 2414 ParameterCount actual(argc); |
2426 | 2415 |
2427 EmitLoadTypeFeedbackVector(masm, rbx); | 2416 EmitLoadTypeFeedbackVector(masm, rbx); |
2428 | 2417 |
2429 if (state_.stub_type() != CallIC::DEFAULT) { | |
2430 Generate_CustomFeedbackCall(masm); | |
2431 return; | |
2432 } | |
2433 | |
2434 // The checks. First, does rdi match the recorded monomorphic target? | 2418 // The checks. First, does rdi match the recorded monomorphic target? |
2435 __ SmiToInteger32(rdx, rdx); | 2419 __ SmiToInteger32(rdx, rdx); |
2436 __ cmpq(rdi, FieldOperand(rbx, rdx, times_pointer_size, | 2420 __ cmpq(rdi, FieldOperand(rbx, rdx, times_pointer_size, |
2437 FixedArray::kHeaderSize)); | 2421 FixedArray::kHeaderSize)); |
2438 __ j(not_equal, &extra_checks_or_miss); | 2422 __ j(not_equal, &extra_checks_or_miss); |
2439 | 2423 |
2440 __ bind(&have_js_function); | 2424 __ bind(&have_js_function); |
2441 if (state_.CallAsMethod()) { | 2425 if (state_.CallAsMethod()) { |
2442 EmitContinueIfStrictOrNative(masm, &cont); | 2426 EmitContinueIfStrictOrNative(masm, &cont); |
2443 | 2427 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2475 if (!FLAG_trace_ic) { | 2459 if (!FLAG_trace_ic) { |
2476 // We are going megamorphic, and we don't want to visit the runtime. | 2460 // We are going megamorphic, and we don't want to visit the runtime. |
2477 __ Move(FieldOperand(rbx, rdx, times_pointer_size, | 2461 __ Move(FieldOperand(rbx, rdx, times_pointer_size, |
2478 FixedArray::kHeaderSize), | 2462 FixedArray::kHeaderSize), |
2479 TypeFeedbackInfo::MegamorphicSentinel(isolate)); | 2463 TypeFeedbackInfo::MegamorphicSentinel(isolate)); |
2480 __ jmp(&slow_start); | 2464 __ jmp(&slow_start); |
2481 } | 2465 } |
2482 | 2466 |
2483 // We are here because tracing is on or we are going monomorphic. | 2467 // We are here because tracing is on or we are going monomorphic. |
2484 __ bind(&miss); | 2468 __ bind(&miss); |
2485 GenerateMiss(masm); | 2469 GenerateMiss(masm, IC::kCallIC_Miss); |
2486 | 2470 |
2487 // the slow case | 2471 // the slow case |
2488 __ bind(&slow_start); | 2472 __ bind(&slow_start); |
2489 // Check that function is not a smi. | 2473 // Check that function is not a smi. |
2490 __ JumpIfSmi(rdi, &non_function); | 2474 __ JumpIfSmi(rdi, &non_function); |
2491 // Check that function is a JSFunction. | 2475 // Check that function is a JSFunction. |
2492 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2476 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2493 __ j(not_equal, &slow); | 2477 __ j(not_equal, &slow); |
2494 __ jmp(&have_js_function); | 2478 __ jmp(&have_js_function); |
2495 | 2479 |
2496 // Unreachable | 2480 // Unreachable |
2497 __ int3(); | 2481 __ int3(); |
2498 } | 2482 } |
2499 | 2483 |
2500 | 2484 |
2501 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2485 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { |
2502 // Get the receiver of the function from the stack; 1 ~ return address. | 2486 // Get the receiver of the function from the stack; 1 ~ return address. |
2503 __ movp(rcx, Operand(rsp, (state_.arg_count() + 1) * kPointerSize)); | 2487 __ movp(rcx, Operand(rsp, (state_.arg_count() + 1) * kPointerSize)); |
2504 | 2488 |
2505 { | 2489 { |
2506 FrameScope scope(masm, StackFrame::INTERNAL); | 2490 FrameScope scope(masm, StackFrame::INTERNAL); |
2507 | 2491 |
2508 // Push the receiver and the function and feedback info. | 2492 // Push the receiver and the function and feedback info. |
2509 __ Push(rcx); | 2493 __ Push(rcx); |
2510 __ Push(rdi); | 2494 __ Push(rdi); |
2511 __ Push(rbx); | 2495 __ Push(rbx); |
2512 __ Integer32ToSmi(rdx, rdx); | 2496 __ Integer32ToSmi(rdx, rdx); |
2513 __ Push(rdx); | 2497 __ Push(rdx); |
2514 | 2498 |
2515 // Call the entry. | 2499 // Call the entry. |
2516 ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss), | 2500 ExternalReference miss = ExternalReference(IC_Utility(id), |
2517 masm->isolate()); | 2501 masm->isolate()); |
2518 __ CallExternalReference(miss, 4); | 2502 __ CallExternalReference(miss, 4); |
2519 | 2503 |
2520 // Move result to edi and exit the internal frame. | 2504 // Move result to edi and exit the internal frame. |
2521 __ movp(rdi, rax); | 2505 __ movp(rdi, rax); |
2522 } | 2506 } |
2523 } | 2507 } |
2524 | 2508 |
2525 | 2509 |
2526 bool CEntryStub::NeedsImmovableCode() { | 2510 bool CEntryStub::NeedsImmovableCode() { |
(...skipping 2568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5095 return_value_operand, | 5079 return_value_operand, |
5096 NULL); | 5080 NULL); |
5097 } | 5081 } |
5098 | 5082 |
5099 | 5083 |
5100 #undef __ | 5084 #undef __ |
5101 | 5085 |
5102 } } // namespace v8::internal | 5086 } } // namespace v8::internal |
5103 | 5087 |
5104 #endif // V8_TARGET_ARCH_X64 | 5088 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |