v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
js-intrinsic-lowering.cc
Go to the documentation of this file.
1// Copyright 2015 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
6
7#include <stack>
8
18
19namespace v8 {
20namespace internal {
21namespace compiler {
22
26
28 if (node->opcode() != IrOpcode::kJSCallRuntime) return NoChange();
29 const Runtime::Function* const f =
31 switch (f->function_id) {
32 case Runtime::kIsBeingInterpreted:
33 return ReduceIsBeingInterpreted(node);
34 case Runtime::kTurbofanStaticAssert:
35 return ReduceTurbofanStaticAssert(node);
36 case Runtime::kVerifyType:
37 return ReduceVerifyType(node);
38 case Runtime::kCheckTurboshaftTypeOf:
39 return ReduceCheckTurboshaftTypeOf(node);
40 default:
41 break;
42 }
43 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange();
44 switch (f->function_id) {
45 case Runtime::kInlineCopyDataProperties:
46 return ReduceCopyDataProperties(node);
47 case Runtime::kInlineCopyDataPropertiesWithExcludedPropertiesOnStack:
49 case Runtime::kInlineCreateIterResultObject:
51 case Runtime::kInlineDeoptimizeNow:
52 return ReduceDeoptimizeNow(node);
53 case Runtime::kInlineGeneratorClose:
54 return ReduceGeneratorClose(node);
55 case Runtime::kInlineCreateJSGeneratorObject:
57 case Runtime::kInlineAsyncFunctionAwait:
58 return ReduceAsyncFunctionAwait(node);
59 case Runtime::kInlineAsyncFunctionEnter:
60 return ReduceAsyncFunctionEnter(node);
61 case Runtime::kInlineAsyncFunctionReject:
62 return ReduceAsyncFunctionReject(node);
63 case Runtime::kInlineAsyncFunctionResolve:
64 return ReduceAsyncFunctionResolve(node);
65 case Runtime::kInlineAsyncGeneratorAwait:
66 return ReduceAsyncGeneratorAwait(node);
67 case Runtime::kInlineAsyncGeneratorReject:
68 return ReduceAsyncGeneratorReject(node);
69 case Runtime::kInlineAsyncGeneratorResolve:
70 return ReduceAsyncGeneratorResolve(node);
71 case Runtime::kInlineAsyncGeneratorYieldWithAwait:
73 case Runtime::kInlineGeneratorGetResumeMode:
75 case Runtime::kInlineIncBlockCounter:
76 return ReduceIncBlockCounter(node);
77 case Runtime::kInlineGetImportMetaObject:
78 return ReduceGetImportMetaObject(node);
79 default:
80 break;
81 }
82 return NoChange();
83}
84
86 return Change(
87 node, Builtins::CallableFor(isolate(), Builtin::kCopyDataProperties), 0);
88}
89
92 Node* node) {
93 int input_count =
94 static_cast<int>(CallRuntimeParametersOf(node->op()).arity());
96 auto callable = Builtins::CallableFor(
97 isolate(), Builtin::kCopyDataPropertiesWithExcludedProperties);
98 auto call_descriptor = Linkage::GetStubCallDescriptor(
99 graph()->zone(), callable.descriptor(), input_count - 1, flags,
100 node->op()->properties());
101 node->InsertInput(graph()->zone(), 0,
102 jsgraph()->HeapConstantNoHole(callable.code()));
103 node->InsertInput(graph()->zone(), 2,
104 jsgraph()->SmiConstant(input_count - 1));
105 NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
106 return Changed(node);
107}
108
110 Node* const value = NodeProperties::GetValueInput(node, 0);
111 Node* const done = NodeProperties::GetValueInput(node, 1);
112 Node* const context = NodeProperties::GetContextInput(node);
113 Node* const effect = NodeProperties::GetEffectInput(node);
114 return Change(node, javascript()->CreateIterResultObject(), value, done,
115 context, effect);
116}
117
119 Node* const frame_state = NodeProperties::GetFrameStateInput(node);
120 Node* const effect = NodeProperties::GetEffectInput(node);
121 Node* const control = NodeProperties::GetControlInput(node);
122
123 Node* deoptimize = graph()->NewNode(
124 common()->Deoptimize(DeoptimizeReason::kDeoptimizeNow, FeedbackSource()),
125 frame_state, effect, control);
126 MergeControlToEnd(graph(), common(), deoptimize);
127
128 node->TrimInputCount(0);
129 NodeProperties::ChangeOp(node, common()->Dead());
130 return Changed(node);
131}
132
134 Node* const closure = NodeProperties::GetValueInput(node, 0);
136 Node* const context = NodeProperties::GetContextInput(node);
137 Node* const effect = NodeProperties::GetEffectInput(node);
138 Node* const control = NodeProperties::GetControlInput(node);
139 Operator const* const op = javascript()->CreateGeneratorObject();
140 Node* create_generator =
141 graph()->NewNode(op, closure, receiver, context, effect, control);
142 ReplaceWithValue(node, create_generator, create_generator);
143 return Changed(create_generator);
144}
145
147 Node* const generator = NodeProperties::GetValueInput(node, 0);
148 Node* const effect = NodeProperties::GetEffectInput(node);
149 Node* const control = NodeProperties::GetControlInput(node);
150 Node* const closed =
152 Node* const undefined = jsgraph()->UndefinedConstant();
153 Operator const* const op = simplified()->StoreField(
155
156 ReplaceWithValue(node, undefined, node);
158 return Change(node, op, generator, closed, effect, control);
159}
160
162 return Change(
163 node, Builtins::CallableFor(isolate(), Builtin::kAsyncFunctionAwait), 0);
164}
165
167 NodeProperties::ChangeOp(node, javascript()->AsyncFunctionEnter());
168 return Changed(node);
169}
170
172 RelaxControls(node);
173 NodeProperties::ChangeOp(node, javascript()->AsyncFunctionReject());
174 return Changed(node);
175}
176
178 RelaxControls(node);
179 NodeProperties::ChangeOp(node, javascript()->AsyncFunctionResolve());
180 return Changed(node);
181}
182
184 return Change(
185 node, Builtins::CallableFor(isolate(), Builtin::kAsyncGeneratorAwait), 0);
186}
187
189 return Change(
190 node, Builtins::CallableFor(isolate(), Builtin::kAsyncGeneratorReject),
191 0);
192}
193
195 return Change(
196 node, Builtins::CallableFor(isolate(), Builtin::kAsyncGeneratorResolve),
197 0);
198}
199
201 return Change(
202 node,
203 Builtins::CallableFor(isolate(), Builtin::kAsyncGeneratorYieldWithAwait),
204 0);
205}
206
208 Node* const generator = NodeProperties::GetValueInput(node, 0);
209 Node* const effect = NodeProperties::GetEffectInput(node);
210 Node* const control = NodeProperties::GetControlInput(node);
211 Operator const* const op =
213
214 return Change(node, op, generator, effect, control);
215}
216
218 Node* node, InstanceType instance_type) {
219 // if (%_IsSmi(value)) {
220 // return false;
221 // } else {
222 // return %_GetInstanceType(%_GetMap(value)) == instance_type;
223 // }
224 Node* value = NodeProperties::GetValueInput(node, 0);
225 Node* effect = NodeProperties::GetEffectInput(node);
226 Node* control = NodeProperties::GetControlInput(node);
227
228 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
229 Node* branch = graph()->NewNode(common()->Branch(), check, control);
230
231 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
232 Node* etrue = effect;
233 Node* vtrue = jsgraph()->FalseConstant();
234
235 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
236 Node* efalse = effect;
237 Node* map = efalse =
238 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), value,
239 efalse, if_false);
240 Node* map_instance_type = efalse = graph()->NewNode(
241 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), map, efalse,
242 if_false);
243 Node* vfalse =
244 graph()->NewNode(simplified()->NumberEqual(), map_instance_type,
245 jsgraph()->ConstantNoHole(instance_type));
246
247 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
248
249 // Replace all effect uses of {node} with the {ephi}.
250 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
251 ReplaceWithValue(node, node, ephi, merge);
252
253 // Turn the {node} into a Phi.
254 return Change(node, common()->Phi(MachineRepresentation::kTagged, 2), vtrue,
255 vfalse, merge);
256}
257
259 return Change(node, simplified()->ObjectIsReceiver());
260}
261
263 if (v8_flags.always_turbofan) {
264 // Ignore static asserts, as we most likely won't have enough information
265 RelaxEffectsAndControls(node);
266 } else {
267 Node* value = NodeProperties::GetValueInput(node, 0);
268 Node* effect = NodeProperties::GetEffectInput(node);
269 Node* assert = graph()->NewNode(
270 common()->StaticAssert("%TurbofanStaticAssert"), value, effect);
271 ReplaceWithValue(node, node, assert, nullptr);
272 }
273 return Changed(jsgraph_->UndefinedConstant());
274}
275
277 Node* value = NodeProperties::GetValueInput(node, 0);
278 Node* effect = NodeProperties::GetEffectInput(node);
279 effect = graph()->NewNode(simplified()->VerifyType(), value, effect);
280 ReplaceWithValue(node, value, effect);
281 return Changed(effect);
282}
283
285 Node* value = node->InputAt(0);
286 if (!v8_flags.turboshaft) {
287 RelaxEffectsAndControls(node);
288 ReplaceWithValue(node, value);
289 return Changed(value);
290 }
291
292 Node* pattern = node->InputAt(1);
293 Node* effect = NodeProperties::GetEffectInput(node);
294 Node* control = NodeProperties::GetControlInput(node);
295 Node* check = graph()->NewNode(simplified()->CheckTurboshaftTypeOf(), value,
296 pattern, effect, control);
297 ReplaceWithValue(node, value, check);
298 return Changed(value);
299}
300
302 RelaxEffectsAndControls(node);
303 return Changed(jsgraph_->FalseConstant());
304}
305
307 // Replace all effect uses of {node} with the effect dependency.
308 RelaxEffectsAndControls(node);
309 // Remove the inputs corresponding to context, effect and control.
311 // Finally update the operator to the new one.
312 NodeProperties::ChangeOp(node, op);
313 return Changed(node);
314}
315
317 NodeProperties::ChangeOp(node, javascript()->ToLength());
318 return Changed(node);
319}
320
322 NodeProperties::ChangeOp(node, javascript()->ToObject());
323 return Changed(node);
324}
325
327 // ToString is unnecessary if the input is a string.
329 if (m.HasResolvedValue() && m.Ref(broker()).IsString()) {
330 ReplaceWithValue(node, m.node());
331 return Replace(m.node());
332 }
334 return Changed(node);
335}
336
338 int const arity =
339 static_cast<int>(CallRuntimeParametersOf(node->op()).arity());
340 static constexpr int kTargetAndReceiver = 2;
342 Node* feedback = jsgraph()->UndefinedConstant();
343 node->InsertInput(graph()->zone(), arity, feedback);
345 node,
346 javascript()->Call(JSCallNode::ArityForArgc(arity - kTargetAndReceiver)));
347 return Changed(node);
348}
349
351 DCHECK(!Linkage::NeedsFrameStateInput(Runtime::kIncBlockCounter));
352 DCHECK(!Linkage::NeedsFrameStateInput(Runtime::kInlineIncBlockCounter));
353 return Change(node,
354 Builtins::CallableFor(isolate(), Builtin::kIncBlockCounter), 0,
356}
357
359 NodeProperties::ChangeOp(node, javascript()->GetImportMeta());
360 return Changed(node);
361}
362
364 Node* b) {
365 RelaxControls(node);
366 node->ReplaceInput(0, a);
367 node->ReplaceInput(1, b);
368 node->TrimInputCount(2);
369 NodeProperties::ChangeOp(node, op);
370 return Changed(node);
371}
372
374 Node* b, Node* c) {
375 RelaxControls(node);
376 node->ReplaceInput(0, a);
377 node->ReplaceInput(1, b);
378 node->ReplaceInput(2, c);
379 node->TrimInputCount(3);
380 NodeProperties::ChangeOp(node, op);
381 return Changed(node);
382}
383
385 Node* b, Node* c, Node* d) {
386 RelaxControls(node);
387 node->ReplaceInput(0, a);
388 node->ReplaceInput(1, b);
389 node->ReplaceInput(2, c);
390 node->ReplaceInput(3, d);
391 node->TrimInputCount(4);
392 NodeProperties::ChangeOp(node, op);
393 return Changed(node);
394}
395
397 int stack_parameter_count,
398 enum FrameStateFlag frame_state_flag) {
399 CallDescriptor::Flags flags = frame_state_flag == kNeedsFrameState
402 auto call_descriptor = Linkage::GetStubCallDescriptor(
403 graph()->zone(), callable.descriptor(), stack_parameter_count, flags,
404 node->op()->properties());
405 node->InsertInput(graph()->zone(), 0,
406 jsgraph()->HeapConstantNoHole(callable.code()));
407 NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
408 return Changed(node);
409}
410
412
414
418
422
426
427} // namespace compiler
428} // namespace internal
429} // namespace v8
JSGraph * jsgraph
static V8_EXPORT_PRIVATE Callable CallableFor(Isolate *isolate, Builtin builtin)
Definition builtins.cc:214
Handle< Code > code() const
Definition callable.h:22
CallInterfaceDescriptor descriptor() const
Definition callable.h:23
static const int kGeneratorClosed
static V8_EXPORT_PRIVATE const Function * FunctionForId(FunctionId id)
Definition runtime.cc:350
static FieldAccess ForMap(WriteBarrierKind write_barrier=kMapWriteBarrier)
static FieldAccess ForJSGeneratorObjectResumeMode()
static FieldAccess ForJSGeneratorObjectContinuation()
static constexpr int ArityForArgc(int parameters)
JSOperatorBuilder * javascript() const
Definition js-graph.h:104
SimplifiedOperatorBuilder * simplified() const
Definition js-graph.h:105
Isolate * isolate() const
Definition js-graph.h:106
Node * ConstantNoHole(ObjectRef ref, JSHeapBroker *broker)
Definition js-graph.cc:51
Reduction Change(Node *node, const Operator *op)
JSIntrinsicLowering(Editor *editor, JSGraph *jsgraph, JSHeapBroker *broker)
Reduction ReduceIsInstanceType(Node *node, InstanceType instance_type)
SimplifiedOperatorBuilder * simplified() const
Reduction ReduceCopyDataPropertiesWithExcludedPropertiesOnStack(Node *node)
static bool NeedsFrameStateInput(Runtime::FunctionId function)
Definition linkage.cc:385
static CallDescriptor * GetStubCallDescriptor(Zone *zone, const CallInterfaceDescriptor &descriptor, int stack_parameter_count, CallDescriptor::Flags flags, Operator::Properties properties=Operator::kNoProperties, StubCallMode stub_mode=StubCallMode::kCallCodeObject)
Definition linkage.cc:587
CommonOperatorBuilder * common() const
static void ChangeOp(Node *node, const Operator *new_op)
static void RemoveNonValueInputs(Node *node)
static Node * GetEffectInput(Node *node, int index=0)
static Node * GetContextInput(Node *node)
static Node * GetFrameStateInput(Node *node)
static Node * GetValueInput(Node *node, int index)
static Node * GetControlInput(Node *node, int index=0)
Node * InputAt(int index) const
Definition node.h:70
const Operator * StoreField(FieldAccess const &, bool maybe_initializing_or_transitioning=true)
const Operator * LoadField(FieldAccess const &)
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
JSHeapBroker *const broker_
JSHeapBroker * broker
TNode< Object > receiver
std::string pattern
int m
Definition mul-fft.cc:294
const CallRuntimeParameters & CallRuntimeParametersOf(const Operator *op)
HeapConstantNoHole(BUILTIN_CODE(isolate(), AllocateInOldGeneration))) DEFINE_GETTER(ArrayConstructorStubConstant
std::string ToString(const BytecodeLivenessState &liveness)
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK(condition)
Definition logging.h:482