Index: src/interpreter/interpreter-assembler.cc |
diff --git a/src/interpreter/interpreter-assembler.cc b/src/interpreter/interpreter-assembler.cc |
index 1e2fe88eb52dea6138d3e559f1a26ab414eda929..1a0d8f194d68f3cebb4e8c4210cf42b3ba431b84 100644 |
--- a/src/interpreter/interpreter-assembler.cc |
+++ b/src/interpreter/interpreter-assembler.cc |
@@ -546,22 +546,22 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
WeakCell::kValueOffset == Symbol::kHashFieldSlot); |
Variable return_value(this, MachineRepresentation::kTagged); |
- Label handle_monomorphic(this), extra_checks(this), end(this), call(this), |
- call_function(this); |
+ Label call_function(this), extra_checks(this, Label::kDeferred), call(this), |
+ end(this); |
// The checks. First, does function match the recorded monomorphic target? |
Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); |
Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
Node* is_monomorphic = WordEqual(function, feedback_value); |
- Branch(is_monomorphic, &handle_monomorphic, &extra_checks); |
+ GotoUnless(is_monomorphic, &extra_checks); |
- Bind(&handle_monomorphic); |
- { |
- // The compare above could have been a SMI/SMI comparison. Guard against |
- // this convincing us that we have a monomorphic JSFunction. |
- Node* is_smi = TaggedIsSmi(function); |
- GotoIf(is_smi, &extra_checks); |
+ // The compare above could have been a SMI/SMI comparison. Guard against |
+ // this convincing us that we have a monomorphic JSFunction. |
+ Node* is_smi = TaggedIsSmi(function); |
+ Branch(is_smi, &extra_checks, &call_function); |
+ Bind(&call_function); |
+ { |
// Increment the call count. |
IncrementCallCount(type_feedback_vector, slot_id); |
@@ -577,56 +577,56 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
Bind(&extra_checks); |
{ |
- Label check_initialized(this, Label::kDeferred), mark_megamorphic(this), |
- check_allocation_site(this), |
- create_allocation_site(this, Label::kDeferred); |
- // Check if it is a megamorphic target |
+ Label check_initialized(this), mark_megamorphic(this), |
+ create_allocation_site(this); |
+ |
+ Comment("check if megamorphic"); |
+ // Check if it is a megamorphic target. |
Node* is_megamorphic = WordEqual( |
feedback_element, |
HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
- Branch(is_megamorphic, &call, &check_allocation_site); |
+ GotoIf(is_megamorphic, &call); |
- Bind(&check_allocation_site); |
- { |
- Node* is_allocation_site = |
- WordEqual(LoadMap(feedback_element), |
- LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
- GotoUnless(is_allocation_site, &check_initialized); |
+ Comment("check if it is an allocation site"); |
+ Node* is_allocation_site = WordEqual( |
+ LoadMap(feedback_element), LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
+ GotoUnless(is_allocation_site, &check_initialized); |
- // If it is not the Array() function, mark megamorphic. |
- Node* context_slot = |
- LoadFixedArrayElement(LoadNativeContext(context), |
- Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
- Node* is_array_function = WordEqual(context_slot, function); |
- GotoUnless(is_array_function, &mark_megamorphic); |
+ // If it is not the Array() function, mark megamorphic. |
+ Node* context_slot = |
+ 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. |
- IncrementCallCount(type_feedback_vector, slot_id); |
- |
- // 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); |
- } |
+ // It is a monomorphic Array function. Increment the call count. |
+ IncrementCallCount(type_feedback_vector, slot_id); |
+ |
+ // 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); |
{ |
- Label possibly_monomorphic(this); |
- // Check if it is uninitialized. |
+ Comment("check if uninitialized"); |
+ // Check if it is uninitialized target first. |
Node* is_uninitialized = WordEqual( |
feedback_element, |
HeapConstant(TypeFeedbackVector::UninitializedSentinel(isolate()))); |
GotoUnless(is_uninitialized, &mark_megamorphic); |
+ Comment("handle_unitinitialized"); |
+ // If it is not a JSFunction mark it as megamorphic. |
Node* is_smi = TaggedIsSmi(function); |
GotoIf(is_smi, &mark_megamorphic); |
- // Check if function is an object of JSFunction type |
+ // Check if function is an object of JSFunction type. |
Node* instance_type = LoadInstanceType(function); |
Node* is_js_function = |
WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
@@ -639,7 +639,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
Node* is_array_function = WordEqual(context_slot, function); |
GotoIf(is_array_function, &create_allocation_site); |
- // Check if the function belongs to the same native context |
+ // Check if the function belongs to the same native context. |
Node* native_context = LoadNativeContext( |
LoadObjectField(function, JSFunction::kContextOffset)); |
Node* is_same_native_context = |
@@ -678,22 +678,9 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
} |
} |
- Bind(&call_function); |
- { |
- // Increment the call count. |
- IncrementCallCount(type_feedback_vector, slot_id); |
- |
- Callable callable_call = CodeFactory::InterpreterPushArgsAndCall( |
- 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(&call); |
{ |
+ Comment("Increment call count and call using Call builtin"); |
// Increment the call count. |
IncrementCallCount(type_feedback_vector, slot_id); |
@@ -725,10 +712,10 @@ Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, |
Node* new_target, Node* first_arg, |
Node* arg_count, Node* slot_id, |
Node* type_feedback_vector) { |
- Label call_construct(this), js_function(this), end(this); |
Variable return_value(this, MachineRepresentation::kTagged); |
Variable allocation_feedback(this, MachineRepresentation::kTagged); |
- allocation_feedback.Bind(UndefinedConstant()); |
+ Label call_construct_function(this, &allocation_feedback), |
+ extra_checks(this, Label::kDeferred), call_construct(this), end(this); |
// Slot id of 0 is used to indicate no type feedback is available. |
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); |
@@ -743,132 +730,118 @@ Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, |
Node* instance_type = LoadInstanceType(constructor); |
Node* is_js_function = |
WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
- Branch(is_js_function, &js_function, &call_construct); |
+ GotoUnless(is_js_function, &call_construct); |
- Bind(&js_function); |
+ // Check if it is a monomorphic constructor. |
+ Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); |
+ Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
+ Node* is_monomorphic = WordEqual(constructor, feedback_value); |
+ allocation_feedback.Bind(UndefinedConstant()); |
+ Branch(is_monomorphic, &call_construct_function, &extra_checks); |
+ |
+ Bind(&call_construct_function); |
+ { |
+ Comment("call using callConstructFunction"); |
+ IncrementCallCount(type_feedback_vector, slot_id); |
+ Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( |
+ isolate(), CallableType::kJSFunction); |
+ return_value.Bind(CallStub(callable_function.descriptor(), |
+ HeapConstant(callable_function.code()), context, |
+ arg_count, new_target, constructor, |
+ allocation_feedback.value(), first_arg)); |
+ Goto(&end); |
+ } |
+ |
+ Bind(&extra_checks); |
{ |
- // Cache the called function in a feedback vector slot. Cache states |
- // are uninitialized, monomorphic (indicated by a JSFunction), and |
- // megamorphic. |
- // TODO(mythria/v8:5210): Check if it is better to mark extra_checks as a |
- // deferred block so that call_construct_function will be scheduled. |
- Label extra_checks(this), call_construct_function(this); |
- |
- Node* feedback_element = |
- LoadFixedArrayElement(type_feedback_vector, slot_id); |
- Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
- Node* is_monomorphic = WordEqual(constructor, feedback_value); |
- Branch(is_monomorphic, &call_construct_function, &extra_checks); |
- |
- Bind(&extra_checks); |
+ Label check_allocation_site(this), check_initialized(this), |
+ initialize(this), mark_megamorphic(this); |
+ |
+ // Check if it is a megamorphic target. |
+ Comment("check if megamorphic"); |
+ Node* is_megamorphic = WordEqual( |
+ feedback_element, |
+ HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
+ GotoIf(is_megamorphic, &call_construct_function); |
+ |
+ Comment("check if weak cell"); |
+ Node* is_weak_cell = WordEqual(LoadMap(feedback_element), |
+ LoadRoot(Heap::kWeakCellMapRootIndex)); |
+ GotoUnless(is_weak_cell, &check_allocation_site); |
+ |
+ // If the weak cell is cleared, we have a new chance to become |
+ // monomorphic. |
+ Comment("check if weak cell is cleared"); |
+ Node* is_smi = TaggedIsSmi(feedback_value); |
+ Branch(is_smi, &initialize, &mark_megamorphic); |
+ |
+ Bind(&check_allocation_site); |
{ |
- Label mark_megamorphic(this), initialize(this), |
- check_allocation_site(this), check_initialized(this), |
- set_alloc_feedback_and_call(this); |
- { |
- // Check if it is a megamorphic target |
- Comment("check if megamorphic"); |
- Node* is_megamorphic = WordEqual( |
- feedback_element, |
- HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
- GotoIf(is_megamorphic, &call_construct_function); |
- |
- Comment("check if weak cell"); |
- Node* is_weak_cell = WordEqual(LoadMap(feedback_element), |
- LoadRoot(Heap::kWeakCellMapRootIndex)); |
- GotoUnless(is_weak_cell, &check_allocation_site); |
- // If the weak cell is cleared, we have a new chance to become |
- // monomorphic. |
- Comment("check if weak cell is cleared"); |
- Node* is_smi = TaggedIsSmi(feedback_value); |
- Branch(is_smi, &initialize, &mark_megamorphic); |
- } |
+ Comment("check if it is an allocation site"); |
+ Node* is_allocation_site = |
+ WordEqual(LoadObjectField(feedback_element, 0), |
+ LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
+ GotoUnless(is_allocation_site, &check_initialized); |
- Bind(&check_allocation_site); |
- { |
- Comment("check if it is an allocation site"); |
- Node* is_allocation_site = |
- WordEqual(LoadObjectField(feedback_element, 0), |
- LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
- GotoUnless(is_allocation_site, &check_initialized); |
- |
- // Make sure the function is the Array() function |
- Node* context_slot = |
- LoadFixedArrayElement(LoadNativeContext(context), |
- Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
- Node* is_array_function = WordEqual(context_slot, constructor); |
- Branch(is_array_function, &set_alloc_feedback_and_call, |
- &mark_megamorphic); |
- } |
+ // Make sure the function is the Array() function. |
+ Node* context_slot = |
+ LoadFixedArrayElement(LoadNativeContext(context), |
+ Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
+ Node* is_array_function = WordEqual(context_slot, constructor); |
+ GotoUnless(is_array_function, &mark_megamorphic); |
- Bind(&set_alloc_feedback_and_call); |
- { |
- allocation_feedback.Bind(feedback_element); |
- Goto(&call_construct_function); |
- } |
+ allocation_feedback.Bind(feedback_element); |
+ Goto(&call_construct_function); |
+ } |
- Bind(&check_initialized); |
- { |
- // Check if it is uninitialized. |
- Comment("check if uninitialized"); |
- Node* is_uninitialized = WordEqual( |
- feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); |
- Branch(is_uninitialized, &initialize, &mark_megamorphic); |
- } |
+ Bind(&check_initialized); |
+ { |
+ // Check if it is uninitialized. |
+ Comment("check if uninitialized"); |
+ Node* is_uninitialized = WordEqual( |
+ feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); |
+ Branch(is_uninitialized, &initialize, &mark_megamorphic); |
+ } |
- Bind(&initialize); |
- { |
- Label create_weak_cell(this), create_allocation_site(this); |
- Comment("initialize the feedback element"); |
- // Check that it is the Array() function. |
- Node* context_slot = |
- LoadFixedArrayElement(LoadNativeContext(context), |
- Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
- Node* is_array_function = WordEqual(context_slot, constructor); |
- Branch(is_array_function, &create_allocation_site, &create_weak_cell); |
- |
- Bind(&create_allocation_site); |
- { |
- Node* site = CreateAllocationSiteInFeedbackVector( |
- type_feedback_vector, SmiTag(slot_id)); |
- allocation_feedback.Bind(site); |
- Goto(&call_construct_function); |
- } |
+ Bind(&initialize); |
+ { |
+ Label create_allocation_site(this), create_weak_cell(this); |
+ Comment("initialize the feedback element"); |
+ // Create an allocation site if the function is an array function, |
+ // otherwise create a weak cell. |
+ Node* context_slot = |
+ LoadFixedArrayElement(LoadNativeContext(context), |
+ Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
+ Node* is_array_function = WordEqual(context_slot, constructor); |
+ Branch(is_array_function, &create_allocation_site, &create_weak_cell); |
- Bind(&create_weak_cell); |
- { |
- CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), |
- constructor); |
- Goto(&call_construct_function); |
- } |
+ Bind(&create_allocation_site); |
+ { |
+ Node* site = CreateAllocationSiteInFeedbackVector(type_feedback_vector, |
+ SmiTag(slot_id)); |
+ allocation_feedback.Bind(site); |
+ Goto(&call_construct_function); |
} |
- Bind(&mark_megamorphic); |
+ Bind(&create_weak_cell); |
{ |
- // MegamorphicSentinel is an immortal immovable object so |
- // write-barrier is not needed. |
- Comment("transition to megamorphic"); |
- DCHECK( |
- Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
- StoreFixedArrayElement( |
- type_feedback_vector, slot_id, |
- HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
- SKIP_WRITE_BARRIER); |
+ CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), |
+ constructor); |
Goto(&call_construct_function); |
} |
} |
- Bind(&call_construct_function); |
+ Bind(&mark_megamorphic); |
{ |
- Comment("call using callConstructFunction"); |
- IncrementCallCount(type_feedback_vector, slot_id); |
- Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( |
- isolate(), CallableType::kJSFunction); |
- return_value.Bind(CallStub(callable_function.descriptor(), |
- HeapConstant(callable_function.code()), |
- context, arg_count, new_target, constructor, |
- allocation_feedback.value(), first_arg)); |
- Goto(&end); |
+ // MegamorphicSentinel is an immortal immovable object so |
+ // write-barrier is not needed. |
+ Comment("transition to megamorphic"); |
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
+ StoreFixedArrayElement( |
+ type_feedback_vector, slot_id, |
+ HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
+ SKIP_WRITE_BARRIER); |
+ Goto(&call_construct_function); |
} |
} |