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

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: Addressed comments. 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 2344 matching lines...) Expand 10 before | Expand all | Expand 10 after
2355 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs, 2355 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs,
2356 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 2356 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
2357 __ pop(edx); 2357 __ pop(edx);
2358 __ pop(ebx); 2358 __ pop(ebx);
2359 __ pop(edi); 2359 __ pop(edi);
2360 2360
2361 __ bind(&done); 2361 __ bind(&done);
2362 } 2362 }
2363 2363
2364 2364
2365 void CallFunctionStub::Generate(MacroAssembler* masm) { 2365 static void GenericCallHelper(MacroAssembler* masm,
2366 const CallIC::State& state) {
2366 // ebx : feedback vector 2367 // ebx : feedback vector
2367 // edx : (only if ebx is not the megamorphic symbol) slot in feedback 2368 // edx : (only if ebx is not the megamorphic symbol) slot in feedback
2368 // vector (Smi) 2369 // vector (Smi)
2369 // edi : the function to call 2370 // edi : the function to call
2370 Isolate* isolate = masm->isolate(); 2371 Isolate* isolate = masm->isolate();
2371 Label slow, non_function, wrap, cont; 2372 Label slow, non_function, wrap, cont;
2372 2373
2373 if (NeedsChecks()) { 2374 if (state.IsGeneric()) {
2374 // Check that the function really is a JavaScript function. 2375 // Check that the function really is a JavaScript function.
2375 __ JumpIfSmi(edi, &non_function); 2376 __ JumpIfSmi(edi, &non_function);
2376 2377
2377 // Goto slow case if we do not have a function. 2378 // Goto slow case if we do not have a function.
2378 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2379 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2379 __ j(not_equal, &slow); 2380 __ j(not_equal, &slow);
2380
2381 if (RecordCallTarget()) {
2382 GenerateRecordCallTarget(masm);
2383 // Type information was updated. Because we may call Array, which
2384 // expects either undefined or an AllocationSite in ebx we need
2385 // to set ebx to undefined.
2386 __ mov(ebx, Immediate(isolate->factory()->undefined_value()));
2387 }
2388 } 2381 }
2389 2382
2390 // Fast-case: Just invoke the function. 2383 // Fast-case: Just invoke the function.
2391 ParameterCount actual(argc_); 2384 int argc = state.arg_count();
2385 ParameterCount actual(argc);
2392 2386
2393 if (CallAsMethod()) { 2387 if (state.CallAsMethod()) {
2394 if (NeedsChecks()) { 2388 if (state.IsGeneric()) {
2395 // Do not transform the receiver for strict mode functions. 2389 // Do not transform the receiver for strict mode functions.
2396 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2390 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2397 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), 2391 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
2398 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 2392 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
2399 __ j(not_equal, &cont); 2393 __ j(not_equal, &cont);
2400 2394
2401 // Do not transform the receiver for natives (shared already in ecx). 2395 // Do not transform the receiver for natives (shared already in ecx).
2402 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), 2396 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
2403 1 << SharedFunctionInfo::kNativeBitWithinByte); 2397 1 << SharedFunctionInfo::kNativeBitWithinByte);
2404 __ j(not_equal, &cont); 2398 __ j(not_equal, &cont);
2405 } 2399 }
2406 2400
2407 // Load the receiver from the stack. 2401 if (state.IsGeneric() || state.IsSloppyOrNonNative()) {
2408 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); 2402 // Load the receiver from the stack.
2403 __ mov(eax, Operand(esp, (argc + 1) * kPointerSize));
2409 2404
2410 if (NeedsChecks()) { 2405 if (state.IsGeneric()) {
2411 __ JumpIfSmi(eax, &wrap); 2406 __ JumpIfSmi(eax, &wrap);
2412 2407
2413 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 2408 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
2414 __ j(below, &wrap); 2409 __ j(below, &wrap);
2415 } else { 2410 } else {
2416 __ jmp(&wrap); 2411 __ jmp(&wrap);
2412 }
2417 } 2413 }
2418 2414
2419 __ bind(&cont); 2415 __ bind(&cont);
2420 } 2416 }
2421 2417
2422 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); 2418 if (state.ArgumentsMustMatch()) {
2419 __ InvokeFunction(edi, actual, actual, JUMP_FUNCTION, NullCallWrapper());
2420 } else {
2421 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2422 }
2423 2423
2424 if (NeedsChecks()) { 2424 if (state.IsGeneric()) {
2425 // Slow-case: Non-function called. 2425 // Slow-case: Non-function called.
2426 __ bind(&slow); 2426 __ bind(&slow);
2427 if (RecordCallTarget()) {
2428 // If there is a call target cache, mark it megamorphic in the
2429 // non-function case. MegamorphicSentinel is an immortal immovable
2430 // object (megamorphic symbol) so no write barrier is needed.
2431 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
2432 FixedArray::kHeaderSize),
2433 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2434 }
2435 // Check for function proxy. 2427 // Check for function proxy.
2436 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 2428 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2437 __ j(not_equal, &non_function); 2429 __ j(not_equal, &non_function);
2438 __ pop(ecx); 2430 __ pop(ecx);
2439 __ push(edi); // put proxy as additional argument under return address 2431 __ push(edi); // put proxy as additional argument under return address
2440 __ push(ecx); 2432 __ push(ecx);
2441 __ Set(eax, Immediate(argc_ + 1)); 2433 __ Set(eax, Immediate(argc + 1));
2442 __ Set(ebx, Immediate(0)); 2434 __ Set(ebx, Immediate(0));
2443 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 2435 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
2444 { 2436 {
2445 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); 2437 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2446 __ jmp(adaptor, RelocInfo::CODE_TARGET); 2438 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2447 } 2439 }
2448 2440
2449 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 2441 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2450 // of the original receiver from the call site). 2442 // of the original receiver from the call site).
2451 __ bind(&non_function); 2443 __ bind(&non_function);
2452 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); 2444 __ mov(Operand(esp, (argc + 1) * kPointerSize), edi);
2453 __ Set(eax, Immediate(argc_)); 2445 __ Set(eax, Immediate(argc));
2454 __ Set(ebx, Immediate(0)); 2446 __ Set(ebx, Immediate(0));
2455 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 2447 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
2456 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline(); 2448 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2457 __ jmp(adaptor, RelocInfo::CODE_TARGET); 2449 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2458 } 2450 }
2459 2451
2460 if (CallAsMethod()) { 2452 if (state.CallAsMethod() &&
2453 (state.IsGeneric() || state.IsSloppyOrNonNative())) {
2461 __ bind(&wrap); 2454 __ bind(&wrap);
2462 // Wrap the receiver and patch it back onto the stack. 2455 // Wrap the receiver and patch it back onto the stack.
2463 { FrameScope frame_scope(masm, StackFrame::INTERNAL); 2456 { FrameScope frame_scope(masm, StackFrame::INTERNAL);
2464 __ push(edi); 2457 __ push(edi);
2465 __ push(eax); 2458 __ push(eax);
2466 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 2459 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
2467 __ pop(edi); 2460 __ pop(edi);
2468 } 2461 }
2469 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax); 2462 __ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
2470 __ jmp(&cont); 2463 __ jmp(&cont);
2471 } 2464 }
2472 } 2465 }
2473 2466
2474 2467
2468 void CallFunctionStub::Generate(MacroAssembler* masm) {
2469 // ebx : feedback vector
2470 // edx : (only if ebx is not the megamorphic symbol) slot in feedback
2471 // vector (Smi)
2472 // edi : the function to call
2473
2474 // GenericCallHelper expresses it's options in terms of CallIC::State.
2475 CallIC::CallType call_type = CallAsMethod() ?
2476 CallIC::METHOD : CallIC::FUNCTION;
2477
2478 if (NeedsChecks()) {
2479 GenericCallHelper(masm,
2480 CallIC::State::SlowCallState(
2481 argc_,
2482 call_type));
2483 } else {
2484 GenericCallHelper(masm,
2485 CallIC::State::MonomorphicCallState(
2486 argc_,
2487 call_type,
2488 CallIC::ARGUMENTS_COUNT_UNKNOWN,
2489 CallIC::SLOPPY_OR_NONNATIVE));
2490 }
2491 }
2492
2493
2475 void CallConstructStub::Generate(MacroAssembler* masm) { 2494 void CallConstructStub::Generate(MacroAssembler* masm) {
2476 // eax : number of arguments 2495 // eax : number of arguments
2477 // ebx : feedback vector 2496 // ebx : feedback vector
2478 // edx : (only if ebx is not the megamorphic symbol) slot in feedback 2497 // edx : (only if ebx is not the megamorphic symbol) slot in feedback
2479 // vector (Smi) 2498 // vector (Smi)
2480 // edi : constructor function 2499 // edi : constructor function
2481 Label slow, non_function_call; 2500 Label slow, non_function_call;
2482 2501
2483 // Check that function is not a smi. 2502 // Check that function is not a smi.
2484 __ JumpIfSmi(edi, &non_function_call); 2503 __ JumpIfSmi(edi, &non_function_call);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2533 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 2552 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
2534 __ bind(&do_call); 2553 __ bind(&do_call);
2535 // Set expected number of arguments to zero (not changing eax). 2554 // Set expected number of arguments to zero (not changing eax).
2536 __ Set(ebx, Immediate(0)); 2555 __ Set(ebx, Immediate(0));
2537 Handle<Code> arguments_adaptor = 2556 Handle<Code> arguments_adaptor =
2538 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 2557 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
2539 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET); 2558 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET);
2540 } 2559 }
2541 2560
2542 2561
2562 void CallICStub::GenerateMonomorphicCall(MacroAssembler* masm) {
2563 GenericCallHelper(masm,
2564 CallIC::State::MonomorphicCallState(
2565 state_.arg_count(),
2566 state_.call_type(),
2567 state_.argument_check(),
2568 state_.function_attributes()));
2569 }
2570
2571
2572 void CallICStub::GenerateSlowCall(MacroAssembler* masm) {
2573 GenericCallHelper(masm,
2574 CallIC::State::SlowCallState(
2575 state_.arg_count(),
2576 state_.call_type()));
2577 }
2578
2579
2580 void CallICStub::Generate(MacroAssembler* masm) {
2581 // edi - function
2582 // ebx - vector
2583 // edx - slot id
2584 Isolate* isolate = masm->isolate();
2585 Label extra_checks_or_miss, slow;
2586
2587 // The checks. First, does edi match the recorded monomorphic target?
2588 __ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size,
2589 FixedArray::kHeaderSize));
2590 __ j(not_equal, &extra_checks_or_miss);
2591
2592 GenerateMonomorphicCall(masm);
2593
2594 __ bind(&extra_checks_or_miss);
2595 if (IsGeneric()) {
2596 Label miss_uninit;
2597
2598 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
2599 FixedArray::kHeaderSize));
2600 __ cmp(ecx, Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2601 __ j(equal, &slow);
2602 __ cmp(ecx, Immediate(TypeFeedbackInfo::UninitializedSentinel(isolate)));
2603 __ j(equal, &miss_uninit);
2604 // If we get here, go from monomorphic to megamorphic, Don't bother missing,
2605 // just update.
2606 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
2607 FixedArray::kHeaderSize),
2608 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2609 __ jmp(&slow);
2610
2611 __ bind(&miss_uninit);
2612 }
2613
2614 GenerateMiss(masm);
2615
2616 // the slow case
2617 __ bind(&slow);
2618 GenerateSlowCall(masm);
2619 }
2620
2621
2622 void CallICStub::GenerateMiss(MacroAssembler* masm) {
2623 // Get the receiver of the function from the stack; 1 ~ return address.
2624 __ mov(ecx, Operand(esp, (state_.arg_count() + 1) * kPointerSize));
2625
2626 {
2627 FrameScope scope(masm, StackFrame::INTERNAL);
2628
2629 // Push the receiver and the function and feedback info.
2630 __ push(ecx);
2631 __ push(edi);
2632 __ push(ebx);
2633 __ push(edx);
2634
2635 // Call the entry.
2636 CEntryStub stub(1);
2637 __ mov(eax, Immediate(4));
2638 __ mov(ebx, Immediate(ExternalReference(IC_Utility(IC::kCallIC_Miss),
2639 masm->isolate())));
2640 __ CallStub(&stub);
2641
2642 // Move result to edi and exit the internal frame.
2643 __ mov(edi, eax);
2644 }
2645 }
2646
2647
2543 bool CEntryStub::NeedsImmovableCode() { 2648 bool CEntryStub::NeedsImmovableCode() {
2544 return false; 2649 return false;
2545 } 2650 }
2546 2651
2547 2652
2548 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2653 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2549 CEntryStub::GenerateAheadOfTime(isolate); 2654 CEntryStub::GenerateAheadOfTime(isolate);
2550 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 2655 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2551 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 2656 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2552 // It is important that the store buffer overflow stubs are generated first. 2657 // It is important that the store buffer overflow stubs are generated first.
2553 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 2658 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2554 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 2659 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
2660 // CallICStub::GenerateAheadOfTime(isolate);
2555 if (Serializer::enabled()) { 2661 if (Serializer::enabled()) {
2556 PlatformFeatureScope sse2(SSE2); 2662 PlatformFeatureScope sse2(SSE2);
2557 BinaryOpICStub::GenerateAheadOfTime(isolate); 2663 BinaryOpICStub::GenerateAheadOfTime(isolate);
2558 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 2664 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
2559 } else { 2665 } else {
2560 BinaryOpICStub::GenerateAheadOfTime(isolate); 2666 BinaryOpICStub::GenerateAheadOfTime(isolate);
2561 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 2667 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
2562 } 2668 }
2563 } 2669 }
2564 2670
(...skipping 2831 matching lines...) Expand 10 before | Expand all | Expand 10 after
5396 Operand(ebp, 7 * kPointerSize), 5502 Operand(ebp, 7 * kPointerSize),
5397 NULL); 5503 NULL);
5398 } 5504 }
5399 5505
5400 5506
5401 #undef __ 5507 #undef __
5402 5508
5403 } } // namespace v8::internal 5509 } } // namespace v8::internal
5404 5510
5405 #endif // V8_TARGET_ARCH_IA32 5511 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698