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

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: Comments addressed. 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(
2425 MacroAssembler* masm,
2426 CallIC::StubType stub_type,
2427 CallIC::ArgumentCheck argument_check,
2428 CallIC::FunctionAttributes attributes) {
2429 Isolate* isolate = masm->isolate();
2430 Label slow, non_function, cont, wrap;
2431 ParameterCount actual(arg_count());
2432
2433 if (stub_type == CallIC::GENERIC) {
2434 // Check that the function really is a JavaScript function.
2435 __ JumpIfSmi(edi, &non_function);
2436
2437 // Goto slow case if we do not have a function.
2438 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2439 __ j(not_equal, &slow);
2440 }
2441
2442 if (call_type() == CallIC::METHOD) {
2443 if (stub_type == CallIC::GENERIC) {
2444 // Do not transform the receiver for strict mode functions.
2445 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2446 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
2447 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
2448 __ j(not_equal, &cont);
2449
2450 // Do not transform the receiver for natives (shared already in ecx).
2451 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
2452 1 << SharedFunctionInfo::kNativeBitWithinByte);
2453 __ j(not_equal, &cont);
2454 }
2455
2456 if (attributes == CallIC::NOT_STRICT_OR_NATIVE) {
Toon Verwaest 2014/03/24 10:25:44 CallIC::SLOPPY Seems like in this case you don't
mvstanton 2014/03/25 15:34:50 Good catch, thanks. Done.
2457 // Load the receiver from the stack.
2458 __ mov(eax, Operand(esp, (arg_count() + 1) * kPointerSize));
2459
2460 __ JumpIfSmi(eax, &wrap);
2461
2462 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
2463 __ j(below, &wrap);
2464 }
2465
2466 __ bind(&cont);
2467 }
2468
2469 if (argument_check == CallIC::ARGUMENTS_MATCH) {
Toon Verwaest 2014/03/24 10:25:44 ARGUMENTS_MUST_MATCH, to distinguish from the othe
mvstanton 2014/03/25 15:34:50 Done.
2470 __ InvokeFunction(edi, actual, actual, JUMP_FUNCTION, NullCallWrapper());
2471 } else {
2472 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2473 }
2474
2475 if (stub_type == CallIC::GENERIC) {
2476 // Slow-case: Non-function called.
2477 __ bind(&slow);
2478 // Check for function proxy.
2479 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2480 __ j(not_equal, &non_function);
2481 __ pop(ecx);
2482 __ push(edi); // put proxy as additional argument under return address
2483 __ push(ecx);
2484 __ Set(eax, Immediate(arg_count() + 1));
2485 __ Set(ebx, Immediate(0));
2486 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
2487 {
2488 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2489 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2490 }
2491
2492 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2493 // of the original receiver from the call site).
2494 __ bind(&non_function);
2495 __ mov(Operand(esp, (arg_count() + 1) * kPointerSize), edi);
2496 __ Set(eax, Immediate(arg_count()));
2497 __ Set(ebx, Immediate(0));
2498 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
2499 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2500 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2501 }
2502
2503 if (call_type() == CallIC::METHOD &&
2504 attributes == CallIC::NOT_STRICT_OR_NATIVE) {
2505 __ bind(&wrap);
2506 // Wrap the receiver and patch it back onto the stack.
2507 { FrameScope frame_scope(masm, StackFrame::INTERNAL);
2508 __ push(edi);
2509 __ push(eax);
2510 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
2511 __ pop(edi);
2512 }
2513 __ mov(Operand(esp, (arg_count() + 1) * kPointerSize), eax);
2514 __ jmp(&cont);
2515 }
2516 }
2517
2518
2519 void CallICStub::Generate(MacroAssembler* masm) {
2520 // edi - function
2521 // ebx - vector
2522 // edx - slot id
2523 Isolate* isolate = masm->isolate();
2524 Label extra_checks_or_miss, slow;
2525
2526 // The checks. First, does edi match the recorded monomorphic target?
2527 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
Toon Verwaest 2014/03/24 10:25:44 __ cmp(edi, Field...
mvstanton 2014/03/25 15:34:50 Done.
2528 FixedArray::kHeaderSize));
2529 __ cmp(ecx, edi);
2530 __ j(not_equal, &extra_checks_or_miss);
2531
2532 if (stub_type() != CallIC::MONOMORPHIC) {
Toon Verwaest 2014/03/24 10:25:44 stub_type() == CallIC::DEFAULT_MONOMORPHIC
mvstanton 2014/03/25 15:34:50 Done.
2533 GenerateCall(masm,
2534 CallIC::MONOMORPHIC,
2535 CallIC::ARGUMENTS_MATCH,
Toon Verwaest 2014/03/24 10:25:44 Can we merge this with the non-default case by jus
mvstanton 2014/03/25 15:34:50 Yes indeed, thanks!
2536 CallIC::NOT_STRICT_OR_NATIVE);
Toon Verwaest 2014/03/24 10:25:44 CallIC::default_strict_or_native() { return argu
2537 } else {
2538 GenerateCall(masm, CallIC::MONOMORPHIC,
2539 argument_check(),
2540 function_attributes());
2541 }
2542
2543 __ bind(&extra_checks_or_miss);
2544 if (stub_type() != CallIC::MONOMORPHIC) {
2545 Label miss_uninit;
2546
2547 __ cmp(ecx, Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2548 __ j(equal, &slow);
2549 __ cmp(ecx, Immediate(TypeFeedbackInfo::UninitializedSentinel(isolate)));
2550 __ j(equal, &miss_uninit);
2551 // If we get here, go from monomorphic to megamorphic, Don't bother missing,
2552 // just update.
2553 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
2554 FixedArray::kHeaderSize),
2555 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2556 __ jmp(&slow);
2557
2558 __ bind(&miss_uninit);
2559 }
2560
2561 GenerateMiss(masm);
2562
2563 // the slow case
2564 __ bind(&slow);
2565 GenerateCall(masm, CallIC::GENERIC, CallIC::ARGUMENTS_DONT_MATCH,
2566 CallIC::NOT_STRICT_OR_NATIVE);
2567 }
2568
2569
2570 void CallICStub::GenerateMiss(MacroAssembler* masm) {
2571 // Get the receiver of the function from the stack; 1 ~ return address.
2572 __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize));
2573
2574 {
2575 FrameScope scope(masm, StackFrame::INTERNAL);
2576
2577 // Push the receiver and the function and feedback info.
2578 __ push(ecx);
2579 __ push(edi);
2580 __ push(ebx);
2581 __ push(edx);
2582
2583 // Call the entry.
2584 CEntryStub stub(1);
2585 __ mov(eax, Immediate(4));
2586 __ mov(ebx, Immediate(ExternalReference(IC_Utility(IC::kCallIC_Miss),
2587 masm->isolate())));
2588 __ CallStub(&stub);
2589
2590 // Move result to edi and exit the internal frame.
2591 __ mov(edi, eax);
2592 }
2593 }
2594
2595
2424 void CallFunctionStub::Generate(MacroAssembler* masm) { 2596 void CallFunctionStub::Generate(MacroAssembler* masm) {
2425 // ebx : feedback vector 2597 // ebx : feedback vector
2426 // edx : (only if ebx is not the megamorphic symbol) slot in feedback 2598 // edx : (only if ebx is not the megamorphic symbol) slot in feedback
2427 // vector (Smi) 2599 // vector (Smi)
2428 // edi : the function to call 2600 // edi : the function to call
2429 Isolate* isolate = masm->isolate(); 2601 Isolate* isolate = masm->isolate();
2430 Label slow, non_function, wrap, cont; 2602 Label slow, non_function, wrap, cont;
2431 2603
2432 if (NeedsChecks()) { 2604 if (NeedsChecks()) {
2433 // Check that the function really is a JavaScript function. 2605 // Check that the function really is a JavaScript function.
2434 __ JumpIfSmi(edi, &non_function); 2606 __ JumpIfSmi(edi, &non_function);
2435 2607
2436 // Goto slow case if we do not have a function. 2608 // Goto slow case if we do not have a function.
2437 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2609 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2438 __ j(not_equal, &slow); 2610 __ j(not_equal, &slow);
2439
2440 if (RecordCallTarget()) {
2441 GenerateRecordCallTarget(masm);
2442 }
2443 } 2611 }
2444 2612
2445 // Fast-case: Just invoke the function. 2613 // Fast-case: Just invoke the function.
2446 ParameterCount actual(argc_); 2614 ParameterCount actual(argc_);
2447 2615
2448 if (CallAsMethod()) { 2616 if (CallAsMethod()) {
2449 if (NeedsChecks()) { 2617 if (NeedsChecks()) {
2450 // Do not transform the receiver for strict mode functions. 2618 // Do not transform the receiver for strict mode functions.
2451 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2619 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2452 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), 2620 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
(...skipping 19 matching lines...) Expand all
2472 } 2640 }
2473 2641
2474 __ bind(&cont); 2642 __ bind(&cont);
2475 } 2643 }
2476 2644
2477 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); 2645 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2478 2646
2479 if (NeedsChecks()) { 2647 if (NeedsChecks()) {
2480 // Slow-case: Non-function called. 2648 // Slow-case: Non-function called.
2481 __ bind(&slow); 2649 __ 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. 2650 // Check for function proxy.
2491 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 2651 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2492 __ j(not_equal, &non_function); 2652 __ j(not_equal, &non_function);
2493 __ pop(ecx); 2653 __ pop(ecx);
2494 __ push(edi); // put proxy as additional argument under return address 2654 __ push(edi); // put proxy as additional argument under return address
2495 __ push(ecx); 2655 __ push(ecx);
2496 __ Set(eax, Immediate(argc_ + 1)); 2656 __ Set(eax, Immediate(argc_ + 1));
2497 __ Set(ebx, Immediate(0)); 2657 __ Set(ebx, Immediate(0));
2498 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 2658 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
2499 { 2659 {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2579 } 2739 }
2580 2740
2581 2741
2582 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2742 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2583 CEntryStub::GenerateAheadOfTime(isolate); 2743 CEntryStub::GenerateAheadOfTime(isolate);
2584 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 2744 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2585 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 2745 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2586 // It is important that the store buffer overflow stubs are generated first. 2746 // It is important that the store buffer overflow stubs are generated first.
2587 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 2747 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2588 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 2748 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
2749 // CallICStub::GenerateAheadOfTime(isolate);
2589 if (Serializer::enabled()) { 2750 if (Serializer::enabled()) {
2590 PlatformFeatureScope sse2(SSE2); 2751 PlatformFeatureScope sse2(SSE2);
2591 BinaryOpICStub::GenerateAheadOfTime(isolate); 2752 BinaryOpICStub::GenerateAheadOfTime(isolate);
2592 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 2753 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
2593 } else { 2754 } else {
2594 BinaryOpICStub::GenerateAheadOfTime(isolate); 2755 BinaryOpICStub::GenerateAheadOfTime(isolate);
2595 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 2756 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
2596 } 2757 }
2597 } 2758 }
2598 2759
(...skipping 2852 matching lines...) Expand 10 before | Expand all | Expand 10 after
5451 Operand(ebp, 7 * kPointerSize), 5612 Operand(ebp, 7 * kPointerSize),
5452 NULL); 5613 NULL);
5453 } 5614 }
5454 5615
5455 5616
5456 #undef __ 5617 #undef __
5457 5618
5458 } } // namespace v8::internal 5619 } } // namespace v8::internal
5459 5620
5460 #endif // V8_TARGET_ARCH_IA32 5621 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/full-codegen.h ('k') | src/ia32/debug-ia32.cc » ('j') | src/ic.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698