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

Side by Side Diff: src/interpreter/interpreter-assembler.cc

Issue 2307903002: [Interpreter] Collect allocation site feedback in call bytecode handler. (Closed)
Patch Set: ia32, arm and arm64 ports. Created 4 years, 3 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/interpreter-assembler.h" 5 #include "src/interpreter/interpreter-assembler.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <ostream> 8 #include <ostream>
9 9
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 isolate(), tail_call_mode, CallableType::kJSFunction); 516 isolate(), tail_call_mode, CallableType::kJSFunction);
517 Node* code_target = HeapConstant(callable.code()); 517 Node* code_target = HeapConstant(callable.code());
518 Node* ret_value = CallStub(callable.descriptor(), code_target, context, 518 Node* ret_value = CallStub(callable.descriptor(), code_target, context,
519 arg_count, first_arg, function); 519 arg_count, first_arg, function);
520 return_value.Bind(ret_value); 520 return_value.Bind(ret_value);
521 Goto(&end); 521 Goto(&end);
522 } 522 }
523 523
524 Bind(&extra_checks); 524 Bind(&extra_checks);
525 { 525 {
526 Label check_initialized(this, Label::kDeferred), mark_megamorphic(this); 526 Label check_initialized(this, Label::kDeferred), mark_megamorphic(this),
527 check_allocation_site(this), create_allocation_site(this);
527 // Check if it is a megamorphic target 528 // Check if it is a megamorphic target
528 Node* is_megamorphic = WordEqual( 529 Node* is_megamorphic = WordEqual(
529 feedback_element, 530 feedback_element,
530 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); 531 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())));
531 BranchIf(is_megamorphic, &call, &check_initialized); 532 BranchIf(is_megamorphic, &call, &check_allocation_site);
533
534 Bind(&check_allocation_site);
535 {
536 Node* is_allocation_site =
537 WordEqual(LoadMap(feedback_element),
538 LoadRoot(Heap::kAllocationSiteMapRootIndex));
539 GotoUnless(is_allocation_site, &check_initialized);
540
541 // If it is not an array function, mark megamorphic.
542 Node* context_slot =
rmcilroy 2016/09/06 10:59:35 nit - array_function
mythria 2016/09/07 08:59:45 Done.
543 LoadFixedArrayElement(LoadNativeContext(context),
544 Int32Constant(Context::ARRAY_FUNCTION_INDEX));
545 Node* is_array_function = WordEqual(context_slot, function);
546 GotoUnless(is_array_function, &mark_megamorphic);
547
548 // It is a monomorphic Array function. Increment the call count.
549 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
550 Node* call_count =
551 LoadFixedArrayElement(type_feedback_vector, call_count_slot);
552 Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1)));
553 // Count is Smi, so we don't need a write barrier.
554 StoreFixedArrayElement(type_feedback_vector, call_count_slot, new_count,
555 SKIP_WRITE_BARRIER);
556
557 // Call ArrayConstructorStub.
558 Callable callable_call =
559 CodeFactory::InterpreterPushArgsAndConstructArray(isolate());
560 Node* code_target_call = HeapConstant(callable_call.code());
561 Node* ret_value =
562 CallStub(callable_call.descriptor(), code_target_call, context,
563 arg_count, function, feedback_element, first_arg);
564 return_value.Bind(ret_value);
565 Goto(&end);
566 }
532 567
533 Bind(&check_initialized); 568 Bind(&check_initialized);
534 { 569 {
535 Label possibly_monomorphic(this); 570 Label possibly_monomorphic(this);
536 // Check if it is uninitialized. 571 // Check if it is uninitialized.
537 Node* is_uninitialized = WordEqual( 572 Node* is_uninitialized = WordEqual(
538 feedback_element, 573 feedback_element,
539 HeapConstant(TypeFeedbackVector::UninitializedSentinel(isolate()))); 574 HeapConstant(TypeFeedbackVector::UninitializedSentinel(isolate())));
540 GotoUnless(is_uninitialized, &mark_megamorphic); 575 GotoUnless(is_uninitialized, &mark_megamorphic);
541 576
542 Node* is_smi = WordIsSmi(function); 577 Node* is_smi = WordIsSmi(function);
543 GotoIf(is_smi, &mark_megamorphic); 578 GotoIf(is_smi, &mark_megamorphic);
544 579
545 // Check if function is an object of JSFunction type 580 // Check if function is an object of JSFunction type
546 Node* instance_type = LoadInstanceType(function); 581 Node* instance_type = LoadInstanceType(function);
547 Node* is_js_function = 582 Node* is_js_function =
548 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); 583 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE));
549 GotoUnless(is_js_function, &mark_megamorphic); 584 GotoUnless(is_js_function, &mark_megamorphic);
550 585
551 // Check that it is not the Array() function. 586 // Check that it is not the Array() function.
rmcilroy 2016/09/06 10:59:35 Update comment - Check if it is the Array() functi
mythria 2016/09/07 08:59:45 Done.
552 Node* context_slot = 587 Node* context_slot =
553 LoadFixedArrayElement(LoadNativeContext(context), 588 LoadFixedArrayElement(LoadNativeContext(context),
554 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); 589 Int32Constant(Context::ARRAY_FUNCTION_INDEX));
555 Node* is_array_function = WordEqual(context_slot, function); 590 Node* is_array_function = WordEqual(context_slot, function);
556 GotoIf(is_array_function, &mark_megamorphic); 591 GotoIf(is_array_function, &create_allocation_site);
557 592
558 // Check if the function belongs to the same native context 593 // Check if the function belongs to the same native context
559 Node* native_context = LoadNativeContext( 594 Node* native_context = LoadNativeContext(
560 LoadObjectField(function, JSFunction::kContextOffset)); 595 LoadObjectField(function, JSFunction::kContextOffset));
561 Node* is_same_native_context = 596 Node* is_same_native_context =
562 WordEqual(native_context, LoadNativeContext(context)); 597 WordEqual(native_context, LoadNativeContext(context));
563 GotoUnless(is_same_native_context, &mark_megamorphic); 598 GotoUnless(is_same_native_context, &mark_megamorphic);
564 599
565 // Initialize it to a monomorphic target. 600 // Initialize it to a monomorphic target.
566 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); 601 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
567 // Count is Smi, so we don't need a write barrier. 602 // Count is Smi, so we don't need a write barrier.
568 StoreFixedArrayElement(type_feedback_vector, call_count_slot, 603 StoreFixedArrayElement(type_feedback_vector, call_count_slot,
569 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER); 604 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
570 605
571 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), 606 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id),
572 function); 607 function);
573 608
574 // Call using call function builtin. 609 // Call using call function builtin.
575 Callable callable = CodeFactory::InterpreterPushArgsAndCall( 610 Callable callable = CodeFactory::InterpreterPushArgsAndCall(
576 isolate(), tail_call_mode, CallableType::kJSFunction); 611 isolate(), tail_call_mode, CallableType::kJSFunction);
577 Node* code_target = HeapConstant(callable.code()); 612 Node* code_target = HeapConstant(callable.code());
578 Node* ret_value = CallStub(callable.descriptor(), code_target, context, 613 Node* ret_value = CallStub(callable.descriptor(), code_target, context,
579 arg_count, first_arg, function); 614 arg_count, first_arg, function);
580 return_value.Bind(ret_value); 615 return_value.Bind(ret_value);
581 Goto(&end); 616 Goto(&end);
582 } 617 }
583 618
619 Bind(&create_allocation_site);
620 {
621 // TODO(mythria): Inline the creation of allocation site.
rmcilroy 2016/09/06 10:59:35 /s/of allocation/of the allocation
mythria 2016/09/07 08:59:45 Done.
622 CreateAllocationSiteStub create_stub(isolate());
623 CallStub(create_stub.GetCallInterfaceDescriptor(),
624 HeapConstant(create_stub.GetCode()), context,
625 type_feedback_vector, SmiTag(slot_id));
626
627 // Initialize the count to 1.
628 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
629 // Count is Smi, so we don't need a write barrier.
630 StoreFixedArrayElement(type_feedback_vector, call_count_slot,
631 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
632
633 // Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state.
634 // They start collecting feedback only when a call is executed the second
635 // time. So, do not pass any feedback here.
636 Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
rmcilroy 2016/09/06 10:59:35 Can you pull out a shared branch for call_function
mythria 2016/09/07 08:59:45 Done.
637 isolate(), tail_call_mode, CallableType::kJSFunction);
638 Node* code_target_call = HeapConstant(callable_call.code());
639 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call,
640 context, arg_count, first_arg, function);
641 return_value.Bind(ret_value);
642 Goto(&end);
643 }
644
584 Bind(&mark_megamorphic); 645 Bind(&mark_megamorphic);
585 { 646 {
586 // Mark it as a megamorphic. 647 // Mark it as a megamorphic.
587 // MegamorphicSentinel is created as a part of Heap::InitialObjects 648 // MegamorphicSentinel is created as a part of Heap::InitialObjects
588 // and will not move during a GC. So it is safe to skip write barrier. 649 // and will not move during a GC. So it is safe to skip write barrier.
589 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); 650 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
590 StoreFixedArrayElement( 651 StoreFixedArrayElement(
591 type_feedback_vector, slot_id, 652 type_feedback_vector, slot_id,
592 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), 653 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())),
593 SKIP_WRITE_BARRIER); 654 SKIP_WRITE_BARRIER);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); 818 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
758 // Count is Smi, so we don't need a write barrier. 819 // Count is Smi, so we don't need a write barrier.
759 StoreFixedArrayElement(type_feedback_vector, call_count_slot, 820 StoreFixedArrayElement(type_feedback_vector, call_count_slot,
760 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER); 821 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
761 Goto(&call_construct_function); 822 Goto(&call_construct_function);
762 } 823 }
763 } 824 }
764 825
765 Bind(&mark_megamorphic); 826 Bind(&mark_megamorphic);
766 { 827 {
767 // MegamorphicSentinel is an immortal immovable object so no 828 // MegamorphicSentinel is an immortal immovable object so
768 // write-barrier 829 // write-barrier is not needed.
769 // is needed.
770 Comment("transition to megamorphic"); 830 Comment("transition to megamorphic");
771 DCHECK( 831 DCHECK(
772 Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); 832 Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
773 StoreFixedArrayElement( 833 StoreFixedArrayElement(
774 type_feedback_vector, slot_id, 834 type_feedback_vector, slot_id,
775 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), 835 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())),
776 SKIP_WRITE_BARRIER); 836 SKIP_WRITE_BARRIER);
777 Goto(&call_construct_function); 837 Goto(&call_construct_function);
778 } 838 }
779 } 839 }
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 Goto(&loop); 1323 Goto(&loop);
1264 } 1324 }
1265 Bind(&done_loop); 1325 Bind(&done_loop);
1266 1326
1267 return array; 1327 return array;
1268 } 1328 }
1269 1329
1270 } // namespace interpreter 1330 } // namespace interpreter
1271 } // namespace internal 1331 } // namespace internal
1272 } // namespace v8 1332 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698