Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 172523002: Create a function call IC (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 2403 matching lines...) Expand 10 before | Expand all | Expand 10 after
2414 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs, 2414 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs,
2415 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 2415 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
2416 __ pop(edx); 2416 __ pop(edx);
2417 __ pop(ebx); 2417 __ pop(ebx);
2418 __ pop(edi); 2418 __ pop(edi);
2419 2419
2420 __ bind(&done); 2420 __ bind(&done);
2421 } 2421 }
2422 2422
2423 2423
2424 void CallICStub::GenerateCall(MacroAssembler* masm, bool monomorphic,
Toon Verwaest 2014/03/10 13:50:44 one arg per line
mvstanton 2014/03/20 15:51:53 Done.
2425 bool args_match, bool strict_or_native) {
2426 Isolate* isolate = masm->isolate();
2427 Label slow, non_function, cont, wrap;
2428 ParameterCount actual(arg_count());
2429
2430 if (!monomorphic) {
2431 // Check that the function really is a JavaScript function.
2432 __ JumpIfSmi(edi, &non_function);
2433
2434 // Goto slow case if we do not have a function.
2435 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2436 __ j(not_equal, &slow);
2437 }
2438
2439 if (call_as_method()) {
2440 if (!monomorphic) {
2441 // Do not transform the receiver for strict mode functions.
2442 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2443 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
2444 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
2445 __ j(not_equal, &cont);
2446
2447 // Do not transform the receiver for natives (shared already in ecx).
2448 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
2449 1 << SharedFunctionInfo::kNativeBitWithinByte);
2450 __ j(not_equal, &cont);
2451 }
2452
2453 if (!strict_or_native) {
2454 // Load the receiver from the stack.
2455 __ mov(eax, Operand(esp, (arg_count() + 1) * kPointerSize));
2456
2457 __ JumpIfSmi(eax, &wrap);
2458
2459 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
2460 __ j(below, &wrap);
2461 }
2462
2463 __ bind(&cont);
2464 }
2465
2466 if (args_match) {
2467 __ InvokeFunction(edi, actual, actual, JUMP_FUNCTION, NullCallWrapper());
2468 } else {
2469 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2470 }
2471
2472 if (!monomorphic) {
2473 // Slow-case: Non-function called.
2474 __ bind(&slow);
2475 // Check for function proxy.
2476 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2477 __ j(not_equal, &non_function);
2478 __ pop(ecx);
2479 __ push(edi); // put proxy as additional argument under return address
2480 __ push(ecx);
2481 __ Set(eax, Immediate(arg_count() + 1));
2482 __ Set(ebx, Immediate(0));
2483 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
2484 {
2485 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2486 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2487 }
2488
2489 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2490 // of the original receiver from the call site).
2491 __ bind(&non_function);
2492 __ mov(Operand(esp, (arg_count() + 1) * kPointerSize), edi);
2493 __ Set(eax, Immediate(arg_count()));
2494 __ Set(ebx, Immediate(0));
2495 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
2496 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2497 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2498 }
2499
2500 if (call_as_method() && !strict_or_native) {
2501 __ bind(&wrap);
2502 // Wrap the receiver and patch it back onto the stack.
2503 { FrameScope frame_scope(masm, StackFrame::INTERNAL);
2504 __ push(edi);
2505 __ push(eax);
2506 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
2507 __ pop(edi);
2508 }
2509 __ mov(Operand(esp, (arg_count() + 1) * kPointerSize), eax);
2510 __ jmp(&cont);
2511 }
2512 }
2513
2514
2515 void CallICStub::Generate(MacroAssembler* masm) {
2516 // edi - function
2517 // ebx - vector
2518 // edx - slot id
2519 Label mono, slow;
2520
2521 Isolate* isolate = masm->isolate();
2522 if (!monomorphic()) {
2523 Label miss_uninit;
2524
2525 // The checks. First, does edi match the cell?
2526 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
2527 FixedArray::kHeaderSize));
2528 __ cmp(ecx, edi);
Toon Verwaest 2014/03/10 13:50:44 Wouldn't it be faster to flip over the conditions,
mvstanton 2014/03/20 15:51:53 Excellent idea, it reads cleaner too.
2529 __ j(equal, &mono);
2530 __ cmp(ecx, Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2531 __ j(equal, &slow);
2532 __ cmp(ecx, Immediate(TypeFeedbackInfo::UninitializedSentinel(isolate)));
2533 __ j(equal, &miss_uninit);
2534 // If we got here we went megamorphic. Don't bother missing, just update.
Toon Verwaest 2014/03/10 13:50:44 we went -> If we get here, go from monomorphic to
mvstanton 2014/03/20 15:51:53 Done.
2535 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
2536 FixedArray::kHeaderSize),
2537 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2538 __ jmp(&slow);
2539
2540 __ bind(&miss_uninit);
2541 GenerateMiss(masm);
2542 __ jmp(&slow);
2543 } else {
2544 // Verify still monomorphic, miss otherwise
Toon Verwaest 2014/03/10 13:50:44 Verify whether the input function matches the reco
mvstanton 2014/03/20 15:51:53 After rearranging the function, I kept your ideal
2545 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
2546 FixedArray::kHeaderSize));
2547 __ cmp(ecx, edi);
2548 __ j(equal, &mono);
Toon Verwaest 2014/03/10 13:50:44 Same here as above. This path should be inlined he
mvstanton 2014/03/20 15:51:53 Done.
2549 // Uh-oh, we missed, have to fall back to slow stub, go ahead and patch but
2550 // we still have to handle the slow case.
2551 GenerateMiss(masm);
2552 __ jmp(&slow);
2553 }
2554
2555 __ bind(&mono);
2556 if (!monomorphic()) {
2557 GenerateCall(masm, true, true, false);
2558 } else {
2559 GenerateCall(masm, true, args_match(), strict_native());
2560 }
2561
2562 // the slow case
2563 __ bind(&slow);
2564 GenerateCall(masm, false, false, false);
2565 }
2566
2567
2568 void CallICStub::GenerateMiss(MacroAssembler* masm) {
2569 // Get the receiver of the function from the stack; 1 ~ return address.
2570 __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize));
2571
2572 {
2573 FrameScope scope(masm, StackFrame::INTERNAL);
2574
2575 // Push the receiver and the function and feedback info.
2576 __ push(ecx);
2577 __ push(edi);
2578 __ push(ebx);
2579 __ push(edx);
2580
2581 // Call the entry.
2582 CEntryStub stub(1);
2583 __ mov(eax, Immediate(4));
2584 __ mov(ebx, Immediate(ExternalReference(IC_Utility(IC::kCallIC_Miss),
2585 masm->isolate())));
2586 __ CallStub(&stub);
2587
2588 // Move result to edi and exit the internal frame.
2589 __ mov(edi, eax);
2590 }
2591 }
2592
2593
2424 void CallFunctionStub::Generate(MacroAssembler* masm) { 2594 void CallFunctionStub::Generate(MacroAssembler* masm) {
2425 // ebx : feedback vector 2595 // ebx : feedback vector
2426 // edx : (only if ebx is not the megamorphic symbol) slot in feedback 2596 // edx : (only if ebx is not the megamorphic symbol) slot in feedback
2427 // vector (Smi) 2597 // vector (Smi)
2428 // edi : the function to call 2598 // edi : the function to call
2429 Isolate* isolate = masm->isolate(); 2599 Isolate* isolate = masm->isolate();
2430 Label slow, non_function, wrap, cont; 2600 Label slow, non_function, wrap, cont;
2431 2601
2432 if (NeedsChecks()) { 2602 if (NeedsChecks()) {
2433 // Check that the function really is a JavaScript function. 2603 // Check that the function really is a JavaScript function.
2434 __ JumpIfSmi(edi, &non_function); 2604 __ JumpIfSmi(edi, &non_function);
2435 2605
2436 // Goto slow case if we do not have a function. 2606 // Goto slow case if we do not have a function.
2437 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2607 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2438 __ j(not_equal, &slow); 2608 __ j(not_equal, &slow);
2439
2440 if (RecordCallTarget()) {
2441 GenerateRecordCallTarget(masm);
2442 }
2443 } 2609 }
2444 2610
2445 // Fast-case: Just invoke the function. 2611 // Fast-case: Just invoke the function.
2446 ParameterCount actual(argc_); 2612 ParameterCount actual(argc_);
2447 2613
2448 if (CallAsMethod()) { 2614 if (CallAsMethod()) {
2449 if (NeedsChecks()) { 2615 if (NeedsChecks()) {
2450 // Do not transform the receiver for strict mode functions. 2616 // Do not transform the receiver for strict mode functions.
2451 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2617 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2452 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), 2618 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
(...skipping 19 matching lines...) Expand all
2472 } 2638 }
2473 2639
2474 __ bind(&cont); 2640 __ bind(&cont);
2475 } 2641 }
2476 2642
2477 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); 2643 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2478 2644
2479 if (NeedsChecks()) { 2645 if (NeedsChecks()) {
2480 // Slow-case: Non-function called. 2646 // Slow-case: Non-function called.
2481 __ bind(&slow); 2647 __ bind(&slow);
2482 if (RecordCallTarget()) {
2483 // If there is a call target cache, mark it megamorphic in the
2484 // non-function case. MegamorphicSentinel is an immortal immovable
2485 // object (megamorphic symbol) so no write barrier is needed.
2486 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
2487 FixedArray::kHeaderSize),
2488 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2489 }
2490 // Check for function proxy. 2648 // Check for function proxy.
2491 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 2649 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2492 __ j(not_equal, &non_function); 2650 __ j(not_equal, &non_function);
2493 __ pop(ecx); 2651 __ pop(ecx);
2494 __ push(edi); // put proxy as additional argument under return address 2652 __ push(edi); // put proxy as additional argument under return address
2495 __ push(ecx); 2653 __ push(ecx);
2496 __ Set(eax, Immediate(argc_ + 1)); 2654 __ Set(eax, Immediate(argc_ + 1));
2497 __ Set(ebx, Immediate(0)); 2655 __ Set(ebx, Immediate(0));
2498 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 2656 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
2499 { 2657 {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2579 } 2737 }
2580 2738
2581 2739
2582 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2740 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2583 CEntryStub::GenerateAheadOfTime(isolate); 2741 CEntryStub::GenerateAheadOfTime(isolate);
2584 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 2742 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2585 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 2743 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2586 // It is important that the store buffer overflow stubs are generated first. 2744 // It is important that the store buffer overflow stubs are generated first.
2587 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 2745 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2588 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 2746 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
2747 // CallICStub::GenerateAheadOfTime(isolate);
2589 if (Serializer::enabled()) { 2748 if (Serializer::enabled()) {
2590 PlatformFeatureScope sse2(SSE2); 2749 PlatformFeatureScope sse2(SSE2);
2591 BinaryOpICStub::GenerateAheadOfTime(isolate); 2750 BinaryOpICStub::GenerateAheadOfTime(isolate);
2592 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 2751 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
2593 } else { 2752 } else {
2594 BinaryOpICStub::GenerateAheadOfTime(isolate); 2753 BinaryOpICStub::GenerateAheadOfTime(isolate);
2595 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 2754 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
2596 } 2755 }
2597 } 2756 }
2598 2757
(...skipping 2852 matching lines...) Expand 10 before | Expand all | Expand 10 after
5451 Operand(ebp, 7 * kPointerSize), 5610 Operand(ebp, 7 * kPointerSize),
5452 NULL); 5611 NULL);
5453 } 5612 }
5454 5613
5455 5614
5456 #undef __ 5615 #undef __
5457 5616
5458 } } // namespace v8::internal 5617 } } // namespace v8::internal
5459 5618
5460 #endif // V8_TARGET_ARCH_IA32 5619 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698