OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |