V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
builtins-lazy-gen.cc
1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/builtins/builtins-lazy-gen.h"
6 
7 #include "src/builtins/builtins-utils-gen.h"
8 #include "src/builtins/builtins.h"
9 #include "src/feedback-vector.h"
10 #include "src/globals.h"
11 #include "src/objects/shared-function-info.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 void LazyBuiltinsAssembler::GenerateTailCallToJSCode(
17  TNode<Code> code, TNode<JSFunction> function) {
18  TNode<Int32T> argc =
19  UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
20  TNode<Context> context = CAST(Parameter(Descriptor::kContext));
21  TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
22 
23  TailCallJSCode(code, context, function, new_target, argc);
24 }
25 
26 void LazyBuiltinsAssembler::GenerateTailCallToReturnedCode(
27  Runtime::FunctionId function_id, TNode<JSFunction> function) {
28  TNode<Context> context = CAST(Parameter(Descriptor::kContext));
29  TNode<Code> code = CAST(CallRuntime(function_id, context, function));
30  GenerateTailCallToJSCode(code, function);
31 }
32 
33 void LazyBuiltinsAssembler::TailCallRuntimeIfMarkerEquals(
34  TNode<Smi> marker, OptimizationMarker expected_marker,
35  Runtime::FunctionId function_id, TNode<JSFunction> function) {
36  Label no_match(this);
37  GotoIfNot(SmiEqual(marker, SmiConstant(expected_marker)), &no_match);
38  GenerateTailCallToReturnedCode(function_id, function);
39  BIND(&no_match);
40 }
41 
42 void LazyBuiltinsAssembler::MaybeTailCallOptimizedCodeSlot(
43  TNode<JSFunction> function, TNode<FeedbackVector> feedback_vector) {
44  Label fallthrough(this);
45 
46  TNode<MaybeObject> maybe_optimized_code_entry = LoadMaybeWeakObjectField(
47  feedback_vector, FeedbackVector::kOptimizedCodeOffset);
48 
49  // Check if the code entry is a Smi. If yes, we interpret it as an
50  // optimisation marker. Otherwise, interpret it as a weak reference to a code
51  // object.
52  Label optimized_code_slot_is_smi(this), optimized_code_slot_is_weak_ref(this);
53  Branch(TaggedIsSmi(maybe_optimized_code_entry), &optimized_code_slot_is_smi,
54  &optimized_code_slot_is_weak_ref);
55 
56  BIND(&optimized_code_slot_is_smi);
57  {
58  // Optimized code slot is a Smi optimization marker.
59  TNode<Smi> marker = CAST(maybe_optimized_code_entry);
60 
61  // Fall through if no optimization trigger.
62  GotoIf(SmiEqual(marker, SmiConstant(OptimizationMarker::kNone)),
63  &fallthrough);
64 
65  // TODO(ishell): introduce Runtime::kHandleOptimizationMarker and check
66  // all these marker values there.
67  TailCallRuntimeIfMarkerEquals(marker,
68  OptimizationMarker::kLogFirstExecution,
69  Runtime::kFunctionFirstExecution, function);
70  TailCallRuntimeIfMarkerEquals(marker, OptimizationMarker::kCompileOptimized,
71  Runtime::kCompileOptimized_NotConcurrent,
72  function);
73  TailCallRuntimeIfMarkerEquals(
74  marker, OptimizationMarker::kCompileOptimizedConcurrent,
75  Runtime::kCompileOptimized_Concurrent, function);
76 
77  // Otherwise, the marker is InOptimizationQueue, so fall through hoping
78  // that an interrupt will eventually update the slot with optimized code.
79  CSA_ASSERT(this,
80  SmiEqual(marker,
81  SmiConstant(OptimizationMarker::kInOptimizationQueue)));
82  Goto(&fallthrough);
83  }
84 
85  BIND(&optimized_code_slot_is_weak_ref);
86  {
87  // Optimized code slot is a weak reference.
88  TNode<Code> optimized_code =
89  CAST(GetHeapObjectAssumeWeak(maybe_optimized_code_entry, &fallthrough));
90 
91  // Check if the optimized code is marked for deopt. If it is, call the
92  // runtime to clear it.
93  Label found_deoptimized_code(this);
94  TNode<CodeDataContainer> code_data_container =
95  CAST(LoadObjectField(optimized_code, Code::kCodeDataContainerOffset));
96 
97  TNode<Int32T> code_kind_specific_flags = LoadObjectField<Int32T>(
98  code_data_container, CodeDataContainer::kKindSpecificFlagsOffset);
99  GotoIf(IsSetWord32<Code::MarkedForDeoptimizationField>(
100  code_kind_specific_flags),
101  &found_deoptimized_code);
102 
103  // Optimized code is good, get it into the closure and link the closure into
104  // the optimized functions list, then tail call the optimized code.
105  StoreObjectField(function, JSFunction::kCodeOffset, optimized_code);
106  GenerateTailCallToJSCode(optimized_code, function);
107 
108  // Optimized code slot contains deoptimized code, evict it and re-enter the
109  // closure's code.
110  BIND(&found_deoptimized_code);
111  GenerateTailCallToReturnedCode(Runtime::kEvictOptimizedCodeSlot, function);
112  }
113 
114  // Fall-through if the optimized code cell is clear and there is no
115  // optimization marker.
116  BIND(&fallthrough);
117 }
118 
119 void LazyBuiltinsAssembler::CompileLazy(TNode<JSFunction> function) {
120  // First lookup code, maybe we don't need to compile!
121  Label compile_function(this, Label::kDeferred);
122 
123  // Compile function if we don't have a valid feedback vector.
124  TNode<FeedbackVector> feedback_vector =
125  LoadFeedbackVector(function, &compile_function);
126 
127  // Is there an optimization marker or optimized code in the feedback vector?
128  MaybeTailCallOptimizedCodeSlot(function, feedback_vector);
129 
130  // We found no optimized code. Infer the code object needed for the SFI.
131  TNode<SharedFunctionInfo> shared =
132  CAST(LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset));
133  // If code entry points to anything other than CompileLazy, install that,
134  // otherwise call runtime to compile the function.
135  TNode<Code> code = GetSharedFunctionInfoCode(shared, &compile_function);
136 
137  CSA_ASSERT(
138  this,
139  WordNotEqual(code, HeapConstant(BUILTIN_CODE(isolate(), CompileLazy))));
140 
141  // Install the SFI's code entry.
142  StoreObjectField(function, JSFunction::kCodeOffset, code);
143  GenerateTailCallToJSCode(code, function);
144 
145  BIND(&compile_function);
146  { GenerateTailCallToReturnedCode(Runtime::kCompileLazy, function); }
147 }
148 
149 TF_BUILTIN(CompileLazy, LazyBuiltinsAssembler) {
150  TNode<JSFunction> function = CAST(Parameter(Descriptor::kTarget));
151 
152  CompileLazy(function);
153 }
154 
155 TF_BUILTIN(CompileLazyDeoptimizedCode, LazyBuiltinsAssembler) {
156  TNode<JSFunction> function = CAST(Parameter(Descriptor::kTarget));
157 
158  // Set the code slot inside the JSFunction to CompileLazy.
159  TNode<Code> code = HeapConstant(BUILTIN_CODE(isolate(), CompileLazy));
160  StoreObjectField(function, JSFunction::kCodeOffset, code);
161  GenerateTailCallToJSCode(code, function);
162 }
163 
164 } // namespace internal
165 } // namespace v8
Definition: libplatform.h:13