Chromium Code Reviews| 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 |