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

Unified Diff: src/code-stubs.cc

Issue 2670843002: [stubs] Also port the CallICStub to CSA. (Closed)
Patch Set: Introduce FullCodeGenerator::IntFromSlot. Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/code-stubs.h ('k') | src/full-codegen/arm/full-codegen-arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stubs.cc
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index ec9d04a40da4ec7384334b83e6813366f7fa39c5..fb7a9c0d93d0ccb306e5c8bc2d1d908907ac1246 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -1759,6 +1759,179 @@ void CallICStub::PrintState(std::ostream& os) const { // NOLINT
os << convert_mode() << ", " << tail_call_mode();
}
+void CallICStub::GenerateAssembly(compiler::CodeAssemblerState* state) const {
+ typedef CodeStubAssembler::Label Label;
+ typedef compiler::Node Node;
+ CodeStubAssembler assembler(state);
+
+ Node* context = assembler.Parameter(Descriptor::kContext);
+ Node* target = assembler.Parameter(Descriptor::kTarget);
+ Node* argc = assembler.Parameter(Descriptor::kActualArgumentsCount);
+ Node* slot = assembler.Parameter(Descriptor::kSlot);
+ Node* vector = assembler.Parameter(Descriptor::kVector);
+
+ // TODO(bmeurer): The slot should actually be an IntPtr, but TurboFan's
+ // SimplifiedLowering cannot deal with IntPtr machine type properly yet.
+ slot = assembler.ChangeInt32ToIntPtr(slot);
+
+ // Static checks to assert it is safe to examine the type feedback element.
+ // We don't know that we have a weak cell. We might have a private symbol
+ // or an AllocationSite, but the memory is safe to examine.
+ // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
+ // FixedArray.
+ // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
+ // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
+ // computed, meaning that it can't appear to be a pointer. If the low bit is
+ // 0, then hash is computed, but the 0 bit prevents the field from appearing
+ // to be a pointer.
+ STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
+ STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
+ WeakCell::kValueOffset &&
+ WeakCell::kValueOffset == Symbol::kHashFieldSlot);
+
+ // Increment the call count.
+ // TODO(bmeurer): Would it be beneficial to use Int32Add on 64-bit?
+ assembler.Comment("increment call count");
+ Node* call_count =
+ assembler.LoadFixedArrayElement(vector, slot, 1 * kPointerSize);
+ Node* new_count = assembler.SmiAdd(call_count, assembler.SmiConstant(1));
+ // Count is Smi, so we don't need a write barrier.
+ assembler.StoreFixedArrayElement(vector, slot, new_count, SKIP_WRITE_BARRIER,
+ 1 * kPointerSize);
+
+ Label call_function(&assembler), extra_checks(&assembler), call(&assembler);
+
+ // The checks. First, does function match the recorded monomorphic target?
+ Node* feedback_element = assembler.LoadFixedArrayElement(vector, slot);
+ Node* feedback_value = assembler.LoadWeakCellValueUnchecked(feedback_element);
+ Node* is_monomorphic = assembler.WordEqual(target, feedback_value);
+ assembler.GotoUnless(is_monomorphic, &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 = assembler.TaggedIsSmi(target);
+ assembler.Branch(is_smi, &extra_checks, &call_function);
+
+ assembler.Bind(&call_function);
+ {
+ // Call using CallFunction builtin.
+ Callable callable =
+ CodeFactory::CallFunction(isolate(), convert_mode(), tail_call_mode());
+ assembler.TailCallStub(callable, context, target, argc);
+ }
+
+ assembler.Bind(&extra_checks);
+ {
+ Label check_initialized(&assembler), mark_megamorphic(&assembler),
+ create_allocation_site(&assembler, Label::kDeferred),
+ create_weak_cell(&assembler, Label::kDeferred);
+
+ assembler.Comment("check if megamorphic");
+ // Check if it is a megamorphic target.
+ Node* is_megamorphic = assembler.WordEqual(
+ feedback_element,
+ assembler.HeapConstant(
+ TypeFeedbackVector::MegamorphicSentinel(isolate())));
+ assembler.GotoIf(is_megamorphic, &call);
+
+ assembler.Comment("check if it is an allocation site");
+ assembler.GotoUnless(
+ assembler.IsAllocationSiteMap(assembler.LoadMap(feedback_element)),
+ &check_initialized);
+
+ // If it is not the Array() function, mark megamorphic.
+ Node* context_slot = assembler.LoadContextElement(
+ assembler.LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX);
+ Node* is_array_function = assembler.WordEqual(context_slot, target);
+ assembler.GotoUnless(is_array_function, &mark_megamorphic);
+
+ // Call ArrayConstructorStub.
+ Callable callable = CodeFactory::ArrayConstructor(isolate());
+ assembler.TailCallStub(callable, context, target, target, argc,
+ feedback_element);
+
+ assembler.Bind(&check_initialized);
+ {
+ assembler.Comment("check if uninitialized");
+ // Check if it is uninitialized target first.
+ Node* is_uninitialized = assembler.WordEqual(
+ feedback_element,
+ assembler.HeapConstant(
+ TypeFeedbackVector::UninitializedSentinel(isolate())));
+ assembler.GotoUnless(is_uninitialized, &mark_megamorphic);
+
+ assembler.Comment("handle unitinitialized");
+ // If it is not a JSFunction mark it as megamorphic.
+ Node* is_smi = assembler.TaggedIsSmi(target);
+ assembler.GotoIf(is_smi, &mark_megamorphic);
+
+ // Check if function is an object of JSFunction type.
+ Node* is_js_function = assembler.IsJSFunction(target);
+ assembler.GotoUnless(is_js_function, &mark_megamorphic);
+
+ // Check if it is the Array() function.
+ Node* context_slot = assembler.LoadContextElement(
+ assembler.LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX);
+ Node* is_array_function = assembler.WordEqual(context_slot, target);
+ assembler.GotoIf(is_array_function, &create_allocation_site);
+
+ // Check if the function belongs to the same native context.
+ Node* native_context = assembler.LoadNativeContext(
+ assembler.LoadObjectField(target, JSFunction::kContextOffset));
+ Node* is_same_native_context = assembler.WordEqual(
+ native_context, assembler.LoadNativeContext(context));
+ assembler.Branch(is_same_native_context, &create_weak_cell,
+ &mark_megamorphic);
+ }
+
+ assembler.Bind(&create_weak_cell);
+ {
+ // Wrap the {target} in a WeakCell and remember it.
+ assembler.Comment("create weak cell");
+ assembler.CreateWeakCellInFeedbackVector(vector, assembler.SmiTag(slot),
+ target);
+
+ // Call using CallFunction builtin.
+ assembler.Goto(&call_function);
+ }
+
+ assembler.Bind(&create_allocation_site);
+ {
+ // Create an AllocationSite for the {target}.
+ assembler.Comment("create allocation site");
+ assembler.CreateAllocationSiteInFeedbackVector(vector,
+ assembler.SmiTag(slot));
+
+ // 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.
+ assembler.Goto(&call_function);
+ }
+
+ assembler.Bind(&mark_megamorphic);
+ {
+ // Mark it as a megamorphic.
+ // MegamorphicSentinel is created as a part of Heap::InitialObjects
+ // and will not move during a GC. So it is safe to skip write barrier.
+ DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
+ assembler.StoreFixedArrayElement(
+ vector, slot, assembler.HeapConstant(
+ TypeFeedbackVector::MegamorphicSentinel(isolate())),
+ SKIP_WRITE_BARRIER);
+ assembler.Goto(&call);
+ }
+ }
+
+ assembler.Bind(&call);
+ {
+ // Call using call builtin.
+ assembler.Comment("call using Call builtin");
+ Callable callable_call =
+ CodeFactory::Call(isolate(), convert_mode(), tail_call_mode());
+ assembler.TailCallStub(callable_call, context, target, argc);
+ }
+}
+
void CallICTrampolineStub::PrintState(std::ostream& os) const { // NOLINT
os << convert_mode() << ", " << tail_call_mode();
}
@@ -1769,7 +1942,7 @@ void CallICTrampolineStub::GenerateAssembly(
CodeStubAssembler assembler(state);
Node* context = assembler.Parameter(Descriptor::kContext);
- Node* target = assembler.Parameter(Descriptor::kFunction);
+ Node* target = assembler.Parameter(Descriptor::kTarget);
Node* argc = assembler.Parameter(Descriptor::kActualArgumentsCount);
Node* slot = assembler.Parameter(Descriptor::kSlot);
Node* vector = assembler.LoadTypeFeedbackVectorForStub();
« no previous file with comments | « src/code-stubs.h ('k') | src/full-codegen/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698