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

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

Issue 247373002: CallICStub with a "never patch" approach until customization. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Ports. Created 6 years, 7 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
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/debug-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2345 matching lines...) Expand 10 before | Expand all | Expand 10 after
2356 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs, 2356 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs,
2357 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 2357 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
2358 __ pop(edx); 2358 __ pop(edx);
2359 __ pop(ebx); 2359 __ pop(ebx);
2360 __ pop(edi); 2360 __ pop(edi);
2361 2361
2362 __ bind(&done); 2362 __ bind(&done);
2363 } 2363 }
2364 2364
2365 2365
2366 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) {
2367 // Do not transform the receiver for strict mode functions.
2368 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2369 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
2370 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
2371 __ j(not_equal, cont);
2372
2373 // Do not transform the receiver for natives (shared already in ecx).
2374 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
2375 1 << SharedFunctionInfo::kNativeBitWithinByte);
2376 __ j(not_equal, cont);
2377 }
2378
2379
2380 static void EmitSlowCase(Isolate* isolate,
2381 MacroAssembler* masm,
2382 int argc,
2383 Label* non_function) {
2384 // Check for function proxy.
2385 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2386 __ j(not_equal, non_function);
2387 __ pop(ecx);
2388 __ push(edi); // put proxy as additional argument under return address
2389 __ push(ecx);
2390 __ Move(eax, Immediate(argc + 1));
2391 __ Move(ebx, Immediate(0));
2392 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
2393 {
2394 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2395 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2396 }
2397
2398 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2399 // of the original receiver from the call site).
2400 __ bind(non_function);
2401 __ mov(Operand(esp, (argc + 1) * kPointerSize), edi);
2402 __ Move(eax, Immediate(argc));
2403 __ Move(ebx, Immediate(0));
2404 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
2405 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2406 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2407 }
2408
2409
2410 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
2411 // Wrap the receiver and patch it back onto the stack.
2412 { FrameScope frame_scope(masm, StackFrame::INTERNAL);
2413 __ push(edi);
2414 __ push(eax);
2415 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
2416 __ pop(edi);
2417 }
2418 __ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
2419 __ jmp(cont);
2420 }
2421
2422
2366 void CallFunctionStub::Generate(MacroAssembler* masm) { 2423 void CallFunctionStub::Generate(MacroAssembler* masm) {
2367 // ebx : feedback vector
2368 // edx : (only if ebx is not the megamorphic symbol) slot in feedback
2369 // vector (Smi)
2370 // edi : the function to call 2424 // edi : the function to call
2371 Isolate* isolate = masm->isolate(); 2425 Isolate* isolate = masm->isolate();
2372 Label slow, non_function, wrap, cont; 2426 Label slow, non_function, wrap, cont;
2373 2427
2374 if (NeedsChecks()) { 2428 if (NeedsChecks()) {
2375 // Check that the function really is a JavaScript function. 2429 // Check that the function really is a JavaScript function.
2376 __ JumpIfSmi(edi, &non_function); 2430 __ JumpIfSmi(edi, &non_function);
2377 2431
2378 // Goto slow case if we do not have a function. 2432 // Goto slow case if we do not have a function.
2379 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2433 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2380 __ j(not_equal, &slow); 2434 __ j(not_equal, &slow);
2381
2382 if (RecordCallTarget()) {
2383 GenerateRecordCallTarget(masm);
2384 // Type information was updated. Because we may call Array, which
2385 // expects either undefined or an AllocationSite in ebx we need
2386 // to set ebx to undefined.
2387 __ mov(ebx, Immediate(isolate->factory()->undefined_value()));
2388 }
2389 } 2435 }
2390 2436
2391 // Fast-case: Just invoke the function. 2437 // Fast-case: Just invoke the function.
2392 ParameterCount actual(argc_); 2438 ParameterCount actual(argc_);
2393 2439
2394 if (CallAsMethod()) { 2440 if (CallAsMethod()) {
2395 if (NeedsChecks()) { 2441 if (NeedsChecks()) {
2396 // Do not transform the receiver for strict mode functions. 2442 EmitContinueIfStrictOrNative(masm, &cont);
2397 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2398 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset),
2399 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
2400 __ j(not_equal, &cont);
2401
2402 // Do not transform the receiver for natives (shared already in ecx).
2403 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset),
2404 1 << SharedFunctionInfo::kNativeBitWithinByte);
2405 __ j(not_equal, &cont);
2406 } 2443 }
2407 2444
2408 // Load the receiver from the stack. 2445 // Load the receiver from the stack.
2409 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); 2446 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize));
2410 2447
2411 if (NeedsChecks()) { 2448 if (NeedsChecks()) {
2412 __ JumpIfSmi(eax, &wrap); 2449 __ JumpIfSmi(eax, &wrap);
2413 2450
2414 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 2451 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
2415 __ j(below, &wrap); 2452 __ j(below, &wrap);
2416 } else { 2453 } else {
2417 __ jmp(&wrap); 2454 __ jmp(&wrap);
2418 } 2455 }
2419 2456
2420 __ bind(&cont); 2457 __ bind(&cont);
2421 } 2458 }
2422 2459
2423 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); 2460 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2424 2461
2425 if (NeedsChecks()) { 2462 if (NeedsChecks()) {
2426 // Slow-case: Non-function called. 2463 // Slow-case: Non-function called.
2427 __ bind(&slow); 2464 __ bind(&slow);
2428 if (RecordCallTarget()) { 2465 // (non_function is bound in EmitSlowCase)
Toon Verwaest 2014/04/29 15:20:30 Drop () around the sentence
2429 // If there is a call target cache, mark it megamorphic in the 2466 EmitSlowCase(isolate, masm, argc_, &non_function);
2430 // non-function case. MegamorphicSentinel is an immortal immovable
2431 // object (megamorphic symbol) so no write barrier is needed.
2432 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
2433 FixedArray::kHeaderSize),
2434 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2435 }
2436 // Check for function proxy.
2437 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
2438 __ j(not_equal, &non_function);
2439 __ pop(ecx);
2440 __ push(edi); // put proxy as additional argument under return address
2441 __ push(ecx);
2442 __ Move(eax, Immediate(argc_ + 1));
2443 __ Move(ebx, Immediate(0));
2444 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY);
2445 {
2446 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2447 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2448 }
2449
2450 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2451 // of the original receiver from the call site).
2452 __ bind(&non_function);
2453 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi);
2454 __ Move(eax, Immediate(argc_));
2455 __ Move(ebx, Immediate(0));
2456 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
2457 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
2458 __ jmp(adaptor, RelocInfo::CODE_TARGET);
2459 } 2467 }
2460 2468
2461 if (CallAsMethod()) { 2469 if (CallAsMethod()) {
2462 __ bind(&wrap); 2470 __ bind(&wrap);
2463 // Wrap the receiver and patch it back onto the stack. 2471 EmitWrapCase(masm, argc_, &cont);
2464 { FrameScope frame_scope(masm, StackFrame::INTERNAL);
2465 __ push(edi);
2466 __ push(eax);
2467 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
2468 __ pop(edi);
2469 }
2470 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax);
2471 __ jmp(&cont);
2472 } 2472 }
2473 } 2473 }
2474 2474
2475 2475
2476 void CallConstructStub::Generate(MacroAssembler* masm) { 2476 void CallConstructStub::Generate(MacroAssembler* masm) {
2477 // eax : number of arguments 2477 // eax : number of arguments
2478 // ebx : feedback vector 2478 // ebx : feedback vector
2479 // edx : (only if ebx is not the megamorphic symbol) slot in feedback 2479 // edx : (only if ebx is not the megamorphic symbol) slot in feedback
2480 // vector (Smi) 2480 // vector (Smi)
2481 // edi : constructor function 2481 // edi : constructor function
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2534 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 2534 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
2535 __ bind(&do_call); 2535 __ bind(&do_call);
2536 // Set expected number of arguments to zero (not changing eax). 2536 // Set expected number of arguments to zero (not changing eax).
2537 __ Move(ebx, Immediate(0)); 2537 __ Move(ebx, Immediate(0));
2538 Handle<Code> arguments_adaptor = 2538 Handle<Code> arguments_adaptor =
2539 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 2539 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
2540 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET); 2540 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET);
2541 } 2541 }
2542 2542
2543 2543
2544 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
2545 __ mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2546 __ mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
2547 __ mov(vector, FieldOperand(vector,
2548 SharedFunctionInfo::kFeedbackVectorOffset));
2549 }
2550
2551
2552 void CallICStub::Generate(MacroAssembler* masm) {
2553 // edi - function
2554 // edx - slot id
2555 Isolate* isolate = masm->isolate();
2556 Label extra_checks_or_miss, slow_start;
2557 Label slow, non_function, wrap, cont;
2558 Label have_js_function;
2559 int argc = state_.arg_count();
2560 ParameterCount actual(argc);
2561
2562 EmitLoadTypeFeedbackVector(masm, ebx);
2563
2564 // The checks. First, does edi match the recorded monomorphic target?
2565 __ cmp(edi, FieldOperand(ebx, edx, times_half_pointer_size,
2566 FixedArray::kHeaderSize));
2567 __ j(not_equal, &extra_checks_or_miss);
2568
2569 __ bind(&have_js_function);
2570 if (state_.CallAsMethod()) {
2571 EmitContinueIfStrictOrNative(masm, &cont);
2572
2573 // Load the receiver from the stack.
2574 __ mov(eax, Operand(esp, (argc + 1) * kPointerSize));
2575
2576 __ JumpIfSmi(eax, &wrap);
2577
2578 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
2579 __ j(below, &wrap);
2580
2581 __ bind(&cont);
2582 }
2583
2584 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper());
2585
2586 __ bind(&slow);
2587 EmitSlowCase(isolate, masm, argc, &non_function);
2588
2589 if (state_.CallAsMethod()) {
2590 __ bind(&wrap);
2591 EmitWrapCase(masm, argc, &cont);
2592 }
2593
2594 __ bind(&extra_checks_or_miss);
2595 Label miss;
2596
2597 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
2598 FixedArray::kHeaderSize));
2599 __ cmp(ecx, Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2600 __ j(equal, &slow_start);
2601 __ cmp(ecx, Immediate(TypeFeedbackInfo::UninitializedSentinel(isolate)));
2602 __ j(equal, &miss);
2603
2604 if (!FLAG_trace_ic) {
2605 // We are going megamorphic, and we don't want to visit the runtime.
2606 __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
2607 FixedArray::kHeaderSize),
2608 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate)));
2609 __ jmp(&slow_start);
2610 }
2611
2612 // We are here because tracing is on or we are going monomorphic.
2613 __ bind(&miss);
2614 GenerateMiss(masm);
2615
2616 // the slow case
2617 __ bind(&slow_start);
2618
2619 // Check that the function really is a JavaScript function.
2620 __ JumpIfSmi(edi, &non_function);
2621
2622 // Goto slow case if we do not have a function.
2623 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2624 __ j(not_equal, &slow);
2625 __ jmp(&have_js_function);
2626
2627 // Unreachable
2628 __ int3();
2629 }
2630
2631
2632 void CallICStub::GenerateMiss(MacroAssembler* masm) {
2633 // Get the receiver of the function from the stack; 1 ~ return address.
2634 __ mov(ecx, Operand(esp, (state_.arg_count() + 1) * kPointerSize));
2635
2636 {
2637 FrameScope scope(masm, StackFrame::INTERNAL);
2638
2639 // Push the receiver and the function and feedback info.
2640 __ push(ecx);
2641 __ push(edi);
2642 __ push(ebx);
2643 __ push(edx);
2644
2645 // Call the entry.
2646 ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss),
2647 masm->isolate());
2648 __ CallExternalReference(miss, 4);
2649
2650 // Move result to edi and exit the internal frame.
2651 __ mov(edi, eax);
2652 }
2653 }
2654
2655
2544 bool CEntryStub::NeedsImmovableCode() { 2656 bool CEntryStub::NeedsImmovableCode() {
2545 return false; 2657 return false;
2546 } 2658 }
2547 2659
2548 2660
2549 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 2661 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2550 CEntryStub::GenerateAheadOfTime(isolate); 2662 CEntryStub::GenerateAheadOfTime(isolate);
2551 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 2663 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2552 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 2664 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2553 // It is important that the store buffer overflow stubs are generated first. 2665 // It is important that the store buffer overflow stubs are generated first.
(...skipping 2531 matching lines...) Expand 10 before | Expand all | Expand 10 after
5085 Operand(ebp, 7 * kPointerSize), 5197 Operand(ebp, 7 * kPointerSize),
5086 NULL); 5198 NULL);
5087 } 5199 }
5088 5200
5089 5201
5090 #undef __ 5202 #undef __
5091 5203
5092 } } // namespace v8::internal 5204 } } // namespace v8::internal
5093 5205
5094 #endif // V8_TARGET_ARCH_IA32 5206 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/debug-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698