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

Unified Diff: src/interpreter/interpreter-assembler.cc

Issue 2487573005: [Interpreter] Optimize for monomorphic case in Call and New bytecode handlers. (Closed)
Patch Set: Fixed comments. Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698