Chromium Code Reviews| Index: src/interpreter/interpreter-assembler.cc |
| diff --git a/src/interpreter/interpreter-assembler.cc b/src/interpreter/interpreter-assembler.cc |
| index 947979e7085a1ebb02a44fe722b60ab2eb6f8272..e41d278d502f095411c74bfda75697367394a5c2 100644 |
| --- a/src/interpreter/interpreter-assembler.cc |
| +++ b/src/interpreter/interpreter-assembler.cc |
| @@ -523,12 +523,47 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
| Bind(&extra_checks); |
| { |
| - Label check_initialized(this, Label::kDeferred), mark_megamorphic(this); |
| + Label check_initialized(this, Label::kDeferred), mark_megamorphic(this), |
| + check_allocation_site(this), create_allocation_site(this); |
| // Check if it is a megamorphic target |
| Node* is_megamorphic = WordEqual( |
| feedback_element, |
| HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
| - BranchIf(is_megamorphic, &call, &check_initialized); |
| + BranchIf(is_megamorphic, &call, &check_allocation_site); |
| + |
| + Bind(&check_allocation_site); |
| + { |
| + Node* is_allocation_site = |
| + WordEqual(LoadMap(feedback_element), |
| + LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
| + GotoUnless(is_allocation_site, &check_initialized); |
| + |
| + // If it is not an array function, mark megamorphic. |
| + Node* context_slot = |
|
rmcilroy
2016/09/06 10:59:35
nit - array_function
mythria
2016/09/07 08:59:45
Done.
|
| + LoadFixedArrayElement(LoadNativeContext(context), |
| + Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
| + Node* is_array_function = WordEqual(context_slot, function); |
| + GotoUnless(is_array_function, &mark_megamorphic); |
| + |
| + // It is a monomorphic Array function. Increment the call count. |
| + Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); |
| + Node* call_count = |
| + LoadFixedArrayElement(type_feedback_vector, call_count_slot); |
| + Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1))); |
| + // Count is Smi, so we don't need a write barrier. |
| + StoreFixedArrayElement(type_feedback_vector, call_count_slot, new_count, |
| + SKIP_WRITE_BARRIER); |
| + |
| + // Call ArrayConstructorStub. |
| + Callable callable_call = |
| + CodeFactory::InterpreterPushArgsAndConstructArray(isolate()); |
| + Node* code_target_call = HeapConstant(callable_call.code()); |
| + Node* ret_value = |
| + CallStub(callable_call.descriptor(), code_target_call, context, |
| + arg_count, function, feedback_element, first_arg); |
| + return_value.Bind(ret_value); |
| + Goto(&end); |
| + } |
| Bind(&check_initialized); |
| { |
| @@ -553,7 +588,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
| LoadFixedArrayElement(LoadNativeContext(context), |
| Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
| Node* is_array_function = WordEqual(context_slot, function); |
| - GotoIf(is_array_function, &mark_megamorphic); |
| + GotoIf(is_array_function, &create_allocation_site); |
| // Check if the function belongs to the same native context |
| Node* native_context = LoadNativeContext( |
| @@ -581,6 +616,32 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
| Goto(&end); |
| } |
| + Bind(&create_allocation_site); |
| + { |
| + // 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.
|
| + CreateAllocationSiteStub create_stub(isolate()); |
| + CallStub(create_stub.GetCallInterfaceDescriptor(), |
| + HeapConstant(create_stub.GetCode()), context, |
| + type_feedback_vector, SmiTag(slot_id)); |
| + |
| + // Initialize the count to 1. |
| + Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); |
| + // Count is Smi, so we don't need a write barrier. |
| + StoreFixedArrayElement(type_feedback_vector, call_count_slot, |
| + SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER); |
| + |
| + // Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state. |
| + // They start collecting feedback only when a call is executed the second |
| + // time. So, do not pass any feedback here. |
| + 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.
|
| + isolate(), tail_call_mode, CallableType::kJSFunction); |
| + Node* code_target_call = HeapConstant(callable_call.code()); |
| + Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, |
| + context, arg_count, first_arg, function); |
| + return_value.Bind(ret_value); |
| + Goto(&end); |
| + } |
| + |
| Bind(&mark_megamorphic); |
| { |
| // Mark it as a megamorphic. |
| @@ -764,9 +825,8 @@ Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, |
| Bind(&mark_megamorphic); |
| { |
| - // MegamorphicSentinel is an immortal immovable object so no |
| - // write-barrier |
| - // is needed. |
| + // MegamorphicSentinel is an immortal immovable object so |
| + // write-barrier is not needed. |
| Comment("transition to megamorphic"); |
| DCHECK( |
| Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |