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

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

Issue 2307903002: [Interpreter] Collect allocation site feedback in call bytecode handler. (Closed)
Patch Set: 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
« no previous file with comments | « no previous file | test/cctest/cctest.status » ('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 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 =
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 using CallFunction builtin.
558 // TODO(mythria): We still do not use the collected feedback when creating
559 // a new array. To use it, we should have an adapter builtin similiar to
560 // InterpreterPushArgsAndCall to push arguments and call the
561 // ArrayConstructorStub or Runtime_NewArray.
562 Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
563 isolate(), tail_call_mode, CallableType::kJSFunction);
564 Node* code_target_call = HeapConstant(callable_call.code());
565 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call,
566 context, arg_count, first_arg, function);
mythria 2016/09/02 14:33:46 We do not pass allocation site feedback here, so t
Benedikt Meurer 2016/09/05 04:11:20 Ah, I misunderstood you in our offline conversatio
mythria 2016/09/05 12:56:34 Thanks Benedikt. I now implemented it throw ArrayC
567 return_value.Bind(ret_value);
568 Goto(&end);
569 }
532 570
533 Bind(&check_initialized); 571 Bind(&check_initialized);
534 { 572 {
535 Label possibly_monomorphic(this); 573 Label possibly_monomorphic(this);
536 // Check if it is uninitialized. 574 // Check if it is uninitialized.
537 Node* is_uninitialized = WordEqual( 575 Node* is_uninitialized = WordEqual(
538 feedback_element, 576 feedback_element,
539 HeapConstant(TypeFeedbackVector::UninitializedSentinel(isolate()))); 577 HeapConstant(TypeFeedbackVector::UninitializedSentinel(isolate())));
540 GotoUnless(is_uninitialized, &mark_megamorphic); 578 GotoUnless(is_uninitialized, &mark_megamorphic);
541 579
542 Node* is_smi = WordIsSmi(function); 580 Node* is_smi = WordIsSmi(function);
543 GotoIf(is_smi, &mark_megamorphic); 581 GotoIf(is_smi, &mark_megamorphic);
544 582
545 // Check if function is an object of JSFunction type 583 // Check if function is an object of JSFunction type
546 Node* instance_type = LoadInstanceType(function); 584 Node* instance_type = LoadInstanceType(function);
547 Node* is_js_function = 585 Node* is_js_function =
548 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); 586 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE));
549 GotoUnless(is_js_function, &mark_megamorphic); 587 GotoUnless(is_js_function, &mark_megamorphic);
550 588
551 // Check that it is not the Array() function. 589 // Check that it is not the Array() function.
552 Node* context_slot = 590 Node* context_slot =
553 LoadFixedArrayElement(LoadNativeContext(context), 591 LoadFixedArrayElement(LoadNativeContext(context),
554 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); 592 Int32Constant(Context::ARRAY_FUNCTION_INDEX));
555 Node* is_array_function = WordEqual(context_slot, function); 593 Node* is_array_function = WordEqual(context_slot, function);
556 GotoIf(is_array_function, &mark_megamorphic); 594 GotoIf(is_array_function, &create_allocation_site);
557 595
558 // Check if the function belongs to the same native context 596 // Check if the function belongs to the same native context
559 Node* native_context = LoadNativeContext( 597 Node* native_context = LoadNativeContext(
560 LoadObjectField(function, JSFunction::kContextOffset)); 598 LoadObjectField(function, JSFunction::kContextOffset));
561 Node* is_same_native_context = 599 Node* is_same_native_context =
562 WordEqual(native_context, LoadNativeContext(context)); 600 WordEqual(native_context, LoadNativeContext(context));
563 GotoUnless(is_same_native_context, &mark_megamorphic); 601 GotoUnless(is_same_native_context, &mark_megamorphic);
564 602
565 // Initialize it to a monomorphic target. 603 // Initialize it to a monomorphic target.
566 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); 604 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
567 // Count is Smi, so we don't need a write barrier. 605 // Count is Smi, so we don't need a write barrier.
568 StoreFixedArrayElement(type_feedback_vector, call_count_slot, 606 StoreFixedArrayElement(type_feedback_vector, call_count_slot,
569 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER); 607 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
570 608
571 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), 609 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id),
572 function); 610 function);
573 611
574 // Call using call function builtin. 612 // Call using call function builtin.
575 Callable callable = CodeFactory::InterpreterPushArgsAndCall( 613 Callable callable = CodeFactory::InterpreterPushArgsAndCall(
576 isolate(), tail_call_mode, CallableType::kJSFunction); 614 isolate(), tail_call_mode, CallableType::kJSFunction);
577 Node* code_target = HeapConstant(callable.code()); 615 Node* code_target = HeapConstant(callable.code());
578 Node* ret_value = CallStub(callable.descriptor(), code_target, context, 616 Node* ret_value = CallStub(callable.descriptor(), code_target, context,
579 arg_count, first_arg, function); 617 arg_count, first_arg, function);
580 return_value.Bind(ret_value); 618 return_value.Bind(ret_value);
581 Goto(&end); 619 Goto(&end);
582 } 620 }
583 621
622 Bind(&create_allocation_site);
623 {
624 // TODO(mythria): Inline the creation of allocation site.
625 CreateAllocationSiteStub create_stub(isolate());
626 CallStub(create_stub.GetCallInterfaceDescriptor(),
627 HeapConstant(create_stub.GetCode()), context,
628 type_feedback_vector, SmiTag(slot_id));
629
630 // Initialize the count to 1.
631 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
632 // Count is Smi, so we don't need a write barrier.
633 StoreFixedArrayElement(type_feedback_vector, call_count_slot,
634 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
635
636 // Call using CallFunction builtin.
637 // TODO(mythria): We still do not use the collected feedback when creating
638 // a new array. To use it, we should have an adapter builtin similiar to
639 // InterpreterPushArgsAndCall to push arguments and call the
640 // ArrayConstructorStub or Runtime_NewArray.
641 Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
642 isolate(), tail_call_mode, CallableType::kJSFunction);
643 Node* code_target_call = HeapConstant(callable_call.code());
644 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call,
645 context, arg_count, first_arg, function);
646 return_value.Bind(ret_value);
647 Goto(&end);
648 }
649
584 Bind(&mark_megamorphic); 650 Bind(&mark_megamorphic);
585 { 651 {
586 // Mark it as a megamorphic. 652 // Mark it as a megamorphic.
587 // MegamorphicSentinel is created as a part of Heap::InitialObjects 653 // 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. 654 // and will not move during a GC. So it is safe to skip write barrier.
589 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); 655 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
590 StoreFixedArrayElement( 656 StoreFixedArrayElement(
591 type_feedback_vector, slot_id, 657 type_feedback_vector, slot_id,
592 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), 658 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())),
593 SKIP_WRITE_BARRIER); 659 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)); 823 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
758 // Count is Smi, so we don't need a write barrier. 824 // Count is Smi, so we don't need a write barrier.
759 StoreFixedArrayElement(type_feedback_vector, call_count_slot, 825 StoreFixedArrayElement(type_feedback_vector, call_count_slot,
760 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER); 826 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER);
761 Goto(&call_construct_function); 827 Goto(&call_construct_function);
762 } 828 }
763 } 829 }
764 830
765 Bind(&mark_megamorphic); 831 Bind(&mark_megamorphic);
766 { 832 {
767 // MegamorphicSentinel is an immortal immovable object so no 833 // MegamorphicSentinel is an immortal immovable object so
768 // write-barrier 834 // write-barrier is not needed.
769 // is needed.
770 Comment("transition to megamorphic"); 835 Comment("transition to megamorphic");
771 DCHECK( 836 DCHECK(
772 Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); 837 Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
773 StoreFixedArrayElement( 838 StoreFixedArrayElement(
774 type_feedback_vector, slot_id, 839 type_feedback_vector, slot_id,
775 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), 840 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())),
776 SKIP_WRITE_BARRIER); 841 SKIP_WRITE_BARRIER);
777 Goto(&call_construct_function); 842 Goto(&call_construct_function);
778 } 843 }
779 } 844 }
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 Goto(&loop); 1328 Goto(&loop);
1264 } 1329 }
1265 Bind(&done_loop); 1330 Bind(&done_loop);
1266 1331
1267 return array; 1332 return array;
1268 } 1333 }
1269 1334
1270 } // namespace interpreter 1335 } // namespace interpreter
1271 } // namespace internal 1336 } // namespace internal
1272 } // namespace v8 1337 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/cctest/cctest.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698